From 36cc00d74fe199a00a95a2940a5989b48a33930f Mon Sep 17 00:00:00 2001 From: stephendenham Date: Tue, 14 Dec 2010 15:29:20 +0000 Subject: [PATCH] Add Grooveshark playlist support. git-svn-id: svn://svn.code.sf.net/p/xbmc-groove/code@12 2dec19e3-eb1d-4749-8193-008c8bba0994 --- addon.xml | 2 +- changelog.txt | 4 + default.py | 135 +++++++++++++++++++++++---------- description.xml | 2 +- resources/img/popular.png | Bin 263190 -> 0 bytes resources/img/popularSongs.png | Bin 0 -> 41743 bytes resources/lib/GrooveAPI.py | 10 +++ 7 files changed, 113 insertions(+), 40 deletions(-) delete mode 100644 resources/img/popular.png create mode 100644 resources/img/popularSongs.png diff --git a/addon.xml b/addon.xml index 02eae09..4792124 100644 --- a/addon.xml +++ b/addon.xml @@ -1,6 +1,6 @@ + version="0.1.0" provider-name="Stephen Denham"> diff --git a/changelog.txt b/changelog.txt index 1c91c09..c30d1db 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +0.1.0: + +Grooveshark playlist support. + 0.0.2: Add similar artists function. diff --git a/default.py b/default.py index 0e0261e..6688267 100644 --- a/default.py +++ b/default.py @@ -3,7 +3,7 @@ import urllib, urllib2, re, xbmcplugin, xbmcgui, xbmc, sys, os, time, pprint, sh MODE_SEARCH_SONGS = 1 MODE_SEARCH_ALBUMS = 2 MODE_SEARCH_ARTISTS = 3 -MODE_POPULAR = 4 +MODE_POPULAR_SONGS = 4 MODE_FAVORITES = 5 MODE_PLAYLISTS = 6 MODE_ALBUM = 7 @@ -13,6 +13,9 @@ MODE_SIMILAR_ARTISTS = 10 MODE_SONG = 11 MODE_FAVORITE = 12 MODE_UNFAVORITE = 13 +MODE_MAKE_PLAYLIST = 14 +MODE_REMOVE_PLAYLIST = 15 +MODE_RENAME_PLAYLIST = 16 lastID = 0 @@ -21,7 +24,6 @@ resDir = xbmc.translatePath(os.path.join(baseDir, 'resources')) libDir = xbmc.translatePath(os.path.join(resDir, 'lib')) imgDir = xbmc.translatePath(os.path.join(resDir, 'img')) thumbDir = os.path.join('special://masterprofile/addon_data/', os.path.join(os.path.basename(os.getcwd()), 'thumb')) -favoritesCache = xbmc.translatePath(os.path.join('special://masterprofile/addon_data/', os.path.join(os.path.basename(os.getcwd()), 'favorites.dmp'))) sys.path.append (libDir) from GrooveAPI import * @@ -37,7 +39,7 @@ class Groveshark: artistImg = xbmc.translatePath(os.path.join(imgDir, 'artist.png')) favoritesImg = xbmc.translatePath(os.path.join(imgDir, 'favorites.png')) playlistImg = xbmc.translatePath(os.path.join(imgDir, 'playlist.png')) - popularImg = xbmc.translatePath(os.path.join(imgDir, 'popular.png')) + popularSongsImg = xbmc.translatePath(os.path.join(imgDir, 'popularSongs.png')) songImg = xbmc.translatePath(os.path.join(imgDir, 'song.png')) defImg = xbmc.translatePath(os.path.join(imgDir, 'default.tbn')) fanImg = xbmc.translatePath(os.path.join(baseDir, 'fanart.png')) @@ -67,7 +69,7 @@ class Groveshark: self._add_dir('Search songs', '', MODE_SEARCH_SONGS, self.songImg, 0) self._add_dir('Search albums', '', MODE_SEARCH_ALBUMS, self.albumImg, 0) self._add_dir('Search artists', '', MODE_SEARCH_ARTISTS, self.artistImg, 0) - self._add_dir('Popular', '', MODE_POPULAR, self.popularImg, 0) + self._add_dir('Popular songs', '', MODE_POPULAR_SONGS, self.popularSongsImg, 0) if (userid != 0): self._add_dir('Favorites', '', MODE_FAVORITES, self.favoritesImg, 0) self._add_dir('Playlists', '', MODE_PLAYLISTS, self.playlistImg, 0) @@ -106,15 +108,17 @@ class Groveshark: self.categories() def favorites(self): - favorites = self._get_favorites() - if (len(favorites) > 0): - self._add_songs_directory(favorites) - else: - dialog = xbmcgui.Dialog() - dialog.ok('Grooveshark', 'You have no favorites.') - self.categories() + userid = self._get_login() + if (userid != 0): + favorites = groovesharkApi.userGetFavoriteSongs(userid) + if (len(favorites) > 0): + self._add_songs_directory(favorites) + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You have no favorites.') + self.categories() - def popular(self): + def popularSongs(self): popular = groovesharkApi.popularGetSongs(limit = self.songsearchlimit) if (len(popular) > 0): self._add_songs_directory(popular) @@ -122,6 +126,24 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark', 'No popular songs.') self.categories() + + def popularAlbums(self): + popular = groovesharkApi.popularGetAlbums(limit = self.albumsearchlimit) + if (len(popular) > 0): + self._add_albums_directory(popular) + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'No popular albums.') + self.categories() + + def popularArtists(self): + popular = groovesharkApi.popularGetArtists(limit = self.artistsearchlimit) + if (len(popular) > 0): + self._add_artists_directory(popular) + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'No popular artists.') + self.categories() def playlists(self): userid = self._get_login() @@ -139,7 +161,6 @@ class Groveshark: if (userid != 0): xbmc.log("Favorite song: " + str(songid)) groovesharkApi.favoriteSong(songID = songid) - os.remove(favoritesCache) else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark', 'You must be logged in', 'to add favorites.') @@ -149,7 +170,6 @@ class Groveshark: if (userid != 0): xbmc.log("Unfavorite song: " + str(songid)) groovesharkApi.unfavoriteSong(songID = songid) - os.remove(favoritesCache) else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark', 'You must be logged in', 'to remove favorites.') @@ -172,8 +192,50 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark', 'No similar artists.') self.categories() + + def makePlaylist(self, albumid, name): + userid = self._get_login() + if (userid != 0): + name_re = re.compile(r'[- ]') + nameTokens = name_re.split("- ") + name = self._get_keyboard(default=nameTokens[1], heading="Playlist name") + album = groovesharkApi.albumGetSongs(albumid, self.songsearchlimit) + songids = [] + for song in album: + songids.append(song[1]) + id = groovesharkApi.playlistCreateUnique(name, songids) + if id == 0: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'Cannot create playlist ', name) + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You must be logged in ', ' to create a playlist.') + + def removePlaylist(self, playlistid, name): + dialog = xbmcgui.Dialog() + if dialog.yesno('Grooveshark', name, 'Delete this playlist?') == True: + userid = self._get_login() + if (userid != 0): + groovesharkApi.playlistDelete(playlistid) + xbmc.executebuiltin("Container.Refresh") + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You must be logged in ', ' to delete a playlist.') + + def renamePlaylist(self, playlistid, name): + userid = self._get_login() + if (userid != 0): + newname = self._get_keyboard(default=name, heading="Playlist name") + if groovesharkApi.playlistRename(playlistid, newname) == 0: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'Cannot rename playlist ', name) + else: + xbmc.executebuiltin("Container.Refresh") + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You must be logged in ', ' to rename a playlist.') - def album(self,albumid): + def album(self, albumid): album = groovesharkApi.albumGetSongs(albumId = albumid, limit = self.songsearchlimit) self._add_songs_directory(album) @@ -214,27 +276,6 @@ class Groveshark: return item - def _get_favorites(self): - favorites = [] - # if the cache does not exist or is older than x hours then reload - if (os.path.isfile(favoritesCache) == False) or (time.time() - os.path.getmtime(favoritesCache) > 3*60*60): - xbmc.log("Refresh favorites cache") - userid = self._get_login() - if (userid != 0): - favorites = groovesharkApi.userGetFavoriteSongs(userid) - f = open(favoritesCache, 'wb') - pickle.dump(favorites, f, protocol=pickle.HIGHEST_PROTOCOL) - f.close() - xbmc.log("Refreshed favorites cache") - # if not old then read from cache - elif os.path.isfile(favoritesCache): - xbmc.log("Existing favorites cache") - f = open(favoritesCache, 'rb') - favorites = pickle.load(f) - f.close() - - return favorites - def _get_keyboard(self, default="", heading="", hidden=False): kb = xbmc.Keyboard(default, heading, hidden) kb.doModal() @@ -370,6 +411,14 @@ class Groveshark: # Codes from http://xbmc-scripting.googlecode.com/svn/trunk/Script%20Templates/common/gui/codes.py menuItems = [] menuItems.append(("Select", "XBMC.executebuiltin(Action(7))")) + if mode == MODE_ALBUM: + mkplaylst=sys.argv[0]+"?mode="+str(MODE_MAKE_PLAYLIST)+"&name="+name+"&id="+str(id) + menuItems.append(("Make Grooveshark playlist", "XBMC.RunPlugin("+mkplaylst+")")) + if mode == MODE_PLAYLIST: + rmplaylst=sys.argv[0]+"?mode="+str(MODE_REMOVE_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id) + menuItems.append(("Delete playlist", "XBMC.RunPlugin("+rmplaylst+")")) + mvplaylst=sys.argv[0]+"?mode="+str(MODE_RENAME_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id) + menuItems.append(("Rename playlist", "XBMC.RunPlugin("+mvplaylst+")")) dir.addContextMenuItems(menuItems, replaceItems=True) return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=dir,isFolder=True, totalItems=items) @@ -424,8 +473,8 @@ elif mode==MODE_SEARCH_ALBUMS: elif mode==MODE_SEARCH_ARTISTS: grooveshark.searchArtists() -elif mode==MODE_POPULAR: - grooveshark.popular() +elif mode==MODE_POPULAR_SONGS: + grooveshark.popularSongs() elif mode==MODE_PLAYLISTS: grooveshark.playlists() @@ -467,5 +516,15 @@ elif mode==MODE_UNFAVORITE: elif mode==MODE_SIMILAR_ARTISTS: grooveshark.similarArtists(lastID) +elif mode==MODE_MAKE_PLAYLIST: + grooveshark.makePlaylist(lastID, name) + +elif mode==MODE_REMOVE_PLAYLIST: + grooveshark.removePlaylist(lastID, name) + +elif mode==MODE_RENAME_PLAYLIST: + grooveshark.renamePlaylist(lastID, name) + + if (mode < MODE_SONG): xbmcplugin.endOfDirectory(int(sys.argv[1])) diff --git a/description.xml b/description.xml index 0bcdf20..ccb00b9 100644 --- a/description.xml +++ b/description.xml @@ -18,7 +18,7 @@ Grooveshark for XBMC. - 0.0.2 + 0.1.0 Ru*FlOS0@q5 zi7)vO#^fc_EUz8%-UdT?E*u@G;AK1>@+p(Wix;O)d%oRHyewD;@r1n&eD9)*E}Ct! zI1wS{h@GIxA-!$VkI}u1$D5JGc2l8V3r(pN3RiW$(7`c^Zb+|cuShPmt$0=qS81%gKStCxu7w z_fQt+zWA0KJMj38KDO^ZH5&Z0ReCSl3cjEJ{`bGX(BARcpyQn>#M5k)$mHpG$CMpU zL$6tSm{yf|S2C>u9H7%7bTT3UufJ(Tr&A&#tU!6N{n5%T1#@*3pq^GEC0F9%1A z8a3)D8zJOxQAEoHezqDrc5Gs=9tj7Z5Dy&$@sJiem1JUa;sFU>#^WI`74Cq1EKO+q z7SE157Ub}e$z}qp^X&Kf3ogF+;w#PJ-|W(r;}8|@VICcsBA#p@Vj&yqpNvmx^ z4$?M*6%2(A7>i>Dx*S>Yn5<}$Y1Yxvi|NRo>;pZ`<29Z+^1vB0X6$Ot{WrGIXiC*l zLS{Pq&kjec4Cqm2^g9P~s*0;iEPNl$Ul^R$?pYzfBX^LSoXcq|Q`ln~4-k<00Sk%JAf%gAN*Ji;@mzg`#y5 zTcFUBz=**{9qC1fVRqAtZPLs`_#g)b3K!qg#0w#^k^|zJ?2KH)@ zL-lH+O(drL$@xNvDNiFF>o`KW&~C{0ap8hWPjSIKo8o&|!*|^|HwKiJ(T?CoUHovfy zy#|c8^Ag9~Q-3G>eS9+$sQ*@mbRP^hQdnvZ{-_Q0@3Yat?ecCBNhis3+;N8lP_y8L=!?+GIxIPu3x zqO|}f$DWCS=DhFNrLR~5iN9_``Q__ z{p=o=K&)=6(!!);dZA2FT+Y^tOiVXME3)0s>o0-+66i01{u1aff&LQcFM<9N=r4i( z66i01{u1aff&LQcFM<9N=r4i(5@@aju2}TNf3P3_M^2wI>4ViZ2Rt!gb1jpruGKHO dQkB4g8+>Ns?!QYmAk)*QzJJPvlRtXa{|DH;2WS8Q diff --git a/resources/img/popularSongs.png b/resources/img/popularSongs.png new file mode 100644 index 0000000000000000000000000000000000000000..e2c18f32781144c8d9062570864b3be37a3e23b5 GIT binary patch literal 41743 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 literal 0 HcmV?d00001 diff --git a/resources/lib/GrooveAPI.py b/resources/lib/GrooveAPI.py index 8cfa941..b92247f 100644 --- a/resources/lib/GrooveAPI.py +++ b/resources/lib/GrooveAPI.py @@ -284,6 +284,16 @@ class GrooveAPI: return 0 else: return 0 + + def playlistCreateUnique(self, name, songIds): + if self.loggedIn == 1: + result = self.callRemote("playlist.createunique", {"name": name, "songIDs": songIds}) + if 'result' in result: + return result['result']['playlistID'] + else: + return 0 + else: + return 0 def playlistGetSongs(self, playlistId, limit=25): result = self.callRemote("playlist.getSongs", {"playlistID": playlistId}) -- 2.20.1