20c91738ec2c45482aca1b3450e200bdb9e12155
[clinton/xbmc-groove.git] / default.py
1 import urllib, urllib2, re, xbmcplugin, xbmcgui, xbmc, sys, os, time, pprint, shutil, xbmcaddon
2
3 MODE_SEARCH_SONGS = 1
4 MODE_SEARCH_ALBUMS = 2
5 MODE_SEARCH_ARTISTS = 3
6 MODE_POPULAR_SONGS = 4
7 MODE_FAVORITES = 5
8 MODE_PLAYLISTS = 6
9 MODE_ALBUM = 7
10 MODE_ARTIST = 8
11 MODE_PLAYLIST = 9
12 MODE_SIMILAR_ARTISTS = 10
13 MODE_SONG = 11
14 MODE_FAVORITE = 12
15 MODE_UNFAVORITE = 13
16 MODE_MAKE_PLAYLIST = 14
17 MODE_REMOVE_PLAYLIST = 15
18 MODE_RENAME_PLAYLIST = 16
19
20 lastID = 0
21
22 baseDir = os.getcwd()
23 resDir = xbmc.translatePath(os.path.join(baseDir, 'resources'))
24 libDir = xbmc.translatePath(os.path.join(resDir, 'lib'))
25 imgDir = xbmc.translatePath(os.path.join(resDir, 'img'))
26 thumbDir = os.path.join('special://masterprofile/addon_data/', os.path.join(os.path.basename(os.getcwd()), 'thumb'))
27 playlistUrl = 'plugin://plugin.audio.groove/?mode=6'
28 thumbDef = os.path.join(os.path.basename(os.getcwd()), 'default.tbn')
29
30 sys.path.append (libDir)
31 from GrooveAPI import *
32 groovesharkApi = GrooveAPI()
33
34 class _Info:
35 def __init__( self, *args, **kwargs ):
36 self.__dict__.update( kwargs )
37
38 class Groveshark:
39
40 albumImg = xbmc.translatePath(os.path.join(imgDir, 'album.png'))
41 artistImg = xbmc.translatePath(os.path.join(imgDir, 'artist.png'))
42 favoritesImg = xbmc.translatePath(os.path.join(imgDir, 'favorites.png'))
43 playlistImg = xbmc.translatePath(os.path.join(imgDir, 'playlist.png'))
44 popularSongsImg = xbmc.translatePath(os.path.join(imgDir, 'popularSongs.png'))
45 songImg = xbmc.translatePath(os.path.join(imgDir, 'song.png'))
46 defImg = xbmc.translatePath(os.path.join(imgDir, 'default.tbn'))
47 fanImg = xbmc.translatePath(os.path.join(baseDir, 'fanart.png'))
48
49 settings = xbmcaddon.Addon(id='plugin.audio.groove')
50 songsearchlimit = settings.getSetting('songsearchlimit')
51 albumsearchlimit = settings.getSetting('albumsearchlimit')
52 artistsearchlimit = settings.getSetting('artistsearchlimit')
53 username = settings.getSetting('username')
54 password = settings.getSetting('password')
55
56 def __init__( self ):
57 self._handle = int(sys.argv[1])
58
59 def categories(self):
60
61 xbmc.log(self.username + ", limits: " + str(self.songsearchlimit) + ", " + str(self.albumsearchlimit) + ", " + str(self.artistsearchlimit))
62
63 userid = self._get_login()
64
65 # Setup
66 groovesharkApi.setRemoveDuplicates(True)
67 xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg)
68 if os.path.isdir(thumbDir) == False:
69 os.makedirs(thumbDir)
70
71 self._add_dir('Search songs', '', MODE_SEARCH_SONGS, self.songImg, 0)
72 self._add_dir('Search albums', '', MODE_SEARCH_ALBUMS, self.albumImg, 0)
73 self._add_dir('Search artists', '', MODE_SEARCH_ARTISTS, self.artistImg, 0)
74 self._add_dir('Popular songs', '', MODE_POPULAR_SONGS, self.popularSongsImg, 0)
75 if (userid != 0):
76 self._add_dir('Favorites', '', MODE_FAVORITES, self.favoritesImg, 0)
77 self._add_dir('Playlists', '', MODE_PLAYLISTS, self.playlistImg, 0)
78
79 def searchSongs(self):
80 query = self._get_keyboard(default="", heading="Search songs")
81 if (query):
82 songs = groovesharkApi.searchSongs(query, limit = self.songsearchlimit)
83 if (len(songs) > 0):
84 self._add_songs_directory(songs)
85 else:
86 dialog = xbmcgui.Dialog()
87 dialog.ok('Grooveshark', 'No matching songs.')
88 self.categories()
89
90 def searchAlbums(self):
91 query = self._get_keyboard(default="", heading="Search albums")
92 if (query):
93 albums = groovesharkApi.searchAlbums(query, limit = self.albumsearchlimit)
94 if (len(albums) > 0):
95 self._add_albums_directory(albums)
96 else:
97 dialog = xbmcgui.Dialog()
98 dialog.ok('Grooveshark', 'No matching albums.')
99 self.categories()
100
101 def searchArtists(self):
102 query = self._get_keyboard(default="", heading="Search artists")
103 if (query):
104 artists = groovesharkApi.searchArtists(query, limit = self.artistsearchlimit)
105 if (len(artists) > 0):
106 self._add_artists_directory(artists)
107 else:
108 dialog = xbmcgui.Dialog()
109 dialog.ok('Grooveshark', 'No matching artists.')
110 self.categories()
111
112 def favorites(self):
113 userid = self._get_login()
114 if (userid != 0):
115 favorites = groovesharkApi.userGetFavoriteSongs(userid)
116 if (len(favorites) > 0):
117 self._add_songs_directory(favorites)
118 else:
119 dialog = xbmcgui.Dialog()
120 dialog.ok('Grooveshark', 'You have no favorites.')
121 self.categories()
122
123 def popularSongs(self):
124 popular = groovesharkApi.popularGetSongs(limit = self.songsearchlimit)
125 if (len(popular) > 0):
126 self._add_songs_directory(popular)
127 else:
128 dialog = xbmcgui.Dialog()
129 dialog.ok('Grooveshark', 'No popular songs.')
130 self.categories()
131
132 def popularAlbums(self):
133 popular = groovesharkApi.popularGetAlbums(limit = self.albumsearchlimit)
134 if (len(popular) > 0):
135 self._add_albums_directory(popular)
136 else:
137 dialog = xbmcgui.Dialog()
138 dialog.ok('Grooveshark', 'No popular albums.')
139 self.categories()
140
141 def popularArtists(self):
142 popular = groovesharkApi.popularGetArtists(limit = self.artistsearchlimit)
143 if (len(popular) > 0):
144 self._add_artists_directory(popular)
145 else:
146 dialog = xbmcgui.Dialog()
147 dialog.ok('Grooveshark', 'No popular artists.')
148 self.categories()
149
150 def playlists(self):
151 userid = self._get_login()
152 if (userid != 0):
153 playlists = groovesharkApi.userGetPlaylists()
154 if (len(playlists) > 0):
155 self._add_playlists_directory(playlists)
156 else:
157 dialog = xbmcgui.Dialog()
158 dialog.ok('Grooveshark', 'You have no playlists.')
159 self.categories()
160
161 def favorite(self, songid):
162 userid = self._get_login()
163 if (userid != 0):
164 xbmc.log("Favorite song: " + str(songid))
165 groovesharkApi.favoriteSong(songID = songid)
166 xbmc.executebuiltin('XBMC.Notification(Grooveshark, Added to favorites, 1000, ' + thumbDef + ')')
167 else:
168 dialog = xbmcgui.Dialog()
169 dialog.ok('Grooveshark', 'You must be logged in', 'to add favorites.')
170
171 def unfavorite(self, songid):
172 userid = self._get_login()
173 if (userid != 0):
174 xbmc.log("Unfavorite song: " + str(songid))
175 groovesharkApi.unfavoriteSong(songID = songid)
176 xbmc.executebuiltin('XBMC.Notification(Grooveshark, Removed from favorites, 1000, ' + thumbDef + ')')
177 else:
178 dialog = xbmcgui.Dialog()
179 dialog.ok('Grooveshark', 'You must be logged in', 'to remove favorites.')
180
181 def frown(self, songid):
182 userid = self._get_login()
183 if (userid != 0):
184 xbmc.log("Frown song: " + str(songid))
185 if groovesharkApi.radioFrown(songId = songid) != True:
186 xbmc.log("Unable to frown song " + str(songid))
187 else:
188 xbmc.executebuiltin('XBMC.Notification(Grooveshark, Frowned, 1000, ' + thumbDef + ')')
189 else:
190 dialog = xbmcgui.Dialog()
191 dialog.ok('Grooveshark', 'You must be logged in', 'to frown a song.')
192
193 def similarArtists(self, artistId):
194 similar = groovesharkApi.artistGetSimilar(artistId, limit = self.artistsearchlimit)
195 if (len(similar) > 0):
196 self._add_artists_directory(similar)
197 else:
198 dialog = xbmcgui.Dialog()
199 dialog.ok('Grooveshark', 'No similar artists.')
200 self.categories()
201
202 def makePlaylist(self, albumid, name):
203 userid = self._get_login()
204 if (userid != 0):
205 re.split(' - ',name,1)
206 nameTokens = re.split(' - ',name,1)
207 name = self._get_keyboard(default=nameTokens[0], heading="Playlist name")
208 if name != '':
209 album = groovesharkApi.albumGetSongs(albumid, self.songsearchlimit)
210 songids = []
211 for song in album:
212 songids.append(song[1])
213 id = groovesharkApi.playlistCreateUnique(name, songids)
214 if id == 0:
215 dialog = xbmcgui.Dialog()
216 dialog.ok('Grooveshark', 'Cannot create playlist ', name)
217 else:
218 xbmc.executebuiltin('XBMC.Notification(Grooveshark, Playlist created, 1000, ' + thumbDef + ')')
219 else:
220 dialog = xbmcgui.Dialog()
221 dialog.ok('Grooveshark', 'You must be logged in ', ' to create a playlist.')
222
223 def removePlaylist(self, playlistid, name):
224 dialog = xbmcgui.Dialog()
225 if dialog.yesno('Grooveshark', name, 'Delete this playlist?') == True:
226 userid = self._get_login()
227 if (userid != 0):
228 groovesharkApi.playlistDelete(playlistid)
229 xbmc.executebuiltin("Container.Update(" + playlistUrl + ",replace)")
230 else:
231 dialog = xbmcgui.Dialog()
232 dialog.ok('Grooveshark', 'You must be logged in ', ' to delete a playlist.')
233
234 def renamePlaylist(self, playlistid, name):
235 userid = self._get_login()
236 if (userid != 0):
237 newname = self._get_keyboard(default=name, heading="Playlist name")
238 if newname == '':
239 return
240 elif groovesharkApi.playlistRename(playlistid, newname) == 0:
241 dialog = xbmcgui.Dialog()
242 dialog.ok('Grooveshark', 'Cannot rename playlist ', name)
243 else:
244 xbmc.executebuiltin("Container.Refresh")
245 else:
246 dialog = xbmcgui.Dialog()
247 dialog.ok('Grooveshark', 'You must be logged in ', ' to rename a playlist.')
248
249 def album(self, albumid):
250 album = groovesharkApi.albumGetSongs(albumId = albumid, limit = self.songsearchlimit)
251 self._add_songs_directory(album)
252
253 def artist(self, artistid):
254 albums = groovesharkApi.artistGetAlbums(artistId = artistid, limit = self.albumsearchlimit)
255 self._add_albums_directory(albums, artistid)
256
257 def playlist(self, playlistid):
258 userid = self._get_login()
259 if (userid != 0):
260 songs = groovesharkApi.playlistGetSongs(playlistId = playlistid, limit = self.songsearchlimit)
261 self._add_songs_directory(songs)
262 else:
263 dialog = xbmcgui.Dialog()
264 dialog.ok('Grooveshark', 'You must be logged in', 'to get playlists.')
265
266 def playSong(self, item):
267 url = item.getProperty('url')
268 xbmc.log("Playing: " + url)
269 xbmcplugin.setResolvedUrl(handle=int(sys.argv[1]), succeeded=True, listitem=item)
270
271 def songItem(self, id, name, album, artist, duration, thumb, image):
272 url = groovesharkApi.getStreamURL(id)
273 # Only try to get the image
274 if image != "":
275 songImg = self._get_icon(image, 'song-' + str(id) + "-image")
276 songThm = songImg
277 else:
278 songThm = self._get_icon(thumb, 'song-' + str(id) + "-thumb")
279 songImg = songThm
280 item = xbmcgui.ListItem(label = artist + " - " + album + " - " + name, path=url, thumbnailImage=songThm, iconImage=songImg)
281 item.setInfo( type="music", infoLabels={ "title": name, "duration": duration, "album": album, "artist": artist} )
282 item.setProperty('mimetype', 'audio/mpeg')
283 item.setProperty("IsPlayable", "true")
284 item.setProperty('url', url)
285 item.setProperty('thumb', songThm)
286 item.setProperty('image', songImg)
287
288 return item
289
290 def _get_keyboard(self, default="", heading="", hidden=False):
291 kb = xbmc.Keyboard(default, heading, hidden)
292 kb.doModal()
293 if (kb.isConfirmed()):
294 return unicode(kb.getText(), "utf-8")
295 return ''
296
297 def _get_login(self):
298 if (self.username == "" or self.password == ""):
299 dialog = xbmcgui.Dialog()
300 dialog.ok('Grooveshark', 'Unable to login.', 'Check username and password in settings.')
301 return 0
302 else:
303 if groovesharkApi.loggedInStatus() == 1:
304 groovesharkApi.logout()
305 userid = groovesharkApi.loginExt(self.username, self.password)
306 if (userid != 0):
307 xbmc.log("Logged in")
308 return userid
309 else:
310 dialog = xbmcgui.Dialog()
311 dialog.ok('Grooveshark', 'Unable to login.', 'Check username and password in settings.')
312 return 0
313
314 def _get_song_item(self, song):
315 name = song[0]
316 id = song[1]
317 duration = song[2]
318 album = song[3]
319 artist = song[6]
320 thumb = song[8]
321 image = song[9]
322 return self.songItem(id, name, album, artist, duration, thumb, image)
323
324 # File download
325 def _get_icon(self, url, id):
326 localThumb = os.path.join(xbmc.translatePath(os.path.join(thumbDir, str(id)))) + '.tbn'
327 try:
328 if os.path.isfile(localThumb) == False:
329 xbmc.log('Downloading ' + url + ' to ' + localThumb)
330 loc = urllib.URLopener()
331 loc.retrieve(url, localThumb)
332 except:
333 xbmc.log('URL download failed of ' + url + ' to ' + localThumb)
334 return(self.defImg)
335
336 return os.path.join(os.path.join(thumbDir, str(id))) + '.tbn'
337
338 def _add_songs_directory(self, songs):
339 n = len(songs)
340 xbmc.log("Found " + str(n) + " songs...")
341 i = 0
342 while i < n:
343 song = songs[i]
344 item = self._get_song_item(song)
345 songurl = item.getProperty('url')
346 songthumb = item.getProperty('thumb')
347 songimage = item.getProperty('image')
348 songname = song[0]
349 songid = song[1]
350 songduration = song[2]
351 songalbum = song[3]
352 songartist = song[6]
353 u=sys.argv[0]+"?url="+urllib.quote_plus(songurl) \
354 +"&mode="+str(MODE_SONG)+"&name="+urllib.quote_plus(songname)+"&id=" \
355 +str(songid) \
356 +"&album="+urllib.quote_plus(songalbum) \
357 +"&artist="+urllib.quote_plus(songartist) \
358 +"&duration="+str(songduration) \
359 +"&thumb="+urllib.quote_plus(songthumb) \
360 +"&image="+urllib.quote_plus(songimage)
361 fav=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_FAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid)
362 unfav=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_UNFAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid)
363 menuItems = []
364 menuItems.append(("Grooveshark Favorite", "XBMC.RunPlugin("+fav+")"))
365 menuItems.append(("Not Grooveshark Favorite", "XBMC.RunPlugin("+unfav+")"))
366 item.addContextMenuItems(menuItems, replaceItems=False)
367 xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=item,isFolder=False,totalItems=n)
368 i = i + 1
369 xbmcplugin.setContent(self._handle, 'songs')
370 xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg)
371
372 def _add_albums_directory(self, albums, artistid=0):
373 n = len(albums)
374 xbmc.log("Found " + str(n) + " albums...")
375 i = 0
376 while i < n:
377 album = albums[i]
378 albumArtistName = album[0]
379 albumName = album[2]
380 albumID = album[3]
381 albumImage = self._get_icon(album[4], 'album-' + str(albumID))
382 self._add_dir(albumName + " - " + albumArtistName, '', MODE_ALBUM, albumImage, albumID, n)
383 i = i + 1
384 if artistid > 0:
385 self._add_dir('Similar artists...', '', MODE_SIMILAR_ARTISTS, self.artistImg, artistid)
386 xbmcplugin.setContent(self._handle, 'albums')
387 xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ALBUM_IGNORE_THE)
388 xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg)
389
390 def _add_artists_directory(self, artists):
391 n = len(artists)
392 xbmc.log("Found " + str(n) + " artists...")
393 i = 0
394 while i < n:
395 artist = artists[i]
396 artistName = artist[0]
397 artistID = artist[1]
398 self._add_dir(artistName, '', MODE_ARTIST, self.artistImg, artistID, n)
399 i = i + 1
400 xbmcplugin.setContent(self._handle, 'artists')
401 xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ARTIST_IGNORE_THE)
402 xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg)
403
404 def _add_playlists_directory(self, playlists):
405 n = len(playlists)
406 xbmc.log("Found " + str(n) + " playlists...")
407 i = 0
408 while i < n:
409 playlist = playlists[i]
410 playlistName = playlist[0]
411 playlistID = playlist[1]
412 self._add_dir(playlistName, '', MODE_PLAYLIST, self.playlistImg, playlistID, n)
413 i = i + 1
414 xbmcplugin.setContent(self._handle, 'files')
415 xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_PLAYLIST_ORDER)
416 xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg)
417
418 def _add_dir(self, name, url, mode, iconimage, id, items=1):
419 u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&id="+str(id)
420 dir=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage=iconimage)
421 dir.setInfo( type="Music", infoLabels={ "title": name } )
422 # Codes from http://xbmc-scripting.googlecode.com/svn/trunk/Script%20Templates/common/gui/codes.py
423 menuItems = []
424 menuItems.append(("Select", "XBMC.executebuiltin(Action(7))"))
425 if mode == MODE_ALBUM:
426 mkplaylst=sys.argv[0]+"?mode="+str(MODE_MAKE_PLAYLIST)+"&name="+name+"&id="+str(id)
427 menuItems.append(("Make Grooveshark playlist", "XBMC.RunPlugin("+mkplaylst+")"))
428 if mode == MODE_PLAYLIST:
429 rmplaylst=sys.argv[0]+"?mode="+str(MODE_REMOVE_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id)
430 menuItems.append(("Delete playlist", "XBMC.RunPlugin("+rmplaylst+")"))
431 mvplaylst=sys.argv[0]+"?mode="+str(MODE_RENAME_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id)
432 menuItems.append(("Rename playlist", "XBMC.RunPlugin("+mvplaylst+")"))
433 dir.addContextMenuItems(menuItems, replaceItems=True)
434 return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=dir,isFolder=True, totalItems=items)
435
436
437 def get_params():
438 param=[]
439 paramstring=sys.argv[2]
440 if len(paramstring)>=2:
441 params=sys.argv[2]
442 cleanedparams=params.replace('?','')
443 if (params[len(params)-1]=='/'):
444 params=params[0:len(params)-2]
445 pairsofparams=cleanedparams.split('&')
446 param={}
447 for i in range(len(pairsofparams)):
448 splitparams={}
449 splitparams=pairsofparams[i].split('=')
450 if (len(splitparams))==2:
451 param[splitparams[0]]=splitparams[1]
452 print param
453 return param
454
455 grooveshark = Groveshark();
456
457 params=get_params()
458 url=None
459 name=None
460 mode=None
461 id=None
462
463 try: url=urllib.unquote_plus(params["url"])
464 except: pass
465 try: name=urllib.unquote_plus(params["name"])
466 except: pass
467 try: mode=int(params["mode"])
468 except: pass
469 try: id=int(params["id"])
470 except: pass
471
472 if (id > 0):
473 lastID = id
474
475 if mode==None:
476 grooveshark.categories()
477
478 elif mode==MODE_SEARCH_SONGS:
479 grooveshark.searchSongs()
480
481 elif mode==MODE_SEARCH_ALBUMS:
482 grooveshark.searchAlbums()
483
484 elif mode==MODE_SEARCH_ARTISTS:
485 grooveshark.searchArtists()
486
487 elif mode==MODE_POPULAR_SONGS:
488 grooveshark.popularSongs()
489
490 elif mode==MODE_PLAYLISTS:
491 grooveshark.playlists()
492
493 elif mode==MODE_FAVORITES:
494 grooveshark.favorites()
495
496 elif mode==MODE_SONG:
497 try: name=urllib.unquote_plus(params["name"])
498 except: pass
499 try: album=urllib.unquote_plus(params["album"])
500 except: pass
501 try: artist=urllib.unquote_plus(params["artist"])
502 except: pass
503 try: duration=int(params["duration"])
504 except: pass
505 try: thumb=urllib.unquote_plus(params["thumb"])
506 except: pass
507 try: image=urllib.unquote_plus(params["image"])
508 except: pass
509 song = grooveshark.songItem(id, name, album, artist, duration, thumb, image)
510 grooveshark.playSong(song)
511
512 elif mode==MODE_ARTIST:
513 grooveshark.artist(lastID)
514
515 elif mode==MODE_ALBUM:
516 grooveshark.album(lastID)
517
518 elif mode==MODE_PLAYLIST:
519 grooveshark.playlist(lastID)
520
521 elif mode==MODE_FAVORITE:
522 grooveshark.favorite(lastID)
523
524 elif mode==MODE_UNFAVORITE:
525 grooveshark.unfavorite(lastID)
526
527 elif mode==MODE_SIMILAR_ARTISTS:
528 grooveshark.similarArtists(lastID)
529
530 elif mode==MODE_MAKE_PLAYLIST:
531 grooveshark.makePlaylist(lastID, name)
532
533 elif mode==MODE_REMOVE_PLAYLIST:
534 grooveshark.removePlaylist(lastID, name)
535
536 elif mode==MODE_RENAME_PLAYLIST:
537 grooveshark.renamePlaylist(lastID, name)
538
539
540 if (mode < MODE_SONG):
541 xbmcplugin.endOfDirectory(int(sys.argv[1]))