X-Git-Url: https://git.hcoop.net/clinton/xbmc-groove.git/blobdiff_plain/aa0c1263c8a5bc58cfb233356e2338bf2649fd9c..e58dda71a07558849b55f1f9138a4f238afb275a:/default.py diff --git a/default.py b/default.py index 695ce9c..5c98792 100644 --- a/default.py +++ b/default.py @@ -1,4 +1,4 @@ -import urllib, urllib2, re, xbmcplugin, xbmcgui, xbmc, sys, os, time, shutil, xbmcaddon +import urllib, sys, os, shutil, re, xbmcaddon, xbmcplugin, xbmcgui, xbmc MODE_SEARCH_SONGS = 1 MODE_SEARCH_ALBUMS = 2 @@ -34,7 +34,7 @@ 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')) baseModeUrl = 'plugin://plugin.audio.groove/' -playlistUrl = baseModeUrl + '?url=&mode=' + str(MODE_PLAYLIST) +playlistUrl = baseModeUrl + '?mode=' + str(MODE_PLAYLIST) playlistsUrl = baseModeUrl + '?mode=' + str(MODE_PLAYLISTS) favoritesUrl = baseModeUrl + '?mode=' + str(MODE_FAVORITES) @@ -42,13 +42,20 @@ thumbDef = os.path.join(os.path.basename(os.getcwd()), 'default.tbn') listBackground = os.path.join(imgDir, 'listbackground.png') sys.path.append (libDir) -from GrooveAPI import * -groovesharkApi = GrooveAPI() +from GrooveAPI import GrooveAPI +try: + groovesharkApi = GrooveAPI() +except: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark XBMC', 'Unable to connect with Grooveshark.', 'Please try again later') + sys.exit(-1) + class _Info: def __init__( self, *args, **kwargs ): self.__dict__.update( kwargs ) - + +# Window dialog to select a grooveshark playlist class GroovesharkPlaylistSelect(xbmcgui.WindowDialog): def __init__(self, items=[]): @@ -63,7 +70,7 @@ class GroovesharkPlaylistSelect(xbmcgui.WindowDialog): self.imgBg = xbmcgui.ControlImage(x+gap, 5*gap+y, w-2*gap, h-5*gap, listBackground) self.addControl(self.imgBg) - self.playlistControl = xbmcgui.ControlList(2*gap+x, y+3*gap+30, w-4*gap, h-10*gap, textColor='0xFFFFFFFF', selectedColor='0xFFFF4242', itemTextYOffset=0, itemHeight=30, alignmentY = 0) + self.playlistControl = xbmcgui.ControlList(2*gap+x, y+3*gap+30, w-4*gap, h-10*gap, textColor='0xFFFFFFFF', selectedColor='0xFFFF4242', itemTextYOffset=0, itemHeight=50, alignmentY = 0) self.addControl(self.playlistControl) self.lastPos = 0 @@ -95,12 +102,13 @@ class GroovesharkPlaylistSelect(xbmcgui.WindowDialog): self.lastPos = pos self.isSelecting = False - # Control + # Control - select def onControl(self, control): if control == self.playlistControl: self.selected = self.playlistControl.getSelectedPosition() self.close() - + + # Action - close or up/down def onAction(self, action): if action == ACTION_PREVIOUS_MENU: self.selected = -1 @@ -131,10 +139,9 @@ class Groveshark: def __init__( self ): self._handle = int(sys.argv[1]) + # Top-level menu def categories(self): - xbmc.log(self.username + ", limits: " + str(self.songsearchlimit) + ", " + str(self.albumsearchlimit) + ", " + str(self.artistsearchlimit)) - self.userid = self._get_login() # Setup @@ -142,14 +149,15 @@ class Groveshark: if os.path.isdir(thumbDir) == False: os.makedirs(thumbDir) - 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('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 songs', '', MODE_POPULAR_SONGS, self.popularSongsImg, 0) if (self.userid != 0): self._add_dir('Favorites', '', MODE_FAVORITES, self.favoritesImg, 0) self._add_dir('Playlists', '', MODE_PLAYLISTS, self.playlistImg, 0) - + + # Search for songs def searchSongs(self): query = self._get_keyboard(default="", heading="Search songs") if (query != ''): @@ -164,6 +172,7 @@ class Groveshark: else: self.categories() + # Search for albums def searchAlbums(self): query = self._get_keyboard(default="", heading="Search albums") if (query != ''): @@ -177,6 +186,7 @@ class Groveshark: else: self.categories() + # Search for artists def searchArtists(self): query = self._get_keyboard(default="", heading="Search artists") if (query != ''): @@ -190,6 +200,7 @@ class Groveshark: else: self.categories() + # Get my favorites def favorites(self): userid = self._get_login() if (userid != 0): @@ -201,6 +212,7 @@ class Groveshark: dialog.ok('Grooveshark XBMC', 'You have no favorites.') self.categories() + # Get popular songs def popularSongs(self): popular = groovesharkApi.popularGetSongs(limit = self.songsearchlimit) if (len(popular) > 0): @@ -210,24 +222,7 @@ class Groveshark: dialog.ok('Grooveshark XBMC', '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 XBMC', '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 XBMC', 'No popular artists.') - self.categories() - + # Get my playlists def playlists(self): userid = self._get_login() if (userid != 0): @@ -242,7 +237,7 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to see your Grooveshark playlists.') - + # Make songs a favorite def favorite(self, songid): userid = self._get_login() if (userid != 0): @@ -253,18 +248,21 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in', 'to add favorites.') - def unfavorite(self, songid, prevMode): + # Remove song from favorites + def unfavorite(self, songid, prevMode=0): userid = self._get_login() if (userid != 0): xbmc.log("Unfavorite song: " + str(songid) + ', previous mode was ' + str(prevMode)) groovesharkApi.unfavoriteSong(songID = songid) xbmc.executebuiltin('XBMC.Notification(Grooveshark XBMC, Removed from Grooveshark favorites, 1000, ' + thumbDef + ')') + # Refresh to remove item from directory if (int(prevMode) == MODE_FAVORITES): - xbmc.executebuiltin("Container.Update(" + favoritesUrl + ")") + xbmc.executebuiltin("Container.Refresh(" + favoritesUrl + ")") else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in', 'to remove Grooveshark favorites.') + # 'Frown' a song def frown(self, songid): userid = self._get_login() if (userid != 0): @@ -277,6 +275,7 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in', 'to frown a Grooveshark song.') + # Find similar artists to searched artist def similarArtists(self, artistId): similar = groovesharkApi.artistGetSimilar(artistId, limit = self.artistsearchlimit) if (len(similar) > 0): @@ -285,12 +284,13 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'No similar artists.') self.categories() - + + # Make a playlist from an album def makePlaylist(self, albumid, name): userid = self._get_login() if (userid != 0): re.split(' - ',name,1) - nameTokens = re.split(' - ',name,1) + nameTokens = re.split(' - ',name,1) # suggested name name = self._get_keyboard(default=nameTokens[0], heading="Grooveshark playlist name") if name != '': groovesharkApi.setRemoveDuplicates(True) @@ -306,45 +306,55 @@ class Groveshark: else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to create a Grooveshark playlist.') - + + # Rename a playlist + def renamePlaylist(self, playlistid, name): + userid = self._get_login() + if (userid != 0): + newname = self._get_keyboard(default=name, heading="Grooveshark playlist name") + if newname == '': + return + elif groovesharkApi.playlistRename(playlistid, newname) == 0: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark XBMC', 'Cannot rename Grooveshark playlist ', name) + else: + # Refresh to show new item name + xbmc.executebuiltin("Container.Refresh") + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to rename a Grooveshark playlist.') + + # Remove a playlist def removePlaylist(self, playlistid, name): dialog = xbmcgui.Dialog() if dialog.yesno('Grooveshark XBMC', name, 'Delete this Grooveshark playlist?') == True: userid = self._get_login() if (userid != 0): - groovesharkApi.playlistDelete(playlistid) - xbmc.executebuiltin("Container.Refresh(" + playlistsUrl + ")") - else: - dialog = xbmcgui.Dialog() - dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to delete a Grooveshark playlist.') - - def removePlaylistSong(self, playlistid, playlistname, songpos): - dialog = xbmcgui.Dialog() - if dialog.yesno('Grooveshark XBMC', 'Delete this song from the Grooveshark playlist?') == True: - userid = self._get_login() - if (userid != 0): - if groovesharkApi.playlistDeleteSong(playlistid, songpos) == 0: + if groovesharkApi.playlistDelete(playlistid) == 0: dialog = xbmcgui.Dialog() - dialog.ok('Grooveshark XBMC', 'Failed to remove ', ' song from Grooveshark playlist.') + dialog.ok('Grooveshark XBMC', 'Cannot remove Grooveshark playlist ', name) else: - xbmc.executebuiltin("Container.Refresh(" + playlistUrl + "&id="+str(playlistid) + "&name=" + playlistname + ",replace)") + # Refresh to remove item from directory + xbmc.executebuiltin("Container.Refresh(" + playlistsUrl + ")") else: dialog = xbmcgui.Dialog() - dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to delete a song from a Grooveshark playlist.') + dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to delete a Grooveshark playlist.') + # Add song to playlist def addPlaylistSong(self, songid): userid = self._get_login() if (userid != 0): playlists = groovesharkApi.userGetPlaylists() if (len(playlists) > 0): ret = 0 + # Select the playlist playlistSelect = GroovesharkPlaylistSelect(items=playlists) playlistSelect.setFocus(playlistSelect.playlistControl) playlistSelect.doModal() i = playlistSelect.selected del playlistSelect if i > -1: - # New playlist + # Add a new playlist if i >= len(playlists): name = self._get_keyboard(default='', heading="Grooveshark playlist name") if name != '': @@ -374,30 +384,34 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to add a song to a Grooveshark playlist.') - def renamePlaylist(self, playlistid, name): - userid = self._get_login() - if (userid != 0): - newname = self._get_keyboard(default=name, heading="Grooveshark playlist name") - if newname == '': - return - elif groovesharkApi.playlistRename(playlistid, newname) == 0: - dialog = xbmcgui.Dialog() - dialog.ok('Grooveshark XBMC', 'Cannot rename Grooveshark playlist ', name) + # Remove song from playlist + def removePlaylistSong(self, playlistid, playlistname, songpos): + dialog = xbmcgui.Dialog() + if dialog.yesno('Grooveshark XBMC', 'Delete this song from the Grooveshark playlist?') == True: + userid = self._get_login() + if (userid != 0): + if groovesharkApi.playlistDeleteSong(playlistid, songpos) == 0: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark XBMC', 'Failed to remove ', ' song from Grooveshark playlist.') + else: + # Refresh to remove item from directory + xbmc.executebuiltin("Container.Refresh(" + playlistUrl + "&id="+str(playlistid) + "&name=" + playlistname + ")") else: - xbmc.executebuiltin("Container.Refresh") - else: - dialog = xbmcgui.Dialog() - dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to rename a Grooveshark playlist.') - + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark XBMC', 'You must be logged in ', ' to delete a song from a Grooveshark playlist.') + + # Show selected album def album(self, albumid): groovesharkApi.setRemoveDuplicates(True) album = groovesharkApi.albumGetSongs(albumId = albumid, limit = self.songsearchlimit) self._add_songs_directory(album) - + + # Show selected artist def artist(self, artistid): albums = groovesharkApi.artistGetAlbums(artistId = artistid, limit = self.albumsearchlimit) self._add_albums_directory(albums, artistid) + # Show selected playlist def playlist(self, playlistid, playlistname): userid = self._get_login() if (userid != 0): @@ -407,13 +421,15 @@ class Groveshark: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'You must be logged in', 'to get Grooveshark playlists.') + # Play a song def playSong(self, item): - url = item.getProperty('url') + url = groovesharkApi.getStreamURL(item.getProperty('id')) + item.setPath(url) xbmc.log("Playing: " + url) xbmcplugin.setResolvedUrl(handle=int(sys.argv[1]), succeeded=True, listitem=item) + # Make a song directory item def songItem(self, id, name, album, artist, duration, thumb, image): - url = groovesharkApi.getStreamURL(id) # Only try to get the image if image != "": songImg = self._get_icon(image, 'song-' + str(id) + "-image") @@ -421,16 +437,16 @@ class Groveshark: else: songThm = self._get_icon(thumb, 'song-' + str(id) + "-thumb") songImg = songThm - item = xbmcgui.ListItem(label = artist + " - " + album + " - " + name, path=url, thumbnailImage=songThm, iconImage=songImg) + item = xbmcgui.ListItem(label = artist + " - " + album + " - " + name, thumbnailImage=songThm, iconImage=songImg) item.setInfo( type="music", infoLabels={ "title": name, "duration": duration, "album": album, "artist": artist} ) item.setProperty('mimetype', 'audio/mpeg') item.setProperty("IsPlayable", "true") - item.setProperty('url', url) + item.setProperty('id', str(id)) item.setProperty('thumb', songThm) item.setProperty('image', songImg) - return item + # Get keyboard input def _get_keyboard(self, default="", heading="", hidden=False): kb = xbmc.Keyboard(default, heading, hidden) kb.doModal() @@ -438,6 +454,7 @@ class Groveshark: return unicode(kb.getText(), "utf-8") return '' + # Login to grooveshark def _get_login(self): if (self.username == "" or self.password == ""): dialog = xbmcgui.Dialog() @@ -447,13 +464,13 @@ class Groveshark: if self.userid == 0: uid = groovesharkApi.loginExt(self.username, self.password) if (uid != 0): - xbmc.log("Logged in") return uid else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark XBMC', 'Unable to login.', 'Check username and password in settings.') return 0 + # Get a song directory item def _get_song_item(self, song): name = song[0] id = song[1] @@ -473,20 +490,18 @@ class Groveshark: loc = urllib.URLopener() loc.retrieve(url, localThumb) except: - xbmc.log('URL download failed of ' + url + ' to ' + localThumb) - return(self.defImg) + shutil.copy2(self.defImg, localThumb) return os.path.join(os.path.join(thumbDir, str(id))) + '.tbn' - + + # Add songs to directory def _add_songs_directory(self, songs, playlistid=0, playlistname='', isFavorites=False): n = len(songs) xbmc.log("Found " + str(n) + " songs...") - dirItems = [] i = 0 while i < n: song = songs[i] item = self._get_song_item(song) - songurl = item.getProperty('url') songthumb = item.getProperty('thumb') songimage = item.getProperty('image') songname = song[0] @@ -494,16 +509,14 @@ class Groveshark: songduration = song[2] songalbum = song[3] songartist = song[6] - u=sys.argv[0]+"?url="+urllib.quote_plus(songurl) \ - +"&mode="+str(MODE_SONG)+"&name="+urllib.quote_plus(songname)+"&id=" \ - +str(songid) \ + u=sys.argv[0]+"?mode="+str(MODE_SONG)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid) \ +"&album="+urllib.quote_plus(songalbum) \ +"&artist="+urllib.quote_plus(songartist) \ +"&duration="+str(songduration) \ +"&thumb="+urllib.quote_plus(songthumb) \ +"&image="+urllib.quote_plus(songimage) - fav=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_FAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid) - unfav=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&mode="+str(MODE_UNFAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid)+"&prevmode=" + fav=sys.argv[0]+"?mode="+str(MODE_FAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid) + unfav=sys.argv[0]+"?mode="+str(MODE_UNFAVORITE)+"&name="+urllib.quote_plus(songname)+"&id="+str(songid)+"&prevmode=" menuItems = [] if isFavorites == True: unfav = unfav +str(MODE_FAVORITES) @@ -517,17 +530,13 @@ class Groveshark: addplaylstsong=sys.argv[0]+"?id="+str(songid)+"&mode="+str(MODE_ADD_PLAYLIST_SONG) menuItems.append(("Add to Grooveshark playlist", "XBMC.RunPlugin("+addplaylstsong+")")) item.addContextMenuItems(menuItems, replaceItems=False) - dirItem = (u, item, False) - dirItems.append(dirItem) - if i % 5 == 0: - xbmcplugin.addDirectoryItems(int(sys.argv[1]), dirItems ,n) - dirItems = [] + xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=item,isFolder=False, totalItems=n) i = i + 1 - - xbmcplugin.addDirectoryItems(int(sys.argv[1]), dirItems ,n) + xbmcplugin.setContent(self._handle, 'songs') xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg) - + + # Add albums to directory def _add_albums_directory(self, albums, artistid=0): n = len(albums) xbmc.log("Found " + str(n) + " albums...") @@ -545,7 +554,8 @@ class Groveshark: xbmcplugin.setContent(self._handle, 'albums') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ALBUM_IGNORE_THE) xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg) - + + # Add artists to directory def _add_artists_directory(self, artists): n = len(artists) xbmc.log("Found " + str(n) + " artists...") @@ -559,7 +569,8 @@ class Groveshark: xbmcplugin.setContent(self._handle, 'artists') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ARTIST_IGNORE_THE) xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg) - + + # Add playlists to directory def _add_playlists_directory(self, playlists): n = len(playlists) xbmc.log("Found " + str(n) + " playlists...") @@ -574,10 +585,14 @@ class Groveshark: xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_PLAYLIST_ORDER) xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg) + # Add whatever directory def _add_dir(self, name, url, mode, iconimage, id, items=1): - u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&id="+str(id) + + u=sys.argv[0]+"?mode="+str(mode)+"&name="+urllib.quote_plus(name)+"&id="+str(id) dir=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage=iconimage) dir.setInfo( type="Music", infoLabels={ "title": name } ) + + # Custom menu items menuItems = [] if mode == MODE_ALBUM: mkplaylst=sys.argv[0]+"?mode="+str(MODE_MAKE_PLAYLIST)+"&name="+name+"&id="+str(id) @@ -587,13 +602,16 @@ class Groveshark: menuItems.append(("Delete Grooveshark playlist", "XBMC.RunPlugin("+rmplaylst+")")) mvplaylst=sys.argv[0]+"?mode="+str(MODE_RENAME_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id) menuItems.append(("Rename Grooveshark playlist", "XBMC.RunPlugin("+mvplaylst+")")) + dir.addContextMenuItems(menuItems, replaceItems=False) return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=dir,isFolder=True, totalItems=items) - + +# Parse URL parameters def get_params(): param=[] paramstring=sys.argv[2] + xbmc.log(paramstring) if len(paramstring)>=2: params=sys.argv[2] cleanedparams=params.replace('?','') @@ -606,26 +624,25 @@ def get_params(): splitparams=pairsofparams[i].split('=') if (len(splitparams))==2: param[splitparams[0]]=splitparams[1] - print param return param +# Main grooveshark = Groveshark(); - + params=get_params() -url=None -name=None mode=None -id=None - -try: url=urllib.unquote_plus(params["url"]) -except: pass -try: name=urllib.unquote_plus(params["name"]) -except: pass try: mode=int(params["mode"]) except: pass -try: id=int(params["id"]) -except: pass +if mode > MODE_FAVORITES: + name=None + id=None + try: name=urllib.unquote_plus(params["name"]) + except: pass + try: id=int(params["id"]) + except: pass + +# Call function for URL if mode==None: grooveshark.categories() @@ -641,12 +658,12 @@ elif mode==MODE_SEARCH_ARTISTS: elif mode==MODE_POPULAR_SONGS: grooveshark.popularSongs() -elif mode==MODE_PLAYLISTS: - grooveshark.playlists() - elif mode==MODE_FAVORITES: grooveshark.favorites() +elif mode==MODE_PLAYLISTS: + grooveshark.playlists() + elif mode==MODE_SONG: try: album=urllib.unquote_plus(params["album"]) except: pass @@ -674,8 +691,9 @@ elif mode==MODE_FAVORITE: grooveshark.favorite(id) elif mode==MODE_UNFAVORITE: - try: prevMode=urllib.unquote_plus(params["prevmode"]) - except: pass + try: prevMode=int(urllib.unquote_plus(params["prevmode"])) + except: + prevMode = 0 grooveshark.unfavorite(id, prevMode) elif mode==MODE_SIMILAR_ARTISTS: @@ -698,5 +716,5 @@ elif mode==MODE_REMOVE_PLAYLIST_SONG: elif mode==MODE_ADD_PLAYLIST_SONG: grooveshark.addPlaylistSong(id) -if (mode < MODE_SONG): +if mode < MODE_SONG: xbmcplugin.endOfDirectory(int(sys.argv[1]))