Fixes.
[clinton/xbmc-groove.git] / default.py
1 import urllib, urllib2, re, xbmcplugin, xbmcgui, xbmc, sys, os
2
3 # plugin constants
4 __plugin__ = "Grooveshark"
5 __author__ = "Stephen Denham"
6 __url__ = ""
7 __svn_url__ = ""
8 __version__ = "0.0.1"
9 __svn_revision__ = ""
10 __XBMC_Revision__ = ""
11
12 MODE_SEARCH_SONGS = 1
13 MODE_SEARCH_ALBUMS = 2
14 MODE_SEARCH_ARTISTS = 3
15 MODE_POPULAR = 4
16 MODE_FAVORITES = 5
17 MODE_PLAYLISTS = 6
18 MODE_ALBUM = 7
19 MODE_ARTIST = 8
20 MODE_PLAYLIST = 9
21 MODE_SONG = 10
22 MODE_FAVORITE = 11
23 MODE_UNFAVORITE = 12
24
25 songsearchlimit = 0
26 albumsearchlimit = 0
27 artistsearchlimit = 0
28
29 lastID = 0
30
31 resDir = xbmc.translatePath(os.path.join(os.getcwd(), 'resources'))
32 libDir = xbmc.translatePath(os.path.join(resDir, 'lib'))
33 imgDir = xbmc.translatePath(os.path.join(resDir, 'img'))
34 thumbDir = os.path.join('special://masterprofile/plugin_data/music', os.path.join(os.path.basename(os.getcwd()), 'thumb'))
35
36 sys.path.append (libDir)
37 from GrooveAPI import *
38 groovesharkApi = GrooveAPI()
39
40 class _Info:
41 def __init__( self, *args, **kwargs ):
42 self.__dict__.update( kwargs )
43
44 class Groveshark:
45
46 albumImg = xbmc.translatePath(os.path.join(imgDir, 'album.png'))
47 artistImg = xbmc.translatePath(os.path.join(imgDir, 'artist.png'))
48 favoritesImg = xbmc.translatePath(os.path.join(imgDir, 'favorites.png'))
49 playlistImg = xbmc.translatePath(os.path.join(imgDir, 'playlist.png'))
50 popularImg = xbmc.translatePath(os.path.join(imgDir, 'popular.png'))
51 songImg = xbmc.translatePath(os.path.join(imgDir, 'song.png'))
52
53 songsearchlimit = xbmcplugin.getSetting('songsearchlimit')
54 albumsearchlimit = xbmcplugin.getSetting('albumsearchlimit')
55 artistsearchlimit = xbmcplugin.getSetting('artistsearchlimit')
56
57
58 def __init__( self ):
59 self._handle = int(sys.argv[1])
60
61 def categories(self):
62
63 userid = self._get_login()
64
65 # Setup
66 groovesharkApi.setRemoveDuplicates(True)
67 if not os.path.exists(xbmc.translatePath(thumbDir)):
68 os.makedirs(xbmc.translatePath(thumbDir))
69
70 self._addDir('Search songs', '', MODE_SEARCH_SONGS, self.songImg, 0)
71 self._addDir('Search albums', '', MODE_SEARCH_ALBUMS, self.albumImg, 0)
72 self._addDir('Search artists', '', MODE_SEARCH_ARTISTS, self.artistImg, 0)
73 self._addDir('Popular', '', MODE_POPULAR, self.popularImg, 0)
74 if (userid != 0):
75 self._addDir('Favorites', '', MODE_FAVORITES, self.favoritesImg, 0)
76 self._addDir('Playlists', '', MODE_PLAYLISTS, self.playlistImg, 0)
77
78 def searchSongs(self):
79 query = self._get_keyboard(default="", heading="Search songs")
80 if (query):
81 songs = groovesharkApi.searchSongs(query, limit = xbmcplugin.getSetting('songsearchlimit'))
82 if (len(songs) > 0):
83 self._get_songs(songs)
84 else:
85 dialog = xbmcgui.Dialog()
86 dialog.ok('Grooveshark', 'No matching songs.')
87 self.categories()
88
89 def searchAlbums(self):
90 query = self._get_keyboard(default="", heading="Search albums")
91 if (query):
92 albums = groovesharkApi.searchAlbums(query, limit = xbmcplugin.getSetting('albumsearchlimit'))
93 if (len(albums) > 0):
94 self._get_albums(albums)
95 else:
96 dialog = xbmcgui.Dialog()
97 dialog.ok('Grooveshark', 'No matching albums.')
98 self.categories()
99
100 def searchArtists(self):
101 query = self._get_keyboard(default="", heading="Search artists")
102 if (query):
103 artists = groovesharkApi.searchArtists(query, limit = xbmcplugin.getSetting('artistsearchlimit'))
104 if (len(artists) > 0):
105 self._get_artists(artists)
106 else:
107 dialog = xbmcgui.Dialog()
108 dialog.ok('Grooveshark', 'No matching artists.')
109 self.categories()
110
111 def favorites(self):
112 userid = self._get_login()
113 if (userid != 0):
114 favorites = groovesharkApi.userGetFavoriteSongs(userid)
115 if (len(favorites) > 0):
116 self._get_songs(favorites)
117 else:
118 dialog = xbmcgui.Dialog()
119 dialog.ok('Grooveshark', 'You have no favorites.')
120 self.categories()
121
122 def popular(self):
123 popular = groovesharkApi.popularGetSongs(limit = xbmcplugin.getSetting('songsearchlimit'))
124 if (len(popular) > 0):
125 self._get_songs(popular)
126 else:
127 dialog = xbmcgui.Dialog()
128 dialog.ok('Grooveshark', 'No popular songs.')
129 self.categories()
130
131 def playlists(self):
132 userid = self._get_login()
133 if (userid != 0):
134 playlists = groovesharkApi.userGetPlaylists()
135 if (len(playlists) > 0):
136 self._get_playlists(playlists)
137 else:
138 dialog = xbmcgui.Dialog()
139 dialog.ok('Grooveshark', 'You have no playlists.')
140 self.categories()
141
142 def favorite(self, songid):
143 userid = self._get_login()
144 if (userid != 0):
145 xbmc.log("Favorite playSong: " + str(songid))
146 groovesharkApi.favoriteSong(songID = songid)
147 else:
148 dialog = xbmcgui.Dialog()
149 dialog.ok('Grooveshark', 'You must be logged in', 'to add favorites.')
150
151 def unfavorite(self, songid):
152 userid = self._get_login()
153 if (userid != 0):
154 xbmc.log("Unfavorite playSong: " + str(songid))
155 groovesharkApi.unfavoriteSong(songID = songid)
156 else:
157 dialog = xbmcgui.Dialog()
158 dialog.ok('Grooveshark', 'You must be logged in', 'to remove favorites.')
159
160 def album(self,albumid):
161 album = groovesharkApi.albumGetSongs(albumId = albumid, limit = xbmcplugin.getSetting('songsearchlimit'))
162 self._get_songs(album)
163
164 def artist(self, artistid):
165 albums = groovesharkApi.artistGetAlbums(artistId = artistid, limit = xbmcplugin.getSetting('albumsearchlimit'))
166 self._get_albums(albums)
167
168 def playlist(self, playlistid):
169 userid = self._get_login()
170 if (userid != 0):
171 songs = groovesharkApi.playlistGetSongs(playlistId = playlistid, limit = xbmcplugin.getSetting('songsearchlimit'))
172 self._get_songs(songs)
173 else:
174 dialog = xbmcgui.Dialog()
175 dialog.ok('Grooveshark', 'You must be logged in', 'to get playlists.')
176
177 def playSong(self, url, name, album, artist, duration, thumb, image):
178 xbmc.log("Playing: " + url + ", image " + image)
179 songItem = xbmcgui.ListItem(label = name, path=url, thumbnailImage=thumb, iconImage=image)
180 songItem.setInfo( type="Music", infoLabels={ "title": name, "duration": duration, "album": album, "artist": artist} )
181 songItem.setProperty('mimetype', 'audio/mpeg')
182 xbmc.Player().stop()
183 xbmc.Player(xbmc.PLAYER_CORE_PAPLAYER).play(url, songItem, False)
184
185 def _get_keyboard(self, default="", heading="", hidden=False):
186 kb = xbmc.Keyboard(default, heading, hidden)
187 kb.doModal()
188 if (kb.isConfirmed()):
189 return unicode(kb.getText(), "utf-8")
190 return ''
191
192 def _get_login(self):
193 username = xbmcplugin.getSetting('username')
194 password = xbmcplugin.getSetting('password')
195 if (username == "" or password == ""):
196 dialog = xbmcgui.Dialog()
197 dialog.ok('Grooveshark', 'Unable to login.', 'Check username and password in settings.')
198 return 0
199 else:
200 if groovesharkApi.loggedInStatus() == 1:
201 groovesharkApi.logout()
202 userid = groovesharkApi.loginExt(username, password)
203 if (userid != 0):
204 xbmc.log("Logged in")
205 return userid
206 else:
207 dialog = xbmcgui.Dialog()
208 dialog.ok('Grooveshark', 'Unable to login.', 'Check username and password in settings.')
209 return 0
210
211 def _get_songs(self, songs):
212 xbmc.log("Found " + str(len(songs)) + " songs...")
213 i = 0
214 while i < len(songs):
215 song = songs[i]
216 songName = song[0]
217 songID = song[1]
218 songDuration = song[2]
219 songAlbum = song[3]
220 songArtist = song[6]
221 songThumb = song[8]
222 songImage = song[9]
223 songUrl = groovesharkApi.getStreamURL(songID)
224 xbmc.log(songName + ", " + songArtist + ", " + songAlbum)
225 self._addSong(songID, songName, songUrl, songDuration, songAlbum, songArtist, songThumb, songImage)
226 i = i + 1
227 xbmcplugin.setContent(self._handle, 'songs')
228
229 def _get_albums(self, albums):
230 xbmc.log("Found " + str(len(albums)) + " albums...")
231 i = 0
232 while i < len(albums):
233 album = albums[i]
234 albumArtistName = album[0]
235 albumName = album[2]
236 albumID = album[3]
237 albumImage = album[4]
238 xbmc.log(albumName)
239 self._addDir(albumName + " - " + albumArtistName, '', MODE_ALBUM, albumImage, albumID)
240 i = i + 1
241 xbmcplugin.setContent(self._handle, 'albums')
242 xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ALBUM_IGNORE_THE)
243
244 def _get_artists(self, artists):
245 xbmc.log("Found " + str(len(artists)) + " artists...")
246 i = 0
247 while i < len(artists):
248 artist = artists[i]
249 artistName = artist[0]
250 artistID = artist[1]
251 xbmc.log(artistName)
252 self._addDir(artistName, '', MODE_ARTIST, self.artistImg, artistID)
253 i = i + 1
254 xbmcplugin.setContent(self._handle, 'artists')
255 xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ARTIST_IGNORE_THE)
256
257 def _get_playlists(self, playlists):
258 xbmc.log("Found " + str(len(playlists)) + " playlists...")
259 i = 0
260 while i < len(playlists):
261 playlist = playlists[i]
262 playlistName = playlist[0]
263 playlistID = playlist[1]
264 xbmc.log(playlistName)
265 self._addDir(playlistName, '', MODE_PLAYLIST, self.playlistImg, playlistID, )
266 i = i + 1
267 xbmcplugin.setContent(self._handle, 'files')
268 xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_PLAYLIST_ORDER)
269
270 def _addSong(self, songid, songname, songurl, songduration, songalbum, songartist, songthumb, songimage):
271 songImg = self._getThumb(songimage, str(songid) + "-image")
272 if songImg == "":
273 songImg = songimage
274 songThm = self._getThumb(songthumb, str(songid) + "-thumb")
275 if songThm == "":
276 songThm = songthumb
277 u=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_SONG)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid) \
278 +"&album="+urllib.quote_plus(songalbum) \
279 +"&artist="+urllib.quote_plus(songartist) \
280 +"&duration="+str(songduration) \
281 +"&thumb="+urllib.quote_plus(songThm) \
282 +"&image="+urllib.quote_plus(songImg)
283 xbmc.log("Artist is " + songartist + ", " + songThm + ", " + songThm)
284 songItem = xbmcgui.ListItem(label = songartist + " - " + songalbum + " - " + songname, iconImage=songImg, thumbnailImage=songThm, path=songurl)
285 songItem.setInfo( type="Music", infoLabels={ "title": songname, "duration": songduration, "album": songalbum, "artist": songartist} )
286 fav=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_FAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid)
287 unfav=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_UNFAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid)
288 menuItems = []
289 menuItems.append(("Grooveshark Favorite", "XBMC.RunPlugin("+fav+")"))
290 menuItems.append(("Not Grooveshark Favorite", "XBMC.RunPlugin("+unfav+")"))
291 songItem.addContextMenuItems(menuItems, replaceItems=False)
292 xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=songItem,isFolder=False)
293 return songItem
294
295 def _addDir(self, name, url, mode, iconimage, id):
296 u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&id="+str(id)
297 dir=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage=iconimage)
298 dir.setInfo( type="Music", infoLabels={ "title": name } )
299 # Codes from http://xbmc-scripting.googlecode.com/svn/trunk/Script%20Templates/common/gui/codes.py
300 menuItems = []
301 menuItems.append(("Select", "XBMC.executebuiltin(Action(7))"))
302 dir.addContextMenuItems(menuItems, replaceItems=True)
303 return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=dir,isFolder=True)
304
305 # File download
306 def _getThumb(self, url, id):
307 # Get the channel icon
308 localThumb = os.path.join(xbmc.translatePath(os.path.join(thumbDir, str(id)))) + '.tbn'
309 try:
310 if os.path.isfile(localThumb) == False:
311 loc = urllib.URLopener()
312 loc.retrieve(url, localThumb)
313 except:
314 xbmc.log('URL download failed of ' + url + ' to ' + localThumb)
315 return ""
316
317 return os.path.join(os.path.join(thumbDir, str(id))) + '.tbn'
318
319
320
321 def get_params():
322 param=[]
323 paramstring=sys.argv[2]
324 if len(paramstring)>=2:
325 params=sys.argv[2]
326 cleanedparams=params.replace('?','')
327 if (params[len(params)-1]=='/'):
328 params=params[0:len(params)-2]
329 pairsofparams=cleanedparams.split('&')
330 param={}
331 for i in range(len(pairsofparams)):
332 splitparams={}
333 splitparams=pairsofparams[i].split('=')
334 if (len(splitparams))==2:
335 param[splitparams[0]]=splitparams[1]
336 print param
337 return param
338
339 grooveshark = Groveshark();
340
341 params=get_params()
342 url=None
343 name=None
344 mode=None
345 id=None
346
347 try: url=urllib.unquote_plus(params["url"])
348 except: pass
349 try: name=urllib.unquote_plus(params["name"])
350 except: pass
351 try: mode=int(params["mode"])
352 except: pass
353 try: id=int(params["id"])
354 except: pass
355
356 if (id > 0):
357 lastID = id
358
359 if mode==None:
360 grooveshark.categories()
361
362 elif mode==MODE_SEARCH_SONGS:
363 grooveshark.searchSongs()
364
365 elif mode==MODE_SEARCH_ALBUMS:
366 grooveshark.searchAlbums()
367
368 elif mode==MODE_SEARCH_ARTISTS:
369 grooveshark.searchArtists()
370
371 elif mode==MODE_POPULAR:
372 grooveshark.popular()
373
374 elif mode==MODE_PLAYLISTS:
375 grooveshark.playlists()
376
377 elif mode==MODE_FAVORITES:
378 grooveshark.favorites()
379
380 elif mode==MODE_SONG:
381 try: name=urllib.unquote_plus(params["name"])
382 except: pass
383 try: album=urllib.unquote_plus(params["album"])
384 except: pass
385 try: artist=urllib.unquote_plus(params["artist"])
386 except: pass
387 try: duration=int(params["duration"])
388 except: pass
389 try: thumb=urllib.unquote_plus(params["thumb"])
390 except: pass
391 try: image=urllib.unquote_plus(params["image"])
392 except: pass
393 grooveshark.playSong(url, name, album, artist, duration, thumb, image)
394
395 elif mode==MODE_ARTIST:
396 grooveshark.artist(lastID)
397
398 elif mode==MODE_ALBUM:
399 grooveshark.album(lastID)
400
401 elif mode==MODE_PLAYLIST:
402 grooveshark.playlist(lastID)
403
404 elif mode==MODE_FAVORITE:
405 grooveshark.favorite(lastID)
406
407 elif mode==MODE_UNFAVORITE:
408 grooveshark.unfavorite(lastID)
409
410 if (mode < MODE_SONG):
411 xbmcplugin.endOfDirectory(int(sys.argv[1]))