following changes in httpclient
[enigma2-plugins.git] / lastfm / src / plugin.py
1 from enigma import eTimer\r
2 from enigma import eConsoleAppContainer\r
3 from enigma import loadPic\r
4 \r
5 from Screens.Screen import Screen\r
6 from Screens.MessageBox import MessageBox\r
7 from Screens.HelpMenu import HelpableScreen , HelpMenu              \r
8 \r
9 from Components.Pixmap import Pixmap\r
10 from Components.Label import Label\r
11 from Components.MenuList import MenuList\r
12 from Components.ActionMap import ActionMap, NumberActionMap\r
13 from Components.config import config, ConfigSubsection, ConfigSlider,ConfigInteger,ConfigYesNo, ConfigText\r
14 from Components.HelpMenuList import HelpMenuList\r
15 \r
16 \r
17 from Tools import Notifications\r
18 \r
19 from Plugins.Plugin import PluginDescriptor\r
20 \r
21 from StreamPlayer import StreamPlayer\r
22 from LastFMConfig import LastFMConfigScreen\r
23 from LastFM import LastFM\r
24 \r
25 import os\r
26 import urllib\r
27 ###############################################################################        \r
28 plugin_path = ""\r
29 \r
30 ###############################################################################        \r
31 \r
32 config.plugins.LastFM = ConfigSubsection()\r
33 config.plugins.LastFM.showcoverart = ConfigYesNo(default = False)\r
34 config.plugins.LastFM.username = ConfigText("user",fixed_size=False)\r
35 config.plugins.LastFM.password = ConfigText("passwd",fixed_size=False)\r
36 config.plugins.LastFM.timeoutstatustext = ConfigInteger(3,limits = (0, 10))\r
37 config.plugins.LastFM.timeouttabselect = ConfigInteger(2,limits = (0, 10))\r
38 config.plugins.LastFM.metadatarefreshinterval = ConfigInteger(5,limits = (0, 100))\r
39 config.plugins.LastFM.recommendedlevel = ConfigInteger(3,limits = (0, 100))\r
40 \r
41 ###############################################################################        \r
42 def main(session,**kwargs):\r
43     session.open(LastFMScreenMain)    \r
44         \r
45 def Plugins(path,**kwargs):\r
46     global plugin_path\r
47     plugin_path = path\r
48     return PluginDescriptor(\r
49         name="Last.FM", \r
50         description="the social music revolution", \r
51         where = PluginDescriptor.WHERE_PLUGINMENU,\r
52         fnc = main\r
53         )\r
54 ############################################################################### \r
55 class LastFMScreenMain(Screen,HelpableScreen,LastFM):\r
56     skin = """\r
57         <screen position="110,83" size="530,430" title="Last.FM" >\r
58             \r
59             <widget name="artist" position="0,0" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
60             <widget name="album" position="0,40" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
61             <widget name="track" position="0,80" size="70,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
62             \r
63             <widget name="info_artist" position="70,0" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
64             <widget name="info_album" position="70,40" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
65             <widget name="info_track" position="70,80" size="344,30" valign=\"center\" halign=\"left\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
66             <widget name="info_cover" position="414,0" size="116,116" />          \r
67             \r
68             <widget name="tablist" position="0,120" size="150,260" scrollbarMode="showOnDemand" />            \r
69             <widget name="streamlist" position="150,120" size="380,260" scrollbarMode="showOnDemand" />            \r
70             \r
71             <widget name="button_red" position="10,400" size="60,30" backgroundColor=\"red\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />          \r
72             <widget name="button_green" position="80,400" size="60,30" backgroundColor=\"green\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\"/>            \r
73             <widget name="button_yellow" position="150,400" size="60,30" backgroundColor=\"yellow\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />            \r
74             <widget name="button_blue" position="220,400" size="60,30" backgroundColor=\"blue\" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />            \r
75             <widget name="infolabel" position="290,400" size="290,30" valign=\"center\" halign=\"center\" zPosition=\"2\"  foregroundColor=\"white\" font=\"Regular;18\" />           \r
76         </screen>"""\r
77          \r
78     noCoverArtPNG = "/usr/share/enigma2/no_coverArt.png"\r
79     \r
80     def __init__(self, session, args = 0):\r
81         self.skin = LastFMScreenMain.skin\r
82         Screen.__init__(self, session)\r
83         HelpableScreen.__init__(self)\r
84         LastFM.__init__(self)\r
85         self.session = session\r
86         self.streamplayer = StreamPlayer(session)\r
87         self.imageconverter = ImageConverter(self.setCoverArt)\r
88         Screen.__init__(self, session)\r
89         self.tabs=[("personal Stations",self.loadPersonalStations)\r
90                    ,("Global Tags",self.loadGlobalTags)\r
91                    ,("Top Tracks",self.loadTopTracks)\r
92                    ,("Recent Tracks",self.loadRecentTracks)\r
93                    ,("Loved Tracks",self.loadLovedTracks)\r
94                    ,("Banned Tracks",self.loadBannedTracks)\r
95                    ,("Friends",self.loadFriends)\r
96                    ,("Neighbours",self.loadNeighbours)\r
97                    ]\r
98         tablist =[]\r
99         for tab in self.tabs:\r
100             tablist.append((tab[0],tab))\r
101         self.tablist = MenuList(tablist)\r
102         self.tablist.onSelectionChanged.append(self.action_TabChanged)\r
103         \r
104         self["artist"] = Label(_("Artist")+":")\r
105         self["album"] = Label(_("Album")+":")\r
106         self["track"] = Label(_("Track")+":")\r
107         \r
108         self["info_artist"] = Label("N/A")\r
109         self["info_album"] = Label("N/A")\r
110         self["info_track"] = Label("N/A")\r
111         self["info_cover"] = Pixmap()\r
112         \r
113         self["tablist"] = self.tablist\r
114         self["streamlist"] = MenuList([])\r
115         \r
116         self["button_red"] = Label(_("play"))\r
117         self["button_green"] = Label(_("skip"))\r
118         self["button_yellow"] = Label(_("love"))\r
119         self["button_blue"] = Label(_("ban"))\r
120         self["infolabel"] = Label("")\r
121         \r
122         self["actions"] = ActionMap(["InfobarChannelSelection","WizardActions", "DirectionActions","MenuActions","ShortcutActions","GlobalActions","HelpActions"], \r
123             {\r
124              "ok": self.action_ok,\r
125              "back": self.action_exit,\r
126              "red": self.action_startstop,\r
127              "green": self.skip,\r
128              "yellow": self.love,\r
129              "blue": self.ban ,\r
130              "historyNext": self.action_nextTab,\r
131              "historyBack": self.action_prevTab,\r
132              \r
133              "menu": self.action_menu,\r
134              }, -1)\r
135         self.helpList.append((self["actions"], "WizardActions", [("ok", _("switch to selected Station"))]))\r
136         self.helpList.append((self["actions"], "WizardActions", [("back", _("quit Last.FM"))]))\r
137 \r
138         self.helpList.append((self["actions"], "MenuActions", [("menu", _("open Configuration"))]))\r
139 \r
140         self.helpList.append((self["actions"], "ShortcutActions", [("red", _("start/stop streaming"))]))\r
141         self.helpList.append((self["actions"], "ShortcutActions", [("green", _("skip current Track"))]))\r
142         self.helpList.append((self["actions"], "ShortcutActions", [("yellow", _("mark current Track as loved"))]))\r
143         self.helpList.append((self["actions"], "ShortcutActions", [("blue", _("ban Track, never play again"))]))\r
144         self.helpList.append((self["actions"], "InfobarChannelSelection", [("historyNext", _("select next Tab"))]))\r
145         self.helpList.append((self["actions"], "InfobarChannelSelection", [("historyBack", _("select prev Tab"))]))\r
146 \r
147         self.onLayoutFinish.append(self.initLastFM)\r
148         self.onLayoutFinish.append(self.tabchangedtimerFired)\r
149         self.onLayoutFinish.append(self.setCoverArt)\r
150         \r
151         self.guiupdatetimer = eTimer()\r
152         self.guiupdatetimer.timeout.get().append(self.guiupdatetimerFired)\r
153         self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)\r
154         \r
155         self.tabchangetimer = eTimer()\r
156         self.tabchangetimer.timeout.get().append(self.tabchangedtimerFired)\r
157         \r
158         self.infolabelcleartimer = eTimer()\r
159         self.infolabelcleartimer.timeout.get().append(self.clearInfoLabel)\r
160 \r
161     def initLastFM(self):\r
162         self.setInfoLabel("loggin into last.fm")\r
163         self.connect(config.plugins.LastFM.username.value,config.plugins.LastFM.password.value)\r
164     \r
165     def onConnectSuccessful(self,text):\r
166         self.setInfoLabel("login successful")      \r
167     \r
168     def onConnectFailed(self,text):\r
169         self.setInfoLabel("login failed! "+text,timeout=False)\r
170 \r
171     def onTrackSkiped(self,reason):\r
172         self.setInfoLabel("Track skiped")\r
173 \r
174     def onTrackLoved(self,reason):\r
175         self.setInfoLabel("Track loved")\r
176     \r
177     def onTrackBaned(self,reason):\r
178         self.setInfoLabel("Track baned")\r
179     \r
180     def onCommandFailed(self,reason):\r
181         self.setInfoLabel(reason)\r
182 \r
183     def onGlobalTagsLoaded(self,tags):\r
184         self.setInfoLabel("Global Tags loaded")\r
185         self.buildMenuList(tags)\r
186 \r
187     def onTopTracksLoaded(self,tracks):\r
188         self.setInfoLabel("Top Tracks loaded")\r
189         self.buildMenuList(tracks)\r
190 \r
191     def onRecentTracksLoaded(self,tracks):\r
192         self.setInfoLabel("recent Tracks loaded")\r
193         self.buildMenuList(tracks)\r
194         \r
195     def onRecentBannedTracksLoaded(self,tracks):\r
196         self.setInfoLabel("banned Tracks loaded")\r
197         self.buildMenuList(tracks)\r
198 \r
199     def onRecentLovedTracksLoaded(self,tracks):\r
200         self.setInfoLabel("loved Tracks loaded")\r
201         self.buildMenuList(tracks)\r
202 \r
203     def onNeighboursLoaded(self,user):\r
204         self.setInfoLabel("Neighbours loaded")\r
205         self.buildMenuList(user)\r
206 \r
207     def onFriendsLoaded(self,user):\r
208         self.setInfoLabel("Friends loaded")\r
209         self.buildMenuList(user)\r
210     \r
211     def onStationChanged(self,reason):\r
212         self.setInfoLabel(reason)    \r
213         \r
214     def onMetadataLoaded(self,metadata):\r
215         self.updateGUI()\r
216         self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)\r
217 \r
218     def action_TabChanged(self):\r
219         self.tabchangetimer.stop()\r
220         self.tabchangetimer.start(config.plugins.LastFM.timeouttabselect.value*1000)\r
221         \r
222     def guiupdatetimerFired(self):\r
223         if self.streamplayer.is_playing:\r
224             self.getMetadata()\r
225         self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)\r
226         \r
227     def tabchangedtimerFired(self):\r
228         self.tablist.getCurrent()[1][1]()\r
229         self.tabchangetimer.stop()\r
230         \r
231     def action_nextTab(self):\r
232         self.tablist.down()\r
233             \r
234     def action_prevTab(self):\r
235         self.tablist.up()\r
236 \r
237     def action_menu(self):\r
238         self.session.open(LastFMConfigScreen)\r
239 \r
240     def action_exit(self):\r
241         print "action_exit"\r
242         self.guiupdatetimer.stop()\r
243         self.streamplayer.stop()\r
244         self.close()\r
245 \r
246     def action_ok(self):\r
247         selectedTag = self["streamlist"].l.getCurrentSelection()[1]\r
248         self.changeStation(selectedTag)\r
249         \r
250     def action_startstop(self):\r
251         if self.streamplayer.is_playing:\r
252             self.streamplayer.stop()\r
253             self.metadata = {}\r
254             self.setInfoLabel("stream stopped")\r
255         \r
256         else:\r
257             self.setInfoLabel("starting stream",timeout=True)\r
258             if self.info.has_key("stream_url"):\r
259                 self.streamplayer.play(self.info["stream_url"])\r
260                 self.guiupdatetimer.start(config.plugins.LastFM.metadatarefreshinterval.value*1000)\r
261 \r
262     def setInfoLabel(self,text,timeout=True):\r
263         self.infolabelcleartimer.stop() \r
264         self["infolabel"].setText(text)\r
265         if timeout is True:\r
266             self.infolabelcleartimer.start(config.plugins.LastFM.timeoutstatustext.value*1000)\r
267             \r
268     def clearInfoLabel(self):\r
269         self["infolabel"].setText("")\r
270         \r
271     def updateGUI(self):\r
272         if self.streamplayer.is_playing is not True:\r
273             return None\r
274         print "updateGUI"\r
275         if self.streamplayer.is_playing:\r
276             self["button_red"].setText(_("stop"))\r
277         else:\r
278             self["button_red"].setText(_("play"))            \r
279             \r
280         if self.metadata.has_key("station"):\r
281             self.setTitle("Last.FM: "+self.metadata["station"])\r
282         else:\r
283             self.setTitle("Last.FM")\r
284 \r
285         if self.metadata.has_key("artist"):\r
286             self["info_artist"].setText(self.metadata["artist"])\r
287         else:\r
288             self["info_artist"].setText("N/A")\r
289 \r
290         if self.metadata.has_key("album"):\r
291             self["info_album"].setText(self.metadata["album"])\r
292         else:\r
293             self["info_album"].setText("N/A")\r
294 \r
295         if self.metadata.has_key("track"):\r
296             self["info_track"].setText(self.metadata["track"])\r
297         else:\r
298             self["info_track"].setText("N/A")\r
299         \r
300         if self.metadata.has_key("albumcover_large") and config.plugins.LastFM.showcoverart.value:\r
301             self.imageconverter.convert(self.metadata["albumcover_large"])\r
302         elif self.metadata.has_key("albumcover_medium") and config.plugins.LastFM.showcoverart.value:\r
303             self.imageconverter.convert(self.metadata["albumcover_medium"])\r
304         elif self.metadata.has_key("albumcover_small") and config.plugins.LastFM.showcoverart.value:\r
305             self.imageconverter.convert(self.metadata["albumcover_small"],self.setCoverArt)\r
306         else:\r
307             self.setCoverArt()\r
308         \r
309         if self.streamplayer.is_playing is not True:\r
310             self.setTitle(myname)\r
311             self.setCoverArt()\r
312             self["info_artist"].setText("N/A")\r
313             self["info_album"].setText("N/A")\r
314             self["info_track"].setText("N/A")\r
315             \r
316     def setCoverArt(self,pixmap=None):\r
317         if pixmap is None:\r
318             self["info_cover"].instance.setPixmapFromFile(self.noCoverArtPNG)            \r
319         else:\r
320             self["info_cover"].instance.setPixmap(pixmap.__deref__())\r
321     \r
322 \r
323     def loadPersonalStations(self):\r
324         tags = []\r
325         x= {}\r
326         x["_display"] = "Personal Radio"\r
327         x["stationurl"] = self.getPersonalURL(config.plugins.LastFM.username.value,level=config.plugins.LastFM.recommendedlevel.value)\r
328         tags.append(x)\r
329         \r
330         x= {}\r
331         x["_display"] = "Neighbours Tracks"\r
332         x["stationurl"] = self.getNeighboursURL(config.plugins.LastFM.username.value)\r
333         tags.append(x)\r
334         \r
335         x= {}\r
336         x["_display"] = "Loved Tracks"\r
337         x["stationurl"] = self.getLovedURL(config.plugins.LastFM.username.value)\r
338         tags.append(x)\r
339         \r
340         if self.metadata.has_key("artist"):\r
341             x= {}\r
342             x["_display"] = "similar Tracks of current Artist"\r
343             x["stationurl"] = self.getSimilarArtistsURL()\r
344             tags.append(x)\r
345             \r
346             x= {}\r
347             x["_display"] = "Tracks liked by Fans of current Track"\r
348             x["stationurl"] = self.getArtistsLikedByFans()\r
349             tags.append(x)\r
350 \r
351             x= {}\r
352             x["_display"] = "Group of Artist of current Track"\r
353             x["stationurl"] = self.getArtistGroup()\r
354             tags.append(x)\r
355         \r
356 \r
357         self.buildMenuList(tags)\r
358         \r
359     def loadGlobalTags(self):\r
360         self.setInfoLabel("loading Global Tags")\r
361         tags = self.getGlobalTags()\r
362 \r
363     def loadTopTracks(self):\r
364         self.setInfoLabel("loading Top Tacks")\r
365         tracks = self.getTopTracks(config.plugins.LastFM.username.value)\r
366 \r
367     def loadRecentTracks(self):\r
368         self.setInfoLabel("loading recent Tracks")\r
369         tracks = self.getRecentTracks(config.plugins.LastFM.username.value)\r
370 \r
371     def loadLovedTracks(self):\r
372         self.setInfoLabel("loading loved Tracks")\r
373         tracks = self.getRecentLovedTracks(config.plugins.LastFM.username.value)\r
374 \r
375     def loadBannedTracks(self):\r
376         self.setInfoLabel("loading loved Tracks")\r
377         tracks = self.getRecentBannedTracks(config.plugins.LastFM.username.value)\r
378         \r
379     def loadNeighbours(self):\r
380         self.setInfoLabel("loading Neighbours")\r
381         tracks = self.getNeighbours(config.plugins.LastFM.username.value)\r
382 \r
383     def loadFriends(self):\r
384         self.setInfoLabel("loading Friends")\r
385         tracks = self.getFriends(config.plugins.LastFM.username.value)\r
386 \r
387     def buildMenuList(self,items):\r
388         menuliste = []\r
389         for i in items:\r
390             menuliste.append((i['_display'],i['stationurl']))\r
391         self["streamlist"].l.setList(menuliste) \r
392 \r
393 \r
394 class ImageConverter:\r
395     \r
396     targetfile= "/tmp/coverart"\r
397     lastURL =""\r
398 \r
399     def __init__(self,callBack):\r
400         self.callBack = callBack\r
401 \r
402     def convert(self,sourceURL):\r
403         if self.lastURL != sourceURL:\r
404             extension = sourceURL.split(".")[-1]\r
405             tmpfile = self.targetfile+"."+extension\r
406             \r
407             fpurl = urllib.urlopen(sourceURL)\r
408             raw = fpurl.read()\r
409             fpurl.close()\r
410             \r
411             fp = open(tmpfile,"w")\r
412             fp.write(raw)\r
413             fp.close()\r
414             \r
415             self.currPic = loadPic(tmpfile, 116, 116, 0,0, 0,1)\r
416             \r
417             os.remove(tmpfile)\r
418             \r
419             self.callBack(pixmap=self.currPic)\r
420             self.lastURL = sourceURL