1 from enigma import eTimer
2 from enigma import eConsoleAppContainer
3 from enigma import loadPic
5 from Screens.Screen import Screen
6 from Screens.MessageBox import MessageBox
7 from Screens.HelpMenu import HelpableScreen , HelpMenu
9 from Components.Pixmap import Pixmap,MovingPixmap
10 from Components.Label import Label
11 from Components.MenuList import MenuList
12 from Components.ActionMap import ActionMap, NumberActionMap
13 from Components.config import config, ConfigSubsection, ConfigSlider,ConfigInteger,ConfigYesNo, ConfigText
14 from Components.HelpMenuList import HelpMenuList
17 from Tools import Notifications
19 from Plugins.Plugin import PluginDescriptor
21 from StreamPlayer import StreamPlayer
22 from LastFMConfig import LastFMConfigScreen
23 from LastFM import LastFM, lastfm_event_register
30 ###############################################################################
33 ###############################################################################
35 config.plugins.LastFM = ConfigSubsection()
36 config.plugins.LastFM.showcoverart = ConfigYesNo(default = True)
37 config.plugins.LastFM.username = ConfigText("user",fixed_size=False)
38 config.plugins.LastFM.password = ConfigText("passwd",fixed_size=False)
39 config.plugins.LastFM.timeoutstatustext = ConfigInteger(3,limits = (0, 10))
40 config.plugins.LastFM.timeouttabselect = ConfigInteger(2,limits = (0, 10))
41 config.plugins.LastFM.metadatarefreshinterval = ConfigInteger(5,limits = (0, 100))
42 config.plugins.LastFM.recommendedlevel = ConfigInteger(3,limits = (0, 100))
44 config.plugins.LastFM.sreensaver = ConfigSubsection()
45 config.plugins.LastFM.sreensaver.use = ConfigYesNo(default = True)
46 config.plugins.LastFM.sreensaver.wait = ConfigInteger(30,limits = (0, 1000))
47 config.plugins.LastFM.sreensaver.showcoverart = ConfigYesNo(default = True)
48 config.plugins.LastFM.sreensaver.coverartanimation = ConfigYesNo(default = True)
49 config.plugins.LastFM.sreensaver.coverartspeed = ConfigInteger(10,limits = (0, 100))
50 config.plugins.LastFM.sreensaver.coverartinterval = ConfigInteger(10,limits = (0, 100))
52 ###############################################################################
53 def main(session,**kwargs):
54 session.open(LastFMScreenMain)
56 def Plugins(path,**kwargs):
59 return PluginDescriptor(
61 description="the social music revolution",
62 where = PluginDescriptor.WHERE_PLUGINMENU,
65 ###############################################################################
66 class LastFMScreenMain(Screen,HelpableScreen,LastFM):
68 <screen position="110,83" size="530,430" title="Last.FM" >
70 <widget name="artist" position="0,0" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
71 <widget name="album" position="0,40" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
72 <widget name="track" position="0,80" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
74 <widget name="info_artist" position="70,0" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
75 <widget name="info_album" position="70,40" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
76 <widget name="info_track" position="70,80" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
77 <widget name="info_cover" position="414,0" size="116,116" />
79 <widget name="tablist" position="0,120" size="150,260" scrollbarMode="showOnDemand" />
80 <widget name="streamlist" position="150,120" size="380,260" scrollbarMode="showOnDemand" />
82 <widget name="button_red" position="10,400" size="60,30" backgroundColor=\"red\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
83 <widget name="button_green" position="80,400" size="60,30" backgroundColor=\"green\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\"/>
84 <widget name="button_yellow" position="150,400" size="60,30" backgroundColor=\"yellow\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
85 <widget name="button_blue" position="220,400" size="60,30" backgroundColor=\"blue\" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
86 <widget name="infolabel" position="290,400" size="290,30" valign=\"center\" halign=\"center\" zPosition=\"2\" foregroundColor=\"white\" font=\"Regular;18\" />
89 noCoverArtPNG = "/usr/share/enigma2/no_coverArt.png"
91 def __init__(self, session, args = 0):
92 self.skin = LastFMScreenMain.skin
93 Screen.__init__(self, session)
94 HelpableScreen.__init__(self)
96 self.session = session
97 self.streamplayer = StreamPlayer(session)
98 self.streamplayer.onStateChanged.append(self.updateGUI)
99 self.imageconverter = ImageConverter(116,116,self.setCoverArt)
100 Screen.__init__(self, session)
102 self.tabs=[("personal Stations",self.loadPersonalStations)
103 ,("Global Tags",self.loadGlobalTags)
104 ,("Top Tracks",self.loadTopTracks)
105 ,("Recent Tracks",self.loadRecentTracks)
106 ,("Loved Tracks",self.loadLovedTracks)
107 ,("Banned Tracks",self.loadBannedTracks)
108 ,("Friends",self.loadFriends)
109 ,("Neighbours",self.loadNeighbours)
112 for tab in self.tabs:
113 tablist.append((tab[0],tab))
114 self.tablist = MenuList(tablist)
115 self.tablist.onSelectionChanged.append(self.action_TabChanged)
117 self["artist"] = Label(_("Artist")+":")
118 self["album"] = Label(_("Album")+":")
119 self["track"] = Label(_("Track")+":")
121 self["info_artist"] = Label("N/A")
122 self["info_album"] = Label("N/A")
123 self["info_track"] = Label("N/A")
124 self["info_cover"] = Pixmap()
126 self["tablist"] = self.tablist
127 self["streamlist"] = MenuList([])
129 self["button_red"] = Label(_("play"))
130 self["button_green"] = Label(_("skip"))
131 self["button_yellow"] = Label(_("love"))
132 self["button_blue"] = Label(_("ban"))
133 self["infolabel"] = Label("")
135 self["actions"] = ActionMap(["InfobarChannelSelection","WizardActions", "DirectionActions","MenuActions","ShortcutActions","GlobalActions","HelpActions","NumberActions"],
137 "ok": self.action_ok,
138 "back": self.action_exit,
139 "red": self.action_startstop,
143 "historyNext": self.action_nextTab,
144 "historyBack": self.action_prevTab,
146 "menu": self.action_menu,
149 self.helpList.append((self["actions"], "WizardActions", [("ok", _("switch to selected Station"))]))
150 self.helpList.append((self["actions"], "WizardActions", [("back", _("quit Last.FM"))]))
152 self.helpList.append((self["actions"], "MenuActions", [("menu", _("open Configuration"))]))
154 self.helpList.append((self["actions"], "ShortcutActions", [("red", _("start/stop streaming"))]))
155 self.helpList.append((self["actions"], "ShortcutActions", [("green", _("skip current Track"))]))
156 self.helpList.append((self["actions"], "ShortcutActions", [("yellow", _("mark current Track as loved"))]))
157 self.helpList.append((self["actions"], "ShortcutActions", [("blue", _("ban Track, never play again"))]))
158 self.helpList.append((self["actions"], "InfobarChannelSelection", [("historyNext", _("select next Tab"))]))
159 self.helpList.append((self["actions"], "InfobarChannelSelection", [("historyBack", _("select prev Tab"))]))
161 self.onLayoutFinish.append(self.initLastFM)
162 self.onLayoutFinish.append(self.tabchangedtimerFired)
163 self.onLayoutFinish.append(self.setCoverArt)
165 self.guiupdatetimer = eTimer()
166 self.guiupdatetimer.timeout.get().append(self.guiupdatetimerFired)
167 self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
169 self.tabchangetimer = eTimer()
170 self.tabchangetimer.timeout.get().append(self.tabchangedtimerFired)
172 self.infolabelcleartimer = eTimer()
173 self.infolabelcleartimer.timeout.get().append(self.clearInfoLabel)
175 self.screensavertimer = eTimer()
176 self.screensavertimer.timeout.get().append(self.startScreensaver)
177 self.onShown.append(self.startScreensaverTimer)
179 def initLastFM(self):
180 self.setInfoLabel("loggin into last.fm")
181 self.connect(config.plugins.LastFM.username.value,config.plugins.LastFM.password.value)
183 def onConnectSuccessful(self,text):
184 self.setInfoLabel("login successful")
186 def onConnectFailed(self,text):
187 self.setInfoLabel("login failed! "+text,timeout=False)
189 def onTrackSkiped(self,reason):
190 self.setInfoLabel("Track skiped")
192 def onTrackLoved(self,reason):
193 self.setInfoLabel("Track loved")
195 def onTrackBaned(self,reason):
196 self.setInfoLabel("Track baned")
198 def onCommandFailed(self,reason):
199 self.setInfoLabel(reason)
201 def onGlobalTagsLoaded(self,tags):
202 self.setInfoLabel("Global Tags loaded")
203 self.buildMenuList(tags)
205 def onTopTracksLoaded(self,tracks):
206 self.setInfoLabel("Top Tracks loaded")
207 self.buildMenuList(tracks)
209 def onRecentTracksLoaded(self,tracks):
210 self.setInfoLabel("recent Tracks loaded")
211 self.buildMenuList(tracks)
213 def onRecentBannedTracksLoaded(self,tracks):
214 self.setInfoLabel("banned Tracks loaded")
215 self.buildMenuList(tracks)
217 def onRecentLovedTracksLoaded(self,tracks):
218 self.setInfoLabel("loved Tracks loaded")
219 self.buildMenuList(tracks)
221 def onNeighboursLoaded(self,user):
222 self.setInfoLabel("Neighbours loaded")
223 self.buildMenuList(user)
225 def onFriendsLoaded(self,user):
226 self.setInfoLabel("Friends loaded")
227 self.buildMenuList(user)
229 def onStationChanged(self,reason):
230 self.setInfoLabel(reason)
232 def onMetadataLoaded(self,metadata):
234 self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
236 def action_TabChanged(self):
237 self.tabchangetimer.stop()
238 self.tabchangetimer.start(config.plugins.LastFM.timeouttabselect.value*1000)
240 def guiupdatetimerFired(self):
241 if self.streamplayer.is_playing:
243 self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
245 def tabchangedtimerFired(self):
246 self.tablist.getCurrent()[1][1]()
247 self.tabchangetimer.stop()
249 def startScreensaverTimer(self):
250 if config.plugins.LastFM.sreensaver.use.value:
251 self.screensavertimer.start(config.plugins.LastFM.sreensaver.wait.value*1000)
253 def resetScreensaverTimer(self):
254 self.screensavertimer.stop()
255 self.screensavertimer.start(config.plugins.LastFM.sreensaver.wait.value*1000)
257 def startScreensaver(self):
258 self.screensavertimer.stop()
259 self.session.openWithCallback(self.updateGUI, LastFMSaveScreen,self.metadata)
261 def action_nextTab(self):
263 self.resetScreensaverTimer()
265 def action_prevTab(self):
267 self.resetScreensaverTimer()
269 def action_menu(self):
270 self.session.open(LastFMConfigScreen)
271 self.resetScreensaverTimer()
273 def action_exit(self):
274 self.screensavertimer.stop()
275 self.guiupdatetimer.stop()
276 self.streamplayer.stop()
280 x = self["streamlist"].l.getCurrentSelection()
284 self.changeStation(x[1])
285 self.resetScreensaverTimer()
287 def action_startstop(self):
288 self.resetScreensaverTimer()
289 if self.streamplayer.is_playing:
290 self.streamplayer.stop()
292 self.setInfoLabel("stream stopped")
295 self.setInfoLabel("starting stream",timeout=True)
296 if self.info.has_key("stream_url"):
297 self.streamplayer.play(self.info["stream_url"])
298 self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)
300 def setInfoLabel(self,text,timeout=True):
301 self.infolabelcleartimer.stop()
302 self["infolabel"].setText(text)
304 self.infolabelcleartimer.start(config.plugins.LastFM.timeoutstatustext.value*1000)
306 def clearInfoLabel(self):
307 self["infolabel"].setText("")
311 if self.streamplayer.is_playing is True:
312 self["button_red"].setText(_("stop"))
314 self["button_red"].setText(_("play"))
316 if self.streamplayer.is_playing is not True or self.shown is not True:
319 if self.metadata.has_key("station"):
320 self.setTitle("Last.FM: "+self.metadata["station"])
322 self.setTitle("Last.FM")
324 if self.metadata.has_key("artist"):
325 self["info_artist"].setText(self.metadata["artist"])
327 self["info_artist"].setText("N/A")
329 if self.metadata.has_key("album"):
330 self["info_album"].setText(self.metadata["album"])
332 self["info_album"].setText("N/A")
334 if self.metadata.has_key("track"):
335 self["info_track"].setText(self.metadata["track"])
337 self["info_track"].setText("N/A")
339 if self.metadata.has_key("albumcover_large") and config.plugins.LastFM.showcoverart.value:
340 self.imageconverter.convert(self.metadata["albumcover_large"])
341 elif self.metadata.has_key("albumcover_medium") and config.plugins.LastFM.showcoverart.value:
342 self.imageconverter.convert(self.metadata["albumcover_medium"])
343 elif self.metadata.has_key("albumcover_small") and config.plugins.LastFM.showcoverart.value:
344 self.imageconverter.convert(self.metadata["albumcover_small"],self.setCoverArt)
348 if self.streamplayer.is_playing is not True:
349 self.setTitle(myname)
351 self["info_artist"].setText("N/A")
352 self["info_album"].setText("N/A")
353 self["info_track"].setText("N/A")
355 def setCoverArt(self,pixmap=None):
357 self["info_cover"].instance.setPixmapFromFile(self.noCoverArtPNG)
359 self["info_cover"].instance.setPixmap(pixmap.__deref__())
362 def loadPersonalStations(self):
365 x["_display"] = "Personal Radio"
366 x["stationurl"] = self.getPersonalURL(config.plugins.LastFM.username.value,level=config.plugins.LastFM.recommendedlevel.value)
370 x["_display"] = "Neighbours Tracks"
371 x["stationurl"] = self.getNeighboursURL(config.plugins.LastFM.username.value)
375 x["_display"] = "Loved Tracks"
376 x["stationurl"] = self.getLovedURL(config.plugins.LastFM.username.value)
379 if self.metadata.has_key("artist"):
381 x["_display"] = "similar Tracks of current Artist"
382 x["stationurl"] = self.getSimilarArtistsURL()
386 x["_display"] = "Tracks liked by Fans of current Track"
387 x["stationurl"] = self.getArtistsLikedByFans()
391 x["_display"] = "Group of Artist of current Track"
392 x["stationurl"] = self.getArtistGroup()
395 self.buildMenuList(tags)
397 def loadGlobalTags(self):
398 self.setInfoLabel("loading Global Tags")
399 tags = self.getGlobalTags()
401 def loadTopTracks(self):
402 self.setInfoLabel("loading Top Tacks")
403 tracks = self.getTopTracks(config.plugins.LastFM.username.value)
405 def loadRecentTracks(self):
406 self.setInfoLabel("loading recent Tracks")
407 tracks = self.getRecentTracks(config.plugins.LastFM.username.value)
409 def loadLovedTracks(self):
410 self.setInfoLabel("loading loved Tracks")
411 tracks = self.getRecentLovedTracks(config.plugins.LastFM.username.value)
413 def loadBannedTracks(self):
414 self.setInfoLabel("loading loved Tracks")
415 tracks = self.getRecentBannedTracks(config.plugins.LastFM.username.value)
417 def loadNeighbours(self):
418 self.setInfoLabel("loading Neighbours")
419 tracks = self.getNeighbours(config.plugins.LastFM.username.value)
421 def loadFriends(self):
422 self.setInfoLabel("loading Friends")
423 tracks = self.getFriends(config.plugins.LastFM.username.value)
425 def buildMenuList(self,items):
428 menuliste.append((i['_display'],i['stationurl']))
429 self["streamlist"].l.setList(menuliste)
431 class LastFMSaveScreen(Screen):
432 skin = """<screen position="0,0" size="720,576" flags="wfNoBorder" title="LastFMSaveScreen" >
433 <widget name="cover" position="50,50" size="200,200" />
435 noCoverArtPNG = "/usr/share/enigma2/no_coverArt.png"
436 coverartsize= [200,200]
437 def __init__(self,session,initialMetadata):
438 self.skin = """<screen position="0,0" size="720,576" flags="wfNoBorder" title="LastFMSaveScreen" >
439 <widget name="cover" position="50,50" size="%i,%i" />
440 </screen>"""%(self.coverartsize[0],self.coverartsize[1])
442 Screen.__init__(self,session)
443 self.imageconverter = ImageConverter(self.coverartsize[0],self.coverartsize[1],self.setCoverArt)
444 self.session = session
445 self.initialMetadata = initialMetadata
446 self["cover"] = MovingPixmap()
447 self["actions"] = ActionMap(["InfobarChannelSelection","WizardActions", "DirectionActions","MenuActions","ShortcutActions","GlobalActions","HelpActions"],
449 "ok": self.action_exit,
450 "back": self.action_exit,
453 self.onLayoutFinish.append(self.update)
454 self.onLayoutFinish.append(self.registerToMetadataUpdates)
456 if config.plugins.LastFM.sreensaver.coverartanimation.value:
457 self.startmovingtimer = eTimer()
458 self.startmovingtimer.timeout.get().append(self.movePixmap)
459 self.startmovingtimer.start(config.plugins.LastFM.sreensaver.coverartinterval.value*1000)
464 def action_exit(self):
465 lastfm_event_register.removeOnMetadataChanged(self.update)
468 def setCoverArt(self,pixmap=None):
470 self["cover"].instance.setPixmapFromFile(self.noCoverArtPNG)
472 self["cover"].instance.setPixmap(pixmap.__deref__())
474 def registerToMetadataUpdates(self):
475 lastfm_event_register.addOnMetadataChanged(self.update)#added here, to make shure that is called after onLayoutFinished
478 def update(self,metadata=None):
481 metadata = self.initialMetadata
483 if config.plugins.LastFM.sreensaver.showcoverart.value is not True:
485 elif metadata.has_key("albumcover_large") and config.plugins.LastFM.showcoverart.value:
486 self.imageconverter.convert(metadata["albumcover_large"])
487 elif metadata.has_key("albumcover_medium") and config.plugins.LastFM.showcoverart.value:
488 self.imageconverter.convert(metadata["albumcover_medium"])
489 elif metadata.has_key("albumcover_small") and config.plugins.LastFM.showcoverart.value:
490 self.imageconverter.convert(metadata["albumcover_small"],self.setCoverArt)
494 def movePixmap(self):
495 self.startmovingtimer.stop()
496 newX = random.randrange(720-self.coverartsize[0]-1)
497 newY = random.randrange(576-self.coverartsize[1]-1)
498 self["cover"].moveTo(newX, newY, time = config.plugins.LastFM.sreensaver.coverartspeed.value)
499 self["cover"].startMoving()
500 self.startmovingtimer.start(config.plugins.LastFM.sreensaver.coverartinterval.value*1000)
502 class ImageConverter:
506 def __init__(self,width,height,callBack):
507 self.callBack = callBack
510 self.targetfile= "/tmp/coverart"+str(random.randrange(5000))
513 def convert(self,sourceURL):
514 if self.lastURL != sourceURL:
515 extension = sourceURL.split(".")[-1]
516 self.tmpfile = self.targetfile+"."+extension
517 httpclient.getFile(self.tmpfile,sourceURL,callback=self.onImageLoaded)
518 self.lastURL = sourceURL
520 def onImageLoaded(self,dummy):
521 self.currPic = loadPic(self.tmpfile, self.width, self.height, 0,1, 0,1)
522 os.remove(self.tmpfile)
523 self.callBack(pixmap=self.currPic)