1 import urllib
, sys
, os
, shutil
, re
, time
, xbmcaddon
, xbmcplugin
, xbmcgui
, xbmc
4 MODE_SEARCH_ARTISTS
= 3
5 MODE_SEARCH_ARTISTS_ALBUMS
= 4
6 MODE_SEARCH_PLAYLISTS
= 5
21 ACTION_SELECT_ITEM
= 7
22 ACTION_PREVIOUS_MENU
= 10
24 # Formats for track labels
25 ARTIST_ALBUM_NAME_LABEL
= 0
26 NAME_ALBUM_ARTIST_LABEL
= 1
29 resDir
= xbmc
.translatePath(os
.path
.join(baseDir
, 'resources'))
30 libDir
= xbmc
.translatePath(os
.path
.join(resDir
, 'lib'))
31 imgDir
= xbmc
.translatePath(os
.path
.join(resDir
, 'img'))
32 cacheDir
= os
.path
.join(xbmc
.translatePath('special://masterprofile/addon_data/'), os
.path
.basename(os
.getcwd()))
33 thumbDirName
= 'thumb'
34 thumbDir
= os
.path
.join('special://masterprofile/addon_data/', os
.path
.basename(os
.getcwd()), thumbDirName
)
36 baseModeUrl
= 'plugin://plugin.audio.groove/'
37 playlistUrl
= baseModeUrl
+ '?mode=' + str(MODE_PLAYLIST
)
38 playlistsUrl
= baseModeUrl
+ '?mode=' + str(MODE_PLAYLISTS
)
39 favoritesUrl
= baseModeUrl
+ '?mode=' + str(MODE_FAVORITES
)
41 thumbDef
= os
.path
.join(imgDir
, 'default.tbn')
43 sys
.path
.append (libDir
)
44 from GroovesharkAPI
import GrooveAPI
47 groovesharkApi
= GrooveAPI()
48 if groovesharkApi
.pingService() != True:
49 raise StandardError('No Grooveshark service')
51 dialog
= xbmcgui
.Dialog()
52 dialog
.ok('Grooveshark XBMC', 'Unable to connect with Grooveshark.', 'Please try again later')
57 def __init__( self
, *args
, **kwargs
):
58 self
.__dict
__.update( kwargs
)
63 albumImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'album.png'))
64 artistImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'artist.png'))
65 artistsAlbumsImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'artistsalbums.png'))
66 favoritesImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'favorites.png'))
67 playlistImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'playlist.png'))
68 usersplaylistsImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'usersplaylists.png'))
69 popularSongsImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'popularSongs.png'))
70 songImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'song.png'))
71 defImg
= xbmc
.translatePath(os
.path
.join(imgDir
, 'default.tbn'))
72 fanImg
= xbmc
.translatePath(os
.path
.join(baseDir
, 'fanart.png'))
74 settings
= xbmcaddon
.Addon(id='plugin.audio.groove')
75 songsearchlimit
= int(settings
.getSetting('songsearchlimit'))
76 albumsearchlimit
= int(settings
.getSetting('albumsearchlimit'))
77 artistsearchlimit
= int(settings
.getSetting('artistsearchlimit'))
78 username
= settings
.getSetting('username')
79 password
= settings
.getSetting('password')
83 self
._handle
= int(sys
.argv
[1])
84 if os
.path
.isdir(cacheDir
) == False:
86 xbmc
.log("Made " + cacheDir
)
87 artDir
= xbmc
.translatePath(thumbDir
)
88 if os
.path
.isdir(artDir
) == False:
90 xbmc
.log("Made " + artDir
)
95 self
.userid
= self
._get
_login
()
98 xbmcplugin
.setPluginFanart(int(sys
.argv
[1]), self
.fanImg
)
100 self
._add
_dir
('Search for songs...', '', MODE_SEARCH_SONGS
, self
.songImg
, 0)
101 self
._add
_dir
('Search for albums...', '', MODE_SEARCH_ALBUMS
, self
.albumImg
, 0)
102 self
._add
_dir
('Search for artists...', '', MODE_SEARCH_ARTISTS
, self
.artistImg
, 0)
103 self
._add
_dir
("Search for artist's albums...", '', MODE_SEARCH_ARTISTS_ALBUMS
, self
.artistsAlbumsImg
, 0)
104 self
._add
_dir
("Search for user's playlists...", '', MODE_SEARCH_PLAYLISTS
, self
.usersplaylistsImg
, 0)
105 self
._add
_dir
('Popular songs', '', MODE_POPULAR_SONGS
, self
.popularSongsImg
, 0)
106 if (self
.userid
!= 0):
107 self
._add
_dir
('My favorites', '', MODE_FAVORITES
, self
.favoritesImg
, 0)
108 self
._add
_dir
('My playlists', '', MODE_PLAYLISTS
, self
.playlistImg
, 0)
111 def searchSongs(self
):
112 query
= self
._get
_keyboard
(default
="", heading
="Search for songs")
114 songs
= groovesharkApi
.getSongSearchResults(query
, limit
= self
.songsearchlimit
)
116 self
._add
_songs
_directory
(songs
)
118 dialog
= xbmcgui
.Dialog()
119 dialog
.ok('Grooveshark XBMC', 'No matching songs.')
125 def searchAlbums(self
):
126 query
= self
._get
_keyboard
(default
="", heading
="Search for albums")
128 albums
= groovesharkApi
.getAlbumSearchResults(query
, limit
= self
.albumsearchlimit
)
129 if (len(albums
) > 0):
130 self
._add
_albums
_directory
(albums
)
132 dialog
= xbmcgui
.Dialog()
133 dialog
.ok('Grooveshark XBMC', 'No matching albums.')
139 def searchArtists(self
):
140 query
= self
._get
_keyboard
(default
="", heading
="Search for artists")
142 artists
= groovesharkApi
.getArtistSearchResults(query
, limit
= self
.artistsearchlimit
)
143 if (len(artists
) > 0):
144 self
._add
_artists
_directory
(artists
)
146 dialog
= xbmcgui
.Dialog()
147 dialog
.ok('Grooveshark XBMC', 'No matching artists.')
152 # Search for playlists
153 def searchPlaylists(self
):
154 query
= self
._get
_keyboard
(default
="", heading
="Search for user's playlists")
156 playlists
= groovesharkApi
.getUserPlaylistsEx(query
)
157 if (len(playlists
) > 0):
158 self
._add
_playlists
_directory
(playlists
)
160 dialog
= xbmcgui
.Dialog()
161 dialog
.ok('Grooveshark XBMC', 'No Grooveshark playlists found.')
166 # Search for artists albums
167 def searchArtistsAlbums(self
):
168 query
= self
._get
_keyboard
(default
="", heading
="Search for artist's albums")
170 artists
= groovesharkApi
.getArtistSearchResults(query
, limit
= self
.artistsearchlimit
)
171 if (len(artists
) > 0):
174 xbmc
.log("Found " + artist
[0] + "...")
175 albums
= groovesharkApi
.getArtistAlbums(artistID
, limit
= self
.albumsearchlimit
)
176 if (len(albums
) > 0):
177 self
._add
_albums
_directory
(albums
)
179 dialog
= xbmcgui
.Dialog()
180 dialog
.ok('Grooveshark XBMC', 'No matching albums.')
183 dialog
= xbmcgui
.Dialog()
184 dialog
.ok('Grooveshark XBMC', 'No matching artists.')
191 userid
= self
._get
_login
()
193 favorites
= groovesharkApi
.getUserFavoriteSongs()
194 if (len(favorites
) > 0):
195 self
._add
_songs
_directory
(favorites
)
197 dialog
= xbmcgui
.Dialog()
198 dialog
.ok('Grooveshark XBMC', 'You have no favorites.')
202 def popularSongs(self
):
203 popular
= groovesharkApi
.getPopularSongsToday(limit
= self
.songsearchlimit
)
204 if (len(popular
) > 0):
205 self
._add
_songs
_directory
(popular
)
207 dialog
= xbmcgui
.Dialog()
208 dialog
.ok('Grooveshark XBMC', 'No popular songs.')
213 userid
= self
._get
_login
()
215 playlists
= groovesharkApi
.getUserPlaylists()
216 if (len(playlists
) > 0):
217 self
._add
_playlists
_directory
(playlists
)
219 dialog
= xbmcgui
.Dialog()
220 dialog
.ok('Grooveshark XBMC', 'You have no Grooveshark playlists.')
223 dialog
= xbmcgui
.Dialog()
224 dialog
.ok('Grooveshark XBMC', 'You must be logged in ', ' to see your Grooveshark playlists.')
226 # Make songs a favorite
227 def favorite(self
, songid
):
228 userid
= self
._get
_login
()
230 xbmc
.log("Favorite song: " + str(songid
))
231 groovesharkApi
.addUserFavoriteSong(songID
= songid
)
232 xbmc
.executebuiltin('XBMC.Notification(Grooveshark XBMC, Added to favorites, 1000, ' + thumbDef
+ ')')
234 dialog
= xbmcgui
.Dialog()
235 dialog
.ok('Grooveshark XBMC', 'You must be logged in', 'to add favorites.')
237 # Show selected album
238 def album(self
, albumid
):
239 album
= groovesharkApi
.getAlbumSongs(albumid
, limit
= self
.songsearchlimit
)
240 self
._add
_songs
_directory
(album
, trackLabelFormat
=NAME_ALBUM_ARTIST_LABEL
)
242 # Show selected artist
243 def artist(self
, artistid
):
244 albums
= groovesharkApi
.getArtistAlbums(artistid
, limit
= self
.albumsearchlimit
)
245 self
._add
_albums
_directory
(albums
)
247 # Show selected playlist
248 def playlist(self
, playlistid
):
249 userid
= self
._get
_login
()
251 songs
= groovesharkApi
.getPlaylistSongs(playlistid
)
252 self
._add
_songs
_directory
(songs
, trackLabelFormat
=NAME_ALBUM_ARTIST_LABEL
)
254 dialog
= xbmcgui
.Dialog()
255 dialog
.ok('Grooveshark XBMC', 'You must be logged in', 'to get Grooveshark playlists.')
258 def playSong(self
, item
):
259 songid
= item
.getProperty('songid')
260 song
= groovesharkApi
.getSongURLFromSongID(songid
)
263 xbmc
.log("Playing: " + song
)
264 xbmcplugin
.setResolvedUrl(handle
=int(sys
.argv
[1]), succeeded
=True, listitem
=item
)
266 xbmc
.executebuiltin('XBMC.Notification(Grooveshark XBMC, Unable to play song, 1000, ' + thumbDef
+ ')')
268 # Make a song directory item
269 def songItem(self
, songid
, name
, album
, artist
, coverart
, trackLabelFormat
=ARTIST_ALBUM_NAME_LABEL
):
270 songImg
= self
._get
_icon
(coverart
, 'song-' + str(songid
) + "-image")
271 if trackLabelFormat
== NAME_ALBUM_ARTIST_LABEL
:
272 trackLabel
= name
+ " - " + album
+ " - " + artist
274 trackLabel
= artist
+ " - " + album
+ " - " + name
275 item
= xbmcgui
.ListItem(label
= trackLabel
, thumbnailImage
=songImg
, iconImage
=songImg
)
276 item
.setInfo( type="music", infoLabels
={ "title": name
, "album": album
, "artist": artist
} )
277 item
.setProperty('mimetype', 'audio/mpeg')
278 item
.setProperty("IsPlayable", "true")
279 item
.setProperty('songid', str(songid
))
280 item
.setProperty('coverart', songImg
)
281 item
.setProperty('title', name
)
282 item
.setProperty('album', album
)
283 item
.setProperty('artist', artist
)
288 def _get_keyboard(self
, default
="", heading
="", hidden
=False):
289 kb
= xbmc
.Keyboard(default
, heading
, hidden
)
291 if (kb
.isConfirmed()):
292 return unicode(kb
.getText(), "utf-8")
295 # Login to grooveshark
296 def _get_login(self
):
297 if (self
.username
== "" or self
.password
== ""):
298 dialog
= xbmcgui
.Dialog()
299 dialog
.ok('Grooveshark XBMC', 'Unable to login.', 'Check username and password in settings.')
303 uid
= groovesharkApi
.login(self
.username
, self
.password
)
307 dialog
= xbmcgui
.Dialog()
308 dialog
.ok('Grooveshark XBMC', 'Unable to login.', 'Check username and password in settings.')
311 # Get a song directory item
312 def _get_song_item(self
, song
, trackLabelFormat
):
318 return self
.songItem(songid
, name
, album
, artist
, coverart
, trackLabelFormat
)
321 def _get_icon(self
, url
, songid
):
323 localThumb
= os
.path
.join(xbmc
.translatePath(os
.path
.join(thumbDir
, str(songid
)))) + '.tbn'
325 if os
.path
.isfile(localThumb
) == False:
326 loc
= urllib
.URLopener()
327 loc
.retrieve(url
, localThumb
)
329 shutil
.copy2(thumbDef
, localThumb
)
330 return os
.path
.join(os
.path
.join(thumbDir
, str(songid
))) + '.tbn'
334 # Add songs to directory
335 def _add_songs_directory(self
, songs
, trackLabelFormat
=ARTIST_ALBUM_NAME_LABEL
):
337 xbmc
.log("Found " + str(n
) + " songs...")
341 item
= self
._get
_song
_item
(song
, trackLabelFormat
)
342 coverart
= item
.getProperty('coverart')
347 u
=sys
.argv
[0]+"?mode="+str(MODE_SONG
)+"&name="+urllib
.quote_plus(songname
)+"&id="+str(songid
) \
348 +"&album="+urllib
.quote_plus(songalbum
) \
349 +"&artist="+urllib
.quote_plus(songartist
) \
350 +"&coverart="+urllib
.quote_plus(coverart
)
351 fav
=sys
.argv
[0]+"?mode="+str(MODE_FAVORITE
)+"&name="+urllib
.quote_plus(songname
)+"&id="+str(songid
)
353 menuItems
.append(("Grooveshark favorite", "XBMC.RunPlugin("+fav
+")"))
354 item
.addContextMenuItems(menuItems
, replaceItems
=False)
355 xbmcplugin
.addDirectoryItem(handle
=int(sys
.argv
[1]),url
=u
,listitem
=item
,isFolder
=False, totalItems
=n
)
358 xbmcplugin
.setContent(self
._handle
, 'songs')
359 xbmcplugin
.setPluginFanart(int(sys
.argv
[1]), self
.fanImg
)
361 # Add albums to directory
362 def _add_albums_directory(self
, albums
):
364 xbmc
.log("Found " + str(n
) + " albums...")
368 albumArtistName
= album
[0]
371 albumImage
= self
._get
_icon
(album
[4], 'album-' + str(albumID
))
372 self
._add
_dir
(albumName
+ " - " + albumArtistName
, '', MODE_ALBUM
, albumImage
, albumID
, n
)
374 xbmcplugin
.setContent(self
._handle
, 'albums')
375 xbmcplugin
.addSortMethod(self
._handle
, xbmcplugin
.SORT_METHOD_ALBUM_IGNORE_THE
)
376 xbmcplugin
.setPluginFanart(int(sys
.argv
[1]), self
.fanImg
)
378 # Add artists to directory
379 def _add_artists_directory(self
, artists
):
381 xbmc
.log("Found " + str(n
) + " artists...")
385 artistName
= artist
[0]
387 self
._add
_dir
(artistName
, '', MODE_ARTIST
, self
.artistImg
, artistID
, n
)
389 xbmcplugin
.setContent(self
._handle
, 'artists')
390 xbmcplugin
.addSortMethod(self
._handle
, xbmcplugin
.SORT_METHOD_ARTIST_IGNORE_THE
)
391 xbmcplugin
.setPluginFanart(int(sys
.argv
[1]), self
.fanImg
)
393 # Add playlists to directory
394 def _add_playlists_directory(self
, playlists
):
396 xbmc
.log("Found " + str(n
) + " playlists...")
399 playlist
= playlists
[i
]
400 playlistName
= playlist
[0]
401 playlistID
= playlist
[1]
402 dir = self
._add
_dir
(playlistName
, '', MODE_PLAYLIST
, self
.playlistImg
, playlistID
, n
)
404 xbmcplugin
.setContent(self
._handle
, 'files')
405 xbmcplugin
.addSortMethod(self
._handle
, xbmcplugin
.SORT_METHOD_LABEL
)
406 xbmcplugin
.setPluginFanart(int(sys
.argv
[1]), self
.fanImg
)
408 # Add whatever directory
409 def _add_dir(self
, name
, url
, mode
, iconimage
, id, items
=1):
411 u
=sys
.argv
[0]+"?mode="+str(mode
)+"&name="+urllib
.quote_plus(name
)+"&id="+str(id)
412 dir=xbmcgui
.ListItem(name
, iconImage
=iconimage
, thumbnailImage
=iconimage
)
413 dir.setInfo( type="Music", infoLabels
={ "title": name
} )
414 return xbmcplugin
.addDirectoryItem(handle
=int(sys
.argv
[1]),url
=u
,listitem
=dir,isFolder
=True, totalItems
=items
)
417 # Parse URL parameters
420 paramstring
=sys
.argv
[2]
421 xbmc
.log(paramstring
)
422 if len(paramstring
)>=2:
424 cleanedparams
=params
.replace('?','')
425 if (params
[len(params
)-1]=='/'):
426 params
=params
[0:len(params
)-2]
427 pairsofparams
=cleanedparams
.split('&')
429 for i
in range(len(pairsofparams
)):
431 splitparams
=pairsofparams
[i
].split('=')
432 if (len(splitparams
))==2:
433 param
[splitparams
[0]]=splitparams
[1]
437 grooveshark
= Groveshark();
441 try: mode
=int(params
["mode"])
444 try: id=int(params
["id"])
447 # Call function for URL
449 grooveshark
.categories()
451 elif mode
==MODE_SEARCH_SONGS
:
452 grooveshark
.searchSongs()
454 elif mode
==MODE_SEARCH_ALBUMS
:
455 grooveshark
.searchAlbums()
457 elif mode
==MODE_SEARCH_ARTISTS
:
458 grooveshark
.searchArtists()
460 elif mode
==MODE_SEARCH_ARTISTS_ALBUMS
:
461 grooveshark
.searchArtistsAlbums()
463 elif mode
==MODE_SEARCH_PLAYLISTS
:
464 grooveshark
.searchPlaylists()
466 elif mode
==MODE_POPULAR_SONGS
:
467 grooveshark
.popularSongs()
469 elif mode
==MODE_FAVORITES
:
470 grooveshark
.favorites()
472 elif mode
==MODE_PLAYLISTS
:
473 grooveshark
.playlists()
475 elif mode
==MODE_SONG
:
476 try: name
=urllib
.unquote_plus(params
["name"])
478 try: album
=urllib
.unquote_plus(params
["album"])
480 try: artist
=urllib
.unquote_plus(params
["artist"])
482 try: coverart
=urllib
.unquote_plus(params
["coverart"])
484 song
= grooveshark
.songItem(id, name
, album
, artist
, coverart
)
485 grooveshark
.playSong(song
)
487 elif mode
==MODE_ARTIST
:
488 grooveshark
.artist(id)
490 elif mode
==MODE_ALBUM
:
491 grooveshark
.album(id)
493 elif mode
==MODE_PLAYLIST
:
494 grooveshark
.playlist(id)
496 elif mode
==MODE_FAVORITE
:
497 grooveshark
.favorite(id)
500 xbmcplugin
.endOfDirectory(int(sys
.argv
[1]))