Move expand_tags for musicdir from winMain to nephilim_app.
[nephilim.git] / nephilim / plugins / Lyrics.py
blob02d6a3c8f6f73fc807d6e22989ca3ad6d538c686
2 # Copyright (C) 2009 Anton Khirnov <wyskas@gmail.com>
4 # Nephilim is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # Nephilim is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Nephilim. If not, see <http://www.gnu.org/licenses/>.
18 from PyQt4 import QtGui,QtCore
19 from PyQt4.QtCore import QVariant
21 import socket
23 from ..plugin import Plugin
24 from .. import misc
26 _available_sites = []
27 try:
28 import LyricWiki_client
29 _available_sites.append('lyricwiki')
30 except ImportError:
31 pass
33 class wgLyrics(QtGui.QWidget):
34 txtView = None # text-object
35 p = None # plugin
36 logger = None
37 def __init__(self, p, parent=None):
38 QtGui.QWidget.__init__(self, parent)
39 self.p = p
40 self.logger = p.logger
41 self.curLyrics = ''
43 self.txtView = QtGui.QTextEdit(self)
44 self.txtView.setReadOnly(True)
46 self.setLayout(QtGui.QVBoxLayout())
47 self.layout().setSpacing(0)
48 self.layout().setMargin(0)
49 self.layout().addWidget(self.txtView)
51 self.connect(self.p, QtCore.SIGNAL('new_lyrics_fetched'), self.set_lyrics)
53 def set_lyrics(self, song, lyrics):
54 if not song:
55 return self.txtView.clear()
57 if song != self.p.mpclient().current_song():
58 return
60 self.txtView.clear()
61 if song:
62 self.txtView.insertHtml('<b>%s</b>\n<br /><u>%s</u><br />'\
63 '<br />\n\n'%(song.title(), song.artist()))
64 else:
65 return
67 if lyrics:
68 self.logger.info('Setting new lyrics.')
69 self.txtView.insertPlainText(lyrics)
70 else:
71 self.logger.info('Lyrics not found.')
72 self.txtView.insertPlainText('Lyrics not found.')
74 class Lyrics(Plugin):
75 o = None
76 sites = []
77 lyrics_dir = None
78 lyrics_path = None
79 DEFAULTS = {'sites' : ['lyricwiki'], 'lyricdir' : '$musicdir/$songdir',
80 'lyricname' : '.lyrics_nephilim_$artist_$album_$title', 'store' : True}
82 def _load(self):
83 self.o = wgLyrics(self)
84 for site in _available_sites:
85 if site in self.settings().value('%s/sites'%self.name()).toStringList():
86 self.sites.append(site)
87 self.connect(self.mpclient(), QtCore.SIGNAL('song_changed'), self.refresh)
88 def _unload(self):
89 self.o = None
90 self.sites = []
91 self.disconnect(self.mpclient(), QtCore.SIGNAL('song_changed'), self.refresh)
92 def info(self):
93 return "Show (and fetch) the lyrics of the currently playing song."
95 def _get_dock_widget(self):
96 return self._create_dock(self.o)
98 class FetchThread(QtCore.QThread):
99 def __init__(self, parent, fetch_func, song):
100 QtCore.QThread.__init__(self)
101 self.setParent(parent)
102 self.fetch_func = fetch_func
103 self.song = song
104 def run(self):
105 self.fetch_func(self.song)
107 def refresh(self):
108 self.logger.info('Autorefreshing lyrics.')
109 song = self.mpclient().current_song()
110 if not song:
111 return self.o.set_lyrics(None, None)
113 (self.lyrics_dir, self.lyrics_path) = misc.generate_metadata_path(song,
114 self.settings().value(self.name() + '/lyricdir').toString(),
115 self.settings().value(self.name() + '/lyricname').toString())
116 try:
117 self.logger.info('Trying to read lyrics from file %s.'%self.lyrics_path)
118 file = open(self.lyrics_path, 'r')
119 lyrics = file.read().decode('utf-8')
120 file.close()
121 if lyrics:
122 return self.emit(QtCore.SIGNAL('new_lyrics_fetched'), song, lyrics)
123 except IOError, e:
124 self.logger.info('Error reading lyrics file: %s.'%e)
127 thread = self.FetchThread(self, self._fetch_lyrics, song)
128 thread.start()
130 def _fetch_lyrics(self, song):
131 self.logger.info('Trying to download lyrics from internet.')
132 lyrics = None
133 for site in self.sites:
134 self.logger.info('Trying %s.'%site)
135 lyrics = eval('self.fetch_%s(song)'%site)
136 if lyrics:
137 try:
138 file = open(self.lyrics_path, 'w')
139 file.write(lyrics.encode('utf-8'))
140 file.close()
141 except IOError, e:
142 self.logger.error('Error saving lyrics: %s'%e)
143 return self.emit(QtCore.SIGNAL('new_lyrics_fetched'), song, lyrics)
145 self.emit(QtCore.SIGNAL('new_lyrics_fetched'), song, None)
147 def fetch_lyricwiki(self, song):
148 soap = LyricWiki_client.LyricWikiBindingSOAP("http://lyricwiki.org/server.php")
149 req = LyricWiki_client.getSongRequest()
150 req.Artist = song.artist().encode('utf-8').decode('iso8859').encode('utf-8')
151 req.Song = song.title().encode('utf-8').decode('iso8859').encode('utf-8')
152 try:
153 result = soap.getSong(req).Return.Lyrics.decode('utf-8').encode('iso8859').decode('utf-8')
154 except socket.error, e:
155 self.logger.error('Error downloading lyrics from LyricWiki: %s.'%e)
156 return None
158 return result if result != 'Not found' else None
160 class SettingsWidgetLyrics(Plugin.SettingsWidget):
161 lyricdir = None
162 lyricname = None
163 store = None
165 def __init__(self, plugin):
166 Plugin.SettingsWidget.__init__(self, plugin)
167 self.settings().beginGroup(self.plugin.name())
170 # store lyrics groupbox
171 self.store = QtGui.QGroupBox('Store lyrics.')
172 self.store.setToolTip('Should %s store its own copy of lyrics?'%misc.APPNAME)
173 self.store.setCheckable(True)
174 self.store.setChecked(self.settings().value('store').toBool())
175 self.store.setLayout(QtGui.QGridLayout())
177 # paths to lyrics
178 self.lyricdir = QtGui.QLineEdit(self.settings().value('lyricdir').toString())
179 self.lyricdir.setToolTip('Where should %s store lyrics.\n'
180 '$musicdir will be expanded to path to MPD music library (as set by user)\n'
181 '$songdir will be expanded to path to the song (relative to $musicdir\n'
182 'other tags same as in lyricname'
183 %misc.APPNAME)
184 self.lyricname = QtGui.QLineEdit(self.settings().value('lyricname').toString())
185 self.lyricname.setToolTip('Filename for %s lyricsfiles.\n'
186 'All tags supported by MPD will be expanded to their\n'
187 'values for current song, e.g. $title, $track, $artist,\n'
188 '$album, $genre etc.'%misc.APPNAME)
189 self.store.layout().addWidget(QtGui.QLabel('Lyrics directory'), 0, 0)
190 self.store.layout().addWidget(self.lyricdir, 0, 1)
191 self.store.layout().addWidget(QtGui.QLabel('Lyrics filename'), 1, 0)
192 self.store.layout().addWidget(self.lyricname, 1, 1)
194 self.setLayout(QtGui.QVBoxLayout())
195 self.layout().addWidget(self.store)
197 self.settings().endGroup()
199 def save_settings(self):
200 self.settings().beginGroup(self.plugin.name())
201 self.settings().setValue('lyricdir', QVariant(self.lyricdir.text()))
202 self.settings().setValue('lyricname', QVariant(self.lyricname.text()))
203 self.settings().setValue('store', QVariant(self.store.isChecked()))
204 self.settings().endGroup()
205 self.plugin.refresh()
207 def get_settings_widget(self):
208 return self.SettingsWidgetLyrics(self)