From: stephendenham Date: Fri, 24 Dec 2010 13:31:47 +0000 (+0000) Subject: Big song listing performance improvement. X-Git-Url: https://git.hcoop.net/clinton/xbmc-groove.git/commitdiff_plain/e278f4743688d14afc318624933cad799a87c466 Big song listing performance improvement. git-svn-id: svn://svn.code.sf.net/p/xbmc-groove/code@23 2dec19e3-eb1d-4749-8193-008c8bba0994 --- diff --git a/addon.xml b/addon.xml index 537ce1a..fd9e4a8 100644 --- a/addon.xml +++ b/addon.xml @@ -1,6 +1,6 @@ + version="0.1.5" provider-name="Stephen Denham"> diff --git a/changelog.txt b/changelog.txt index 007459e..6432b49 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +0.1.5: + +Big song listing performance improvement. + 0.1.4: Improve song icon performance. diff --git a/default.py b/default.py index e9f87de..884d412 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,14 @@ 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 * +from GrooveAPI import GrooveAPI groovesharkApi = GrooveAPI() 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=[]): @@ -95,12 +96,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 +133,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 +143,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 +166,7 @@ class Groveshark: else: self.categories() + # Search for albums def searchAlbums(self): query = self._get_keyboard(default="", heading="Search albums") if (query != ''): @@ -177,6 +180,7 @@ class Groveshark: else: self.categories() + # Search for artists def searchArtists(self): query = self._get_keyboard(default="", heading="Search artists") if (query != ''): @@ -190,6 +194,7 @@ class Groveshark: else: self.categories() + # Get my favorites def favorites(self): userid = self._get_login() if (userid != 0): @@ -201,6 +206,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 +216,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 +231,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 +242,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.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 +269,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 +278,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 +300,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 +378,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 +415,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 +431,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 +448,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 +458,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] @@ -476,18 +487,15 @@ class Groveshark: 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...") - progressDialog = xbmcgui.DialogProgress() - progressDialog.create('Grooveshark XBMC', 'Fetching...', '0 of ' + str(n)) - 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] @@ -495,16 +503,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) @@ -518,18 +524,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) + xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=item,isFolder=False, totalItems=n) i = i + 1 - progressDialog.update(int((i*100)/n), 'Fetching...', str(i) + ' of ' + str(n)) - if progressDialog.iscanceled(): - break - progressDialog.close() - 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...") @@ -547,7 +548,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...") @@ -561,7 +563,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...") @@ -576,10 +579,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) @@ -589,13 +596,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('?','') @@ -608,26 +618,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() @@ -643,12 +652,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 @@ -676,8 +685,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: @@ -700,5 +710,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])) diff --git a/description.xml b/description.xml index 7a617ce..e2e5048 100644 --- a/description.xml +++ b/description.xml @@ -18,7 +18,7 @@ Grooveshark XBMC. - 0.1.4 + 0.1.5