home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / rhythmbox / plugins / lyrics.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-30  |  9.8 KB  |  270 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. import os
  5. import gtk
  6. import gobject
  7. import urllib
  8. import re
  9. from xml.dom import minidom
  10. from gettext import gettext as _
  11. import rb
  12. import rhythmdb
  13. from Loader import Loader
  14. ui_str = '\n<ui>\n  <menubar name="MenuBar">\n    <menu name="ViewMenu" action="View">\n      <menuitem name="ViewSongLyrics" action="ViewSongLyrics"/>\n    </menu>\n  </menubar>\n</ui>\n'
  15. LYRICS_FOLDER = '~/.gnome2/rhythmbox/lyrics'
  16. LYRIC_TITLE_STRIP = [
  17.     '\\(live[^\\)]*\\)',
  18.     '\\(acoustic[^\\)]*\\)',
  19.     '\\([^\\)]*mix\\)',
  20.     '\\([^\\)]*version\\)',
  21.     '\\([^\\)]*edit\\)',
  22.     '\\(feat[^\\)]*\\)']
  23. LYRIC_TITLE_REPLACE = [
  24.     ('/', '-'),
  25.     ('&', 'and')]
  26. LYRIC_ARTIST_REPLACE = [
  27.     ('/', '-'),
  28.     ('&', 'and')]
  29.  
  30. def create_lyrics_view():
  31.     view = gtk.TextView()
  32.     view.set_wrap_mode(gtk.WRAP_WORD)
  33.     view.set_editable(False)
  34.     sw = gtk.ScrolledWindow()
  35.     sw.add(view)
  36.     sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  37.     sw.set_shadow_type(gtk.SHADOW_IN)
  38.     vbox = gtk.VBox(spacing = 12)
  39.     vbox.pack_start(sw, expand = True)
  40.     return (vbox, view.get_buffer())
  41.  
  42.  
  43. class LyricWindow(gtk.Window):
  44.     
  45.     def __init__(self, db, entry):
  46.         gtk.Window.__init__(self)
  47.         self.set_border_width(12)
  48.         title = db.entry_get(entry, rhythmdb.PROP_TITLE)
  49.         artist = db.entry_get(entry, rhythmdb.PROP_ARTIST)
  50.         self.set_title(title + ' - ' + artist + ' - Lyrics')
  51.         close = gtk.Button(stock = gtk.STOCK_CLOSE)
  52.         close.connect('clicked', (lambda w: self.destroy()))
  53.         (lyrics_view, buffer) = create_lyrics_view()
  54.         self.buffer = buffer
  55.         bbox = gtk.HButtonBox()
  56.         bbox.set_layout(gtk.BUTTONBOX_END)
  57.         bbox.pack_start(close)
  58.         lyrics_view.pack_start(bbox, expand = False)
  59.         self.buffer.set_text(_('Searching for lyrics...'))
  60.         self.add(lyrics_view)
  61.         self.set_default_size(400, 300)
  62.         self.show_all()
  63.  
  64.  
  65.  
  66. class LyricPane(object):
  67.     
  68.     def __init__(self, db, song_info):
  69.         (self.view, self.buffer) = create_lyrics_view()
  70.         self.view.show_all()
  71.         self.page_num = song_info.append_page(_('Lyrics'), self.view)
  72.         self.db = db
  73.         self.song_info = song_info
  74.         self.have_lyrics = 0
  75.         self.visible = 0
  76.         self.entry = self.song_info.get_property('current-entry')
  77.         self.entry_change_id = song_info.connect('notify::current-entry', self.entry_changed)
  78.         nb = self.view.get_parent()
  79.         self.switch_page_id = nb.connect('switch-page', self.switch_page_cb)
  80.  
  81.     
  82.     def entry_changed(self, pspec, duh):
  83.         self.entry = self.song_info.get_property('current-entry')
  84.         self.have_lyrics = 0
  85.         if self.visible != 0:
  86.             self.get_lyrics()
  87.         
  88.  
  89.     
  90.     def switch_page_cb(self, notebook, page, page_num):
  91.         if self.have_lyrics != 0:
  92.             return None
  93.         
  94.         if page_num != self.page_num:
  95.             self.visible = 0
  96.             return None
  97.         
  98.         self.visible = 1
  99.         self.get_lyrics()
  100.  
  101.     
  102.     def get_lyrics(self):
  103.         if self.entry is None:
  104.             return None
  105.         
  106.         self.buffer.set_text(_('Searching for lyrics...'))
  107.         lyrics_grabber = LyricGrabber()
  108.         lyrics_grabber.get_lyrics(self.db, self.entry, self.buffer.set_text)
  109.  
  110.  
  111.  
  112. class LyricGrabber(object):
  113.     
  114.     def __init__(self):
  115.         self.loader = Loader()
  116.  
  117.     
  118.     def _build_cache_path(self, artist, title):
  119.         lyrics_folder = os.path.expanduser(LYRICS_FOLDER)
  120.         if not os.path.exists(lyrics_folder):
  121.             os.mkdir(lyrics_folder)
  122.         
  123.         return lyrics_folder + '/%s - %s.txt' % (artist, title)
  124.  
  125.     
  126.     def get_lyrics(self, db, entry, callback):
  127.         self.callback = callback
  128.         artist = db.entry_get(entry, rhythmdb.PROP_ARTIST).lower()
  129.         title = db.entry_get(entry, rhythmdb.PROP_TITLE).lower()
  130.         for exp in LYRIC_ARTIST_REPLACE:
  131.             p = re.compile(exp[0])
  132.             artist = p.sub(exp[1], artist)
  133.         
  134.         for exp in LYRIC_TITLE_REPLACE:
  135.             p = re.compile(exp[0])
  136.             title = p.sub(exp[1], title)
  137.         
  138.         for exp in LYRIC_TITLE_STRIP:
  139.             p = re.compile(exp)
  140.             title = p.sub('', title)
  141.         
  142.         title = title.strip()
  143.         artist = artist.strip()
  144.         self.cache_path = self._build_cache_path(artist, title)
  145.         if os.path.exists(self.cache_path):
  146.             self.loader.get_url(self.cache_path, callback)
  147.             return None
  148.         
  149.         url = 'http://api.leoslyrics.com/api_search.php?auth=Rhythmbox&artist=%s&songtitle=%s' % (urllib.quote(artist.encode('utf-8')), urllib.quote(title.encode('utf-8')))
  150.         self.loader.get_url(url, self.search_results)
  151.  
  152.     
  153.     def search_results(self, data):
  154.         if data is None:
  155.             self.callback('Server did not respond.')
  156.             return None
  157.         
  158.         
  159.         try:
  160.             xmldoc = minidom.parseString(data).documentElement
  161.         except:
  162.             self.callback("Couldn't parse search results.")
  163.             return None
  164.  
  165.         result_code = xmldoc.getElementsByTagName('response')[0].getAttribute('code')
  166.         if result_code != '0':
  167.             self.callback('Server is busy, try again later.')
  168.             xmldoc.unlink()
  169.             return None
  170.         
  171.         matches = xmldoc.getElementsByTagName('result')[:10]
  172.         hids = map((lambda x: x.getAttribute('hid')), matches)
  173.         if len(hids) == 0:
  174.             self.callback('Unable to find lyrics for this track.')
  175.             xmldoc.unlink()
  176.             return None
  177.         
  178.         xmldoc.unlink()
  179.         url = 'http://api.leoslyrics.com/api_lyrics.php?auth=Rhythmbox&hid=%s' % urllib.quote(hids[0].encode('utf-8'))
  180.         self.loader.get_url(url, self.lyrics)
  181.  
  182.     
  183.     def lyrics(self, data):
  184.         if data is None:
  185.             self.callback('Unable to find lyrics for this track.')
  186.             return None
  187.         
  188.         
  189.         try:
  190.             xmldoc = minidom.parseString(data).documentElement
  191.         except:
  192.             self.callback('Unable to parse the lyrics returned.')
  193.             return None
  194.  
  195.         text = xmldoc.getElementsByTagName('title')[0].firstChild.nodeValue
  196.         text += ' - ' + xmldoc.getElementsByTagName('artist')[0].getElementsByTagName('name')[0].firstChild.nodeValue + '\n\n'
  197.         text += xmldoc.getElementsByTagName('text')[0].firstChild.nodeValue
  198.         xmldoc.unlink()
  199.         text += '\n\n' + _('Lyrics provided by leoslyrics.com')
  200.         f = file(self.cache_path, 'w')
  201.         f.write(text)
  202.         f.close()
  203.         self.callback(text)
  204.  
  205.  
  206.  
  207. class LyricsDisplayPlugin(rb.Plugin):
  208.     
  209.     def __init__(self):
  210.         rb.Plugin.__init__(self)
  211.         self.window = None
  212.  
  213.     
  214.     def activate(self, shell):
  215.         self.action = gtk.Action('ViewSongLyrics', _('Song L_yrics'), _('Display lyrics for the playing song'), 'rb-song-lyrics')
  216.         self.activate_id = self.action.connect('activate', self.show_song_lyrics, shell)
  217.         self.action_group = gtk.ActionGroup('SongLyricsPluginActions')
  218.         self.action_group.add_action(self.action)
  219.         uim = shell.get_ui_manager()
  220.         uim.insert_action_group(self.action_group, 0)
  221.         self.ui_id = uim.add_ui_from_string(ui_str)
  222.         uim.ensure_update()
  223.         sp = shell.get_player()
  224.         self.pec_id = sp.connect('playing-song-changed', self.playing_entry_changed)
  225.         self.playing_entry_changed(sp, sp.get_playing_entry())
  226.         self.csi_id = shell.connect('create_song_info', self.create_song_info)
  227.  
  228.     
  229.     def deactivate(self, shell):
  230.         uim = shell.get_ui_manager()
  231.         uim.remove_ui(self.ui_id)
  232.         uim.remove_action_group(self.action_group)
  233.         self.action_group = None
  234.         self.action = None
  235.         sp = shell.get_player()
  236.         sp.disconnect(self.pec_id)
  237.         if self.window is not None:
  238.             self.window.destroy()
  239.         
  240.  
  241.     
  242.     def playing_entry_changed(self, sp, entry):
  243.         if entry is not None:
  244.             self.action.set_sensitive(True)
  245.         else:
  246.             self.action.set_sensitive(False)
  247.  
  248.     
  249.     def show_song_lyrics(self, action, shell):
  250.         if self.window is not None:
  251.             self.window.destroy()
  252.         
  253.         db = shell.get_property('db')
  254.         sp = shell.get_player()
  255.         entry = sp.get_playing_entry()
  256.         if entry is None:
  257.             return None
  258.         
  259.         self.window = LyricWindow(db, entry)
  260.         lyrics_grabber = LyricGrabber()
  261.         lyrics_grabber.get_lyrics(db, entry, self.window.buffer.set_text)
  262.  
  263.     
  264.     def create_song_info(self, shell, song_info, is_multiple):
  265.         if is_multiple is False:
  266.             x = LyricPane(shell.get_property('db'), song_info)
  267.         
  268.  
  269.  
  270.