- save service names in xml,
[enigma2-plugins.git] / lastfm / src / plugin.py
1 from enigma import eTimer, loadPic
2 from Screens.Screen import Screen
3 from Screens.HelpMenu import HelpableScreen
4 from Components.Pixmap import Pixmap, MovingPixmap
5 from Components.Label import Label
6 from Components.MenuList import MenuList
7 from Components.ActionMap import ActionMap
8 from Components.config import config, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText
9 from Plugins.Plugin import PluginDescriptor
10
11 from StreamPlayer import StreamPlayer
12 from LastFMConfig import LastFMConfigScreen
13 from LastFM import LastFM
14 from twisted.web.client import downloadPage
15 from os import remove as os_remove, system as os_system
16 from random import randrange
17
18 ###############################################################################        
19 plugin_path = ""
20 streamplayer = False
21 ###############################################################################        
22
23 config.plugins.LastFM = ConfigSubsection()
24 config.plugins.LastFM.showcoverart = ConfigYesNo(default = True)
25 config.plugins.LastFM.username = ConfigText("user",fixed_size=False)
26 config.plugins.LastFM.password = ConfigText("passwd",fixed_size=False)
27 config.plugins.LastFM.timeoutstatustext = ConfigInteger(3,limits = (0, 10))
28 config.plugins.LastFM.timeouttabselect = ConfigInteger(2,limits = (0, 10))
29 config.plugins.LastFM.metadatarefreshinterval = ConfigInteger(1,limits = (0, 100))
30 config.plugins.LastFM.recommendedlevel = ConfigInteger(3,limits = (0, 100))
31 config.plugins.LastFM.sendSubmissions = ConfigYesNo(default = False)
32
33 config.plugins.LastFM.useproxy = ConfigYesNo(default = False)
34 config.plugins.LastFM.proxyport = ConfigInteger(6676,limits = (1, 65536))
35
36 config.plugins.LastFM.sreensaver = ConfigSubsection()
37 config.plugins.LastFM.sreensaver.use = ConfigYesNo(default = True)
38 config.plugins.LastFM.sreensaver.wait = ConfigInteger(30,limits = (0, 1000))
39 config.plugins.LastFM.sreensaver.showcoverart = ConfigYesNo(default = True)
40 config.plugins.LastFM.sreensaver.coverartanimation = ConfigYesNo(default = True)
41 config.plugins.LastFM.sreensaver.coverartspeed = ConfigInteger(10,limits = (0, 100))
42 config.plugins.LastFM.sreensaver.coverartinterval = ConfigInteger(10,limits = (0, 100))
43
44 ###############################################################################        
45 try:
46     from LastFMproxyStarter import ProxyStarter
47     global proxy
48     proxy = ProxyStarter()
49 except:
50     proxy = False
51     
52 def main(session,**kwargs):
53     global proxy
54     if proxy is not False:
55         proxy.start()
56         
57     global streamplayer
58     if streamplayer is not False:
59         streamplayer.setSession(session)
60     else:
61         streamplayer = StreamPlayer(session)
62         
63     session.openWithCallback(LastFMScreenMainCB,LastFMScreenMain,streamplayer)    
64
65 def LastFMScreenMainCB():
66     global proxy
67     if proxy is not False:
68         proxy.stop()
69         del proxy
70         proxy = ProxyStarter()
71
72 def startScrobbler(reason, **kwargs):
73     if "session" in kwargs and config.plugins.LastFM.sendSubmissions.value:
74         global streamplayer
75         if streamplayer is False:
76             streamplayer = StreamPlayer(kwargs["session"])
77         else:
78             streamplayer.setSession(kwargs["session"])
79         
80         from scrobbler import EventListener
81         evl = EventListener(kwargs["session"],streamplayer)
82         evl.startListenToEvents()
83         
84 def Plugins(path,**kwargs):
85     global plugin_path
86     plugin_path = path
87     return [PluginDescriptor(
88         name="Last.FM", 
89         description="the social music revolution", 
90         where = PluginDescriptor.WHERE_PLUGINMENU,
91         fnc = main,
92         icon="plugin.png"
93         ),
94         PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = startScrobbler)
95         ]
96 ############################################################################### 
97 class LastFMScreenMain(Screen,HelpableScreen,LastFM):
98     skin = """
99         <screen position="110,83" size="530,430" title="Last.FM" >
100             
101             <widget name="artist" position="0,0" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
102             <widget name="album" position="0,40" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
103             <widget name="track" position="0,80" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
104             
105             <widget name="info_artist" position="70,0" size="284,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
106             <widget name="duration" position="354,0" size="60,30" valign=\"center\" halign=\"right\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
107             <widget name="info_album" position="70,40" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
108             <widget name="info_track" position="70,80" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
109             <widget name="info_cover" position="414,0" size="116,116" />          
110             
111             <widget name="tablist" position="0,120" size="150,260" scrollbarMode="showOnDemand" />            
112             <widget name="streamlist" position="150,120" size="380,260" scrollbarMode="showOnDemand" />            
113             
114             <widget name="button_red" position="10,400" size="60,30" backgroundColor=\"red\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          
115             <widget name="button_green" position="80,400" size="60,30" backgroundColor=\"green\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\"/>            
116             <widget name="button_yellow" position="150,400" size="60,30" backgroundColor=\"yellow\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />            
117             <widget name="button_blue" position="220,400" size="60,30" backgroundColor=\"blue\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />            
118             <widget name="infolabel" position="290,400" size="290,30" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />           
119         </screen>"""
120          
121     noCoverArtPNG = "/usr/share/enigma2/no_coverArt.png"
122     
123     def __init__(self, session,streamplayer, args = 0):
124         self.skin = LastFMScreenMain.skin
125         Screen.__init__(self, session)
126         HelpableScreen.__init__(self)
127         LastFM.__init__(self)
128         self.session = session
129         self.streamplayer = streamplayer#StreamPlayer(session)
130         self.streamplayer.onStateChanged.append(self.onStreamplayerStateChanged)
131         self.imageconverter = ImageConverter(116,116,self.setCoverArt)
132         Screen.__init__(self, session)
133         
134         self.tabs=[("personal Stations",self.loadPersonalStations)
135                    ,("Global Tags",self.loadGlobalTags)
136                    ,("Top Tracks",self.loadTopTracks)
137                    ,("Recent Tracks",self.loadRecentTracks)
138                    ,("Loved Tracks",self.loadLovedTracks)
139                    ,("Banned Tracks",self.loadBannedTracks)
140                    ,("Friends",self.loadFriends)
141                    ,("Neighbours",self.loadNeighbours)
142                    ]
143         tablist =[]
144         for tab in self.tabs:
145             tablist.append((tab[0],tab))
146         self.tablist = MenuList(tablist)
147         self.tablist.onSelectionChanged.append(self.action_TabChanged)
148         
149         self["artist"] = Label(_("Artist")+":")
150         self["duration"] = Label("-00:00")
151         self["album"] = Label(_("Album")+":")
152         self["track"] = Label(_("Track")+":")
153         
154         self["info_artist"] = Label("N/A")
155         self["info_album"] = Label("N/A")
156         self["info_track"] = Label("N/A")
157         self["info_cover"] = Pixmap()
158         
159         self["tablist"] = self.tablist
160         self["streamlist"] = MenuList([])
161         
162         self["button_red"] = Label(_("play"))
163         self["button_green"] = Label(_("skip"))
164         self["button_yellow"] = Label(_("love"))
165         self["button_blue"] = Label(_("ban"))
166         self["infolabel"] = Label("")
167         
168         self["actions"] = ActionMap(["InfobarChannelSelection","WizardActions", "DirectionActions","MenuActions","ShortcutActions","GlobalActions","HelpActions","NumberActions"], 
169             {
170              "ok": self.action_ok,
171              "back": self.action_exit,
172              "red": self.action_startstop,
173              "green": self.skipTrack,
174              "yellow": self.love,
175              "blue": self.banTrack ,
176              "historyNext": self.action_nextTab,
177              "historyBack": self.action_prevTab,
178              
179              "menu": self.action_menu,
180              }, -1)
181         
182         self.helpList.append((self["actions"], "WizardActions", [("ok", _("switch to selected Station"))]))
183         self.helpList.append((self["actions"], "WizardActions", [("back", _("quit Last.FM"))]))
184
185         self.helpList.append((self["actions"], "MenuActions", [("menu", _("open Configuration"))]))
186
187         self.helpList.append((self["actions"], "ShortcutActions", [("red", _("start/stop streaming"))]))
188         self.helpList.append((self["actions"], "ShortcutActions", [("green", _("skip current Track"))]))
189         self.helpList.append((self["actions"], "ShortcutActions", [("yellow", _("mark current Track as loved"))]))
190         self.helpList.append((self["actions"], "ShortcutActions", [("blue", _("ban Track, never play again"))]))
191         self.helpList.append((self["actions"], "InfobarChannelSelection", [("historyNext", _("select next Tab"))]))
192         self.helpList.append((self["actions"], "InfobarChannelSelection", [("historyBack", _("select prev Tab"))]))
193
194         self.onLayoutFinish.append(self.initLastFM)
195         self.onLayoutFinish.append(self.tabchangedtimerFired)
196         self.onLayoutFinish.append(self.setCoverArt)
197         
198         self.guiupdatetimer = eTimer()
199         self.guiupdatetimer.timeout.get().append(self.guiupdatetimerFired)
200         self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
201         
202         self.tabchangetimer = eTimer()
203         self.tabchangetimer.timeout.get().append(self.tabchangedtimerFired)
204         
205         self.infolabelcleartimer = eTimer()
206         self.infolabelcleartimer.timeout.get().append(self.clearInfoLabel)
207
208         self.screensavertimer = eTimer()
209         self.screensavertimer.timeout.get().append(self.startScreensaver)
210         self.onShown.append(self.startScreensaverTimer)
211         
212
213     def initLastFM(self):
214         self.setInfoLabel("loggin into last.fm")
215         self.connect(config.plugins.LastFM.username.value,config.plugins.LastFM.password.value)
216         
217     def onStreamplayerStateChanged(self,reason):
218         if reason is self.streamplayer.STATE_PLAYLISTENDS:
219             self.loadPlaylist()
220         else:
221             pass
222     def onConnectSuccessful(self,text):
223         self.setInfoLabel("login successful")      
224     
225     def onConnectFailed(self,text):
226         self.setInfoLabel("login failed! "+text,timeout=False)
227
228     def onTrackSkiped(self,reason):
229         self.setInfoLabel("Track skiped")
230
231     def onTrackLoved(self,reason):
232         self.setInfoLabel("Track loved")
233     
234     def onTrackBanned(self,reason):
235         self.setInfoLabel("Track baned")
236         
237     
238     def onCommandFailed(self,reason):
239         self.setInfoLabel(reason)
240
241     def onGlobalTagsLoaded(self,tags):
242         self.setInfoLabel("Global Tags loaded")
243         self.buildMenuList(tags)
244
245     def onTopTracksLoaded(self,tracks):
246         self.setInfoLabel("Top Tracks loaded")
247         self.buildMenuList(tracks)
248
249     def onRecentTracksLoaded(self,tracks):
250         self.setInfoLabel("recent Tracks loaded")
251         self.buildMenuList(tracks)
252         
253     def onRecentBannedTracksLoaded(self,tracks):
254         self.setInfoLabel("banned Tracks loaded")
255         self.buildMenuList(tracks)
256
257     def onRecentLovedTracksLoaded(self,tracks):
258         self.setInfoLabel("loved Tracks loaded")
259         self.buildMenuList(tracks)
260
261     def onNeighboursLoaded(self,user):
262         self.setInfoLabel("Neighbours loaded")
263         self.buildMenuList(user)
264
265     def onFriendsLoaded(self,user):
266         self.setInfoLabel("Friends loaded")
267         self.buildMenuList(user)
268     
269     def onStationChanged(self,reason):
270         self.setInfoLabel(reason) 
271         self.loadPlaylist() 
272         
273     def onMetadataLoaded(self,metadata):
274         self.updateGUI()
275         self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
276     
277     def onPlaylistLoaded(self,reason):
278         self.streamplayer.setPlaylist(self.playlist)
279         self.streamplayer.play()
280
281     def skipTrack(self):
282         self.streamplayer.skip()
283         self.updateGUI()
284         
285     def banTrack(self):
286         self.ban()
287         self.streamplayer.skip()
288         self.updateGUI()
289         
290     def action_TabChanged(self):
291         self.tabchangetimer.stop()
292         self.tabchangetimer.start(config.plugins.LastFM.timeouttabselect.value*1000)
293         
294     def guiupdatetimerFired(self):
295         self.updateGUI()
296         self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
297         
298     def tabchangedtimerFired(self):
299         self.tablist.getCurrent()[1][1]()
300         self.tabchangetimer.stop()
301
302     def startScreensaverTimer(self):
303         self.screensavertimer.start(config.plugins.LastFM.sreensaver.wait.value*1000)
304
305     def resetScreensaverTimer(self):
306         self.screensavertimer.stop()
307         self.screensavertimer.start(config.plugins.LastFM.sreensaver.wait.value*1000)
308         
309     def startScreensaver(self):
310         if config.plugins.LastFM.sreensaver.use.value:
311             self.screensavertimer.stop()
312             self.session.openWithCallback(self.updateGUI, LastFMSaveScreen,self)
313            
314     def action_nextTab(self):
315         self.tablist.down()
316         self.resetScreensaverTimer()
317         
318     def action_prevTab(self):
319         self.tablist.up()
320         self.resetScreensaverTimer()
321
322     def action_menu(self):
323         self.session.open(LastFMConfigScreen)
324         self.resetScreensaverTimer()
325
326     def action_exit(self):
327         self.screensavertimer.stop()
328         self.guiupdatetimer.stop()
329         self.streamplayer.stop(force=True)
330         self.streamplayer.onStateChanged=[]
331         
332         self.close()
333
334     def action_ok(self):
335         x = self["streamlist"].l.getCurrentSelection()
336         if x is None:
337             pass
338         elif len(x) >1:
339             self.changeStation(x[1])
340             self.resetScreensaverTimer()
341                 
342     def action_startstop(self):
343         self.resetScreensaverTimer()
344         if self.streamplayer.is_playing:
345             self.streamplayer.stop(force=True)
346             self.setInfoLabel("stream stopped")
347         else:
348             self.setInfoLabel("starting stream",timeout=True)
349             self.loadPlaylist()
350             self.updateGUI() #forcing guiupdate, so we dont wait till guiupdatetimer fired
351             self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
352
353     def setInfoLabel(self,text,timeout=True):
354         self.infolabelcleartimer.stop() 
355         self["infolabel"].setText(text)
356         if timeout is True:
357             self.infolabelcleartimer.start(config.plugins.LastFM.timeoutstatustext.value*1000)
358             
359     def clearInfoLabel(self):
360         self["infolabel"].setText("")
361         
362     def updateGUI(self):
363         if self.streamplayer.is_playing is True:
364             self["duration"].setText(self.streamplayer.getRemaining())
365         else:
366             self["duration"].setText("00:00")
367             
368         
369         if self.streamplayer.is_playing is True:
370             self["button_red"].setText(_("stop"))
371         else:
372             self["button_red"].setText(_("play"))            
373         
374         if self.streamplayer.is_playing is not True or self.shown is not True:
375             return None
376             
377         if self.streamplayer.is_playing is True:
378             self.setTitle("Last.FM: "+self.streamplayer.getMetadata("station"))
379         else:
380             self.setTitle("Last.FM")
381
382         if self.streamplayer.is_playing is True:
383             self["info_artist"].setText(self.streamplayer.getMetadata("creator"))
384         else:
385             self["info_artist"].setText("N/A")
386
387         if self.streamplayer.is_playing is True:
388             self["info_album"].setText(self.streamplayer.getMetadata("album"))
389         else:
390             self["info_album"].setText("N/A")
391
392         if self.streamplayer.is_playing is True:
393             self["info_track"].setText(self.streamplayer.getMetadata("title"))
394         else:
395             self["info_track"].setText("N/A")
396         
397         if self.streamplayer.getMetadata("image").startswith("http") and config.plugins.LastFM.showcoverart.value:
398             self.imageconverter.convert(self.streamplayer.getMetadata("image"))
399         else:
400             self.setCoverArt()
401         
402         if self.streamplayer.is_playing is not True:
403             self.setTitle(myname)
404             self.setCoverArt()
405             self["info_artist"].setText("N/A")
406             self["info_album"].setText("N/A")
407             self["info_track"].setText("N/A")
408         
409     def setCoverArt(self,pixmap=None):
410         if pixmap is None:
411             self["info_cover"].instance.setPixmapFromFile(self.noCoverArtPNG)            
412         else:
413             self["info_cover"].instance.setPixmap(pixmap.__deref__())
414     
415
416     def loadPersonalStations(self):
417         tags = []
418         x= {}
419         x["_display"] = "Personal Radio"
420         x["stationurl"] = self.getPersonalURL(config.plugins.LastFM.username.value,level=config.plugins.LastFM.recommendedlevel.value)
421         tags.append(x)
422         
423         x= {}
424         x["_display"] = "Neighbours Tracks"
425         x["stationurl"] = self.getNeighboursURL(config.plugins.LastFM.username.value)
426         tags.append(x)
427         
428         x= {}
429         x["_display"] = "Loved Tracks"
430         x["stationurl"] = self.getLovedURL(config.plugins.LastFM.username.value)
431         tags.append(x)
432         
433         creator = self.streamplayer.getMetadata("creator")
434         if creator != "no creator" and creator != "N/A":
435             x= {}
436             x["_display"] = "Tracks similar to "+self.streamplayer.getMetadata("creator")
437             x["stationurl"] = self.getSimilarArtistsURL(artist=creator)
438             tags.append(x)
439             
440             x= {}
441             x["_display"] = "Tracks liked by Fans of "+self.streamplayer.getMetadata("creator")
442             x["stationurl"] = self.getArtistsLikedByFans(artist=creator)
443             tags.append(x)
444
445             x= {}
446             x["_display"] = "Group of "+self.streamplayer.getMetadata("creator")
447             x["stationurl"] = self.getArtistGroup(artist=creator)
448             tags.append(x)
449         
450         self.buildMenuList(tags)
451         
452     def loadGlobalTags(self):
453         self.setInfoLabel("loading Global Tags")
454         tags = self.getGlobalTags()
455
456     def loadTopTracks(self):
457         self.setInfoLabel("loading Top Tacks")
458         tracks = self.getTopTracks(config.plugins.LastFM.username.value)
459
460     def loadRecentTracks(self):
461         self.setInfoLabel("loading recent Tracks")
462         tracks = self.getRecentTracks(config.plugins.LastFM.username.value)
463
464     def loadLovedTracks(self):
465         self.setInfoLabel("loading loved Tracks")
466         tracks = self.getRecentLovedTracks(config.plugins.LastFM.username.value)
467
468     def loadBannedTracks(self):
469         self.setInfoLabel("loading loved Tracks")
470         tracks = self.getRecentBannedTracks(config.plugins.LastFM.username.value)
471         
472     def loadNeighbours(self):
473         self.setInfoLabel("loading Neighbours")
474         tracks = self.getNeighbours(config.plugins.LastFM.username.value)
475
476     def loadFriends(self):
477         self.setInfoLabel("loading Friends")
478         tracks = self.getFriends(config.plugins.LastFM.username.value)
479
480     def buildMenuList(self,items):
481         menuliste = []
482         for i in items:
483             menuliste.append((i['_display'],i['stationurl']))
484         self["streamlist"].l.setList(menuliste) 
485
486 class LastFMSaveScreen(Screen):
487     skin = """<screen position="0,0" size="720,576" flags="wfNoBorder" title="LastFMSaveScreen" >
488                 <widget name="cover" position="50,50" size="200,200" />          
489               </screen>"""
490     noCoverArtPNG = "/usr/share/enigma2/no_coverArt.png"
491     coverartsize= [200,200]
492     lastcreator=""
493     def __init__(self,session,parent):
494         self.skin = """<screen position="0,0" size="720,576" flags="wfNoBorder" title="LastFMSaveScreen" >
495                 <widget name="cover" position="50,50" size="%i,%i" />          
496               </screen>"""%(self.coverartsize[0],self.coverartsize[1])
497     
498         Screen.__init__(self,session)
499         self.imageconverter = ImageConverter(self.coverartsize[0],self.coverartsize[1],self.setCoverArt)
500         self.session = session
501         self.streamplayer = parent.streamplayer
502         self.parent = parent
503         self["cover"] = MovingPixmap()
504                         
505         self["actions"] = ActionMap(["InfobarChannelSelection","WizardActions", "DirectionActions","MenuActions","ShortcutActions","GlobalActions","HelpActions"], 
506             {
507              "ok": self.action_exit,
508              "back": self.action_exit,
509                          "red": self.parent.action_startstop,
510              "green": self.parent.skipTrack,
511              "yellow": self.parent.love,
512              "blue": self.parent.banTrack ,
513              }, -1)
514         
515         self.onLayoutFinish.append(self.update)
516         self.updatetimer = eTimer()
517         self.updatetimer.timeout.get().append(self.update)
518         self.updatetimer.start(1000)
519             
520         if config.plugins.LastFM.sreensaver.coverartanimation.value:
521             self.startmovingtimer = eTimer()
522             self.startmovingtimer.timeout.get().append(self.movePixmap)
523             self.startmovingtimer.start(config.plugins.LastFM.sreensaver.coverartinterval.value*1000)
524         
525     def action_ok(self):
526         pass
527     
528     def action_exit(self):
529         self.close()
530         
531     def setCoverArt(self,pixmap=None):
532         if pixmap is None:
533             self["cover"].instance.setPixmapFromFile(self.noCoverArtPNG)            
534         else:
535             self["cover"].instance.setPixmap(pixmap.__deref__())        
536     
537     def update(self):
538         if self.streamplayer.getMetadata("creator") == self.lastcreator:
539             pass
540         else:
541             self.lastcreator = self.streamplayer.getMetadata("creator")
542             if config.plugins.LastFM.sreensaver.showcoverart.value is not True:
543                 pass#do nothing
544             elif self.streamplayer.getMetadata("image").startswith("http") and config.plugins.LastFM.showcoverart.value:
545                 self.imageconverter.convert(self.streamplayer.getMetadata("image"))
546             else:
547                 self.setCoverArt()
548         self.updatetimer.start(1000)
549         
550     def movePixmap(self):
551         self.startmovingtimer.stop() 
552         newX = randrange(720-self.coverartsize[0]-1)
553         newY = randrange(576-self.coverartsize[1]-1)
554         self["cover"].moveTo(newX, newY, time = config.plugins.LastFM.sreensaver.coverartspeed.value)
555         self["cover"].startMoving()
556         self.startmovingtimer.start(config.plugins.LastFM.sreensaver.coverartinterval.value*1000)
557
558 class ImageConverter:
559     
560     lastURL = ""
561
562     def __init__(self,width,height,callBack):
563         self.callBack = callBack
564         self.width = width
565         self.height = height
566         self.targetfile= "/tmp/coverart"+str(randrange(5000))
567     
568         
569     def convert(self,sourceURL):
570         if self.lastURL != sourceURL:
571             extension = sourceURL.split(".")[-1]
572             self.tmpfile = self.targetfile+"."+extension
573             downloadPage(sourceURL,self.tmpfile).addCallback(self.onImageLoaded)
574             self.lastURL = sourceURL
575
576     def onImageLoaded(self,dummy):
577             self.currPic = loadPic(self.tmpfile, self.width, self.height, 0,1, 0,1)
578             os_remove(self.tmpfile)
579             self.callBack(pixmap=self.currPic)
580