X-Git-Url: https://git.hcoop.net/clinton/xbmc-groove.git/blobdiff_plain/0b11d3f3d677a7ac3566449f16257d5ae5bee062..6d37cafde9361f0440dad54d421817c5b4de4004:/default.py diff --git a/default.py b/default.py index 62d8938..11e53a7 100644 --- a/default.py +++ b/default.py @@ -16,7 +16,7 @@ # along with xbmc-groove. If not, see . -import urllib, sys, os, shutil, re, pickle, time, tempfile, xbmcaddon, xbmcplugin, xbmcgui, xbmc +import urllib, urllib2, sys, os, shutil, re, pickle, time, traceback, xbmcaddon, xbmcplugin, xbmcgui, xbmc __addon__ = xbmcaddon.Addon('plugin.audio.groove') __addonname__ = __addon__.getAddonInfo('name') @@ -26,6 +26,7 @@ __version__ = __addon__.getAddonInfo('version') __language__ = __addon__.getLocalizedString __debugging__ = __addon__.getSetting('debug') +# Directory listings must be < MODE_SONG MODE_SEARCH_SONGS = 1 MODE_SEARCH_ALBUMS = 2 MODE_SEARCH_ARTISTS = 3 @@ -40,14 +41,16 @@ MODE_ARTIST = 11 MODE_PLAYLIST = 12 MODE_SONG_PAGE = 13 MODE_SIMILAR_ARTISTS = 14 -MODE_SONG = 15 -MODE_FAVORITE = 16 -MODE_UNFAVORITE = 17 -MODE_MAKE_PLAYLIST = 18 -MODE_REMOVE_PLAYLIST = 19 -MODE_RENAME_PLAYLIST = 20 -MODE_REMOVE_PLAYLIST_SONG = 21 -MODE_ADD_PLAYLIST_SONG = 22 +MODE_ARTIST_POPULAR_FROM_ALBUMS = 15 +MODE_SONG = 150 + +MODE_FAVORITE = 160 +MODE_UNFAVORITE = 170 +MODE_MAKE_PLAYLIST = 180 +MODE_REMOVE_PLAYLIST = 190 +MODE_RENAME_PLAYLIST = 200 +MODE_REMOVE_PLAYLIST_SONG = 210 +MODE_ADD_PLAYLIST_SONG = 220 ACTION_MOVE_LEFT = 1 ACTION_MOVE_UP = 3 @@ -76,6 +79,7 @@ resDir = xbmc.translatePath(os.path.join(baseDir, 'resources')) libDir = xbmc.translatePath(os.path.join(resDir, 'lib')) imgDir = xbmc.translatePath(os.path.join(resDir, 'img')) cacheDir = os.path.join(xbmc.translatePath('special://masterprofile/addon_data/'), os.path.basename(baseDir)) +tempDir = xbmc.translatePath('special://temp') thumbDirName = 'thumb' thumbDir = os.path.join(xbmc.translatePath('special://masterprofile/addon_data/'), os.path.basename(baseDir), thumbDirName) @@ -99,10 +103,14 @@ else: __debugging__ = False try: - groovesharkApi = GrooveAPI(__debugging__) + groovesharkApi = GrooveAPI(__debugging__, tempDir) if groovesharkApi.pingService() != True: raise StandardError(__language__(30007)) except: + print "Exception on initialisation" + print '-'*60 + traceback.print_exc() + print '-'*60 dialog = xbmcgui.Dialog(__language__(30008),__language__(30009),__language__(30010)) dialog.ok(__language__(30008),__language__(30009)) sys.exit(-1) @@ -144,7 +152,8 @@ 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=50, alignmentY = 0) + self.playlistControl = xbmcgui.ControlList(2*gap+x, y+3*gap+30, w-4*gap, h-10*gap, textColor='0xFFFFFFFF', selectedColor='0xFFFF4242') + self.playlistControl.setItemHeight(50) self.addControl(self.playlistControl) self.lastPos = 0 @@ -349,12 +358,14 @@ class Grooveshark: if (query != ''): artists = groovesharkApi.getArtistSearchResults(query, limit = self.artistsearchlimit) if (len(artists) > 0): - artist = artists[0] + # check for artist name match, first result is sometimes not the closest lexical match + artist = next ((a for a in artists if a[0].lower() == query.lower()), artists[0]) artistID = artist[1] if __debugging__ : xbmc.log("Found " + artist[0] + "...") albums = groovesharkApi.getArtistAlbums(artistID, self.albumsearchlimit) if (len(albums) > 0): + self._add_dir(__language__(30016), '', MODE_ARTIST_POPULAR_FROM_ALBUMS, self.popularSongsArtistImg, artistID) self._add_albums_directory(albums, artistID) else: dialog = xbmcgui.Dialog() @@ -440,6 +451,7 @@ class Grooveshark: # Show selected artist def artist(self, artistid): albums = groovesharkApi.getArtistAlbums(artistid, limit = self.albumsearchlimit) + self._add_dir(__language__(30016), '', MODE_ARTIST_POPULAR_FROM_ALBUMS, self.popularSongsArtistImg, artistid) self._add_albums_directory(albums, artistid, True) # Show selected playlist @@ -452,30 +464,38 @@ class Grooveshark: dialog = xbmcgui.Dialog() dialog.ok(__language__(30008), __language__(30034), __language__(30040)) - # Show popular songs of the artist - def artistPopularSongs(self): + # Search for artist show popular songs of the artist + def searchArtistPopularSongs(self): query = self._get_keyboard(default="", heading=__language__(30041)) - if (query != ''): + if (query != ''): artists = groovesharkApi.getArtistSearchResults(query, limit = self.artistsearchlimit) if (len(artists) > 0): - artist = artists[0] + # check for exact artist name match, sometimes a more + # popular artist is returned first (e.g. 'Angel Dust' + # gets you 'Faith No More' because of their popular + # album 'Angel Dust') + artist = next ((a for a in artists if a[0].lower() == query.lower()), artists[0]) artistID = artist[1] if __debugging__ : xbmc.log("Found " + artist[0] + "...") - songs = groovesharkApi.getArtistPopularSongs(artistID, limit = self.songsearchlimit) - if (len(songs) > 0): - self._add_songs_directory(songs, trackLabelFormat=NAME_ALBUM_ARTIST_LABEL) - else: - dialog = xbmcgui.Dialog() - dialog.ok(__language__(30008), __language__(30042)) - self.categories() + self.artistPopularSongs (artistID) else: dialog = xbmcgui.Dialog() dialog.ok(__language__(30008), __language__(30043)) self.categories() else: self.categories() - + + # Show popular songs of the artist + def artistPopularSongs(self, artistID): + songs = groovesharkApi.getArtistPopularSongs(artistID, limit = self.songsearchlimit) + if (len(songs) > 0): + self._add_songs_directory(songs, trackLabelFormat=NAME_ALBUM_ARTIST_LABEL) + else: + dialog = xbmcgui.Dialog() + dialog.ok(__language__(30008), __language__(30042)) + self.categories() + # Play a song def playSong(self, item): global playTimer @@ -523,7 +543,7 @@ class Grooveshark: def songItem(self, songid, name, album, artist, coverart, trackLabelFormat=ARTIST_ALBUM_NAME_LABEL, tracknumber=1): stream = self._getSongStream(songid) - if stream != False: + if stream != None: duration = stream[1] url = stream[2] key = stream[3] @@ -546,9 +566,10 @@ class Grooveshark: item.setProperty('duration', str(duration)) item.setProperty('key', str(key)) item.setProperty('server', str(server)) + item.setProperty('fanart_image', self.fanImg) return item else: - xbmc.log("No song URL") + xbmc.log("No access to song URL") return None # Next page of songs @@ -677,7 +698,7 @@ class Grooveshark: else: # Refresh to remove item from directory xbmc.executebuiltin('XBMC.Notification(' + __language__(30008) + ',' + __language__(30066)+ ', 1000, ' + thumbDef + ')') - xbmc.executebuiltin("Container.Update(" + playlistUrl + "&id="+str(playlistid) + "&name=" + playlistname + ")") + xbmc.executebuiltin("Container.Update(" + playlistUrl + "&id="+str(playlistid) + "&name=" + str(playlistname) + ")") else: dialog = xbmcgui.Dialog() dialog.ok(__language__(30008), __language__(30034), __language__(30067)) @@ -704,16 +725,15 @@ class Grooveshark: def _get_login(self): if (self.username == "" or self.password == ""): dialog = xbmcgui.Dialog() - dialog.ok(__language__(30008), __language__(30069), __language__(30070)) + dialog.ok(__language__(30008), __language__(30069), __language__(30070), __language__(30082)) return 0 else: - if self.userid == 0: - uid = groovesharkApi.login(self.username, self.password) + uid = groovesharkApi.login(self.username, self.password) if (uid != 0): return uid else: dialog = xbmcgui.Dialog() - dialog.ok(__language__(30008), __language__(30069), __language__(30070)) + dialog.ok(__language__(30008), __language__(30069), __language__(30070), __language__(30082)) return 0 # File download @@ -722,8 +742,12 @@ class Grooveshark: localThumb = os.path.join(xbmc.translatePath(os.path.join(thumbDir, str(songid)))) + '.tbn' try: if os.path.isfile(localThumb) == False: - loc = urllib.URLopener() - loc.retrieve(url, localThumb) + headers = { 'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/32.0.1700.102 Chrome/32.0.1700.102 Safari/537.36' } + req = urllib2.Request(url, None, headers) + loc = urllib2.urlopen(req) + output = open(localThumb,'wb') + output.write(loc.read()) + output.close() except: shutil.copy2(thumbDef, localThumb) return os.path.join(os.path.join(thumbDir, str(songid))) + '.tbn' @@ -755,7 +779,6 @@ class Grooveshark: start = offset end = min(start + self.songspagelimit,totalSongs) - id = 0 n = start items = end - start while n < end: @@ -784,14 +807,13 @@ class Grooveshark: menuItems.append((__language__(30071), "XBMC.RunPlugin("+fav+")")) menuItems.append((__language__(30072), "XBMC.RunPlugin("+unfav+")")) if playlistid > 0: - rmplaylstsong=sys.argv[0]+"?playlistid="+str(playlistid)+"&id="+str(songid)+"&mode="+str(MODE_REMOVE_PLAYLIST_SONG)+"&name="+playlistname + rmplaylstsong=sys.argv[0]+"?playlistid="+str(playlistid)+"&id="+str(songid)+"&mode="+str(MODE_REMOVE_PLAYLIST_SONG)+"&name="+str(playlistname) menuItems.append((__language__(30073), "XBMC.RunPlugin("+rmplaylstsong+")")) else: addplaylstsong=sys.argv[0]+"?id="+str(songid)+"&mode="+str(MODE_ADD_PLAYLIST_SONG) menuItems.append((__language__(30074), "XBMC.RunPlugin("+addplaylstsong+")")) item.addContextMenuItems(menuItems, replaceItems=False) xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=item,isFolder=False, totalItems=items) - id = id + 1 else: end = min(end + 1,totalSongs) if __debugging__ : @@ -799,7 +821,7 @@ class Grooveshark: n = n + 1 if totalSongs > end: - u=sys.argv[0]+"?mode="+str(MODE_SONG_PAGE)+"&id=playlistid"+"&offset="+str(end)+"&label="+str(trackLabelFormat)+"&name="+playlistname + u=sys.argv[0]+"?mode="+str(MODE_SONG_PAGE)+"&id=playlistid"+"&offset="+str(end)+"&label="+str(trackLabelFormat)+"&name="+str(playlistname) self._add_dir(__language__(30075) + '...', u, MODE_SONG_PAGE, self.songImg, 0, totalSongs - end) xbmcplugin.setContent(self._handle, 'songs') @@ -815,7 +837,7 @@ class Grooveshark: while i < n: album = albums[i] albumID = album[3] - if isverified or groovesharkApi.getDoesAlbumExist(albumID): + if isverified: albumArtistName = album[0] albumName = album[2] albumImage = self._get_icon(album[4], 'album-' + str(albumID)) @@ -840,11 +862,8 @@ class Grooveshark: while i < n: artist = artists[i] artistID = artist[1] - if groovesharkApi.getDoesArtistExist(artistID): - artistName = artist[0] - self._add_dir(artistName, '', MODE_ARTIST, self.artistImg, artistID, itemsExisting) - else: - itemsExisting = itemsExisting - 1 + artistName = artist[0] + self._add_dir(artistName, '', MODE_ARTIST, self.artistImg, artistID, itemsExisting) i = i + 1 xbmcplugin.setContent(self._handle, 'artists') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ARTIST_IGNORE_THE) @@ -860,36 +879,37 @@ class Grooveshark: playlist = playlists[i] playlistName = playlist[0] playlistID = playlist[1] - dir = self._add_dir(playlistName, '', MODE_PLAYLIST, self.playlistImg, playlistID, n) + self._add_dir(playlistName, '', MODE_PLAYLIST, self.playlistImg, playlistID, n) i = i + 1 xbmcplugin.setContent(self._handle, 'files') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_LABEL) xbmcplugin.setPluginFanart(int(sys.argv[1]), self.fanImg) # Add whatever directory - def _add_dir(self, name, url, mode, iconimage, id, items=1): + def _add_dir(self, name, url, mode, iconimage, itemId, items=1): if url == '': - u=sys.argv[0]+"?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(itemId) else: u = url - dir=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage=iconimage) - dir.setInfo( type="Music", infoLabels={ "title": name } ) + directory=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage=iconimage) + directory.setInfo( type="Music", infoLabels={ "title": name } ) + directory.setProperty('fanart_image', self.fanImg) # Custom menu items menuItems = [] if mode == MODE_ALBUM: - mkplaylst=sys.argv[0]+"?mode="+str(MODE_MAKE_PLAYLIST)+"&name="+name+"&id="+str(id) + mkplaylst=sys.argv[0]+"?mode="+str(MODE_MAKE_PLAYLIST)+"&name="+name+"&id="+str(itemId) menuItems.append((__language__(30076), "XBMC.RunPlugin("+mkplaylst+")")) if mode == MODE_PLAYLIST: - rmplaylst=sys.argv[0]+"?mode="+str(MODE_REMOVE_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id) + rmplaylst=sys.argv[0]+"?mode="+str(MODE_REMOVE_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(itemId) menuItems.append((__language__(30077), "XBMC.RunPlugin("+rmplaylst+")")) - mvplaylst=sys.argv[0]+"?mode="+str(MODE_RENAME_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(id) + mvplaylst=sys.argv[0]+"?mode="+str(MODE_RENAME_PLAYLIST)+"&name="+urllib.quote_plus(name)+"&id="+str(itemId) menuItems.append((__language__(30078), "XBMC.RunPlugin("+mvplaylst+")")) - dir.addContextMenuItems(menuItems, replaceItems=False) + directory.addContextMenuItems(menuItems, replaceItems=False) - return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=dir,isFolder=True, totalItems=items) + return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=directory,isFolder=True, totalItems=items) def _getSavedSongs(self): path = os.path.join(cacheDir, 'songs.dmp') @@ -922,23 +942,24 @@ class Grooveshark: return int(usecs / 1000000) def _getSongStream(self, songid): - id = int(songid) + idSong = int(songid) stream = None - streams = [] + streams = {} path = os.path.join(cacheDir, 'streams.dmp') try: f = open(path, 'rb') streams = pickle.load(f) - for song in streams: - if song[0] == id: - duration = song[1] - url = song[2] - key = song[3] - server = song[4] - stream = [id, duration, url, key, server] - if __debugging__ : - xbmc.log("Found " + str(id) + " in stream cache") - break; + song = streams[songid] + + duration = song[1] + url = song[2] + key = song[3] + server = song[4] + stream = [idSong, duration, url, key, server] + + if __debugging__ : + xbmc.log("Found " + str(idSong) + " in stream cache") + f.close() except: pass @@ -951,14 +972,14 @@ class Grooveshark: url = stream['url'] key = stream['StreamKey'] server = stream['StreamServerID'] - stream = [id, duration, url, key, server] + stream = [idSong, duration, url, key, server] self._addSongStream(stream) return stream def _addSongStream(self, stream): streams = self._getStreams() - streams.append(stream) + streams[int(stream[0])] = stream path = os.path.join(cacheDir, 'streams.dmp') try: f = open(path, 'wb') @@ -970,25 +991,21 @@ class Grooveshark: xbmc.log("An error occurred adding to stream") def _setSongStream(self, stream): - id = int(stream[0]) + idStream = int(stream[0]) stream[1] = self._setDuration(stream[1]) streams = self._getStreams() path = os.path.join(cacheDir, 'streams.dmp') - i = 0 - for song in streams: - if song[0] == id: - streams[i] = stream - try: - f = open(path, 'wb') - pickle.dump(streams, f, protocol=pickle.HIGHEST_PROTOCOL) - f.close() - if __debugging__ : - xbmc.log("Updated " + str(id) + " in stream cache") - break; - except: - xbmc.log("An error occurred setting stream") - i = i + 1 + try: + streams[idStream] = stream + f = open(path, 'wb') + pickle.dump(streams, f, protocol=pickle.HIGHEST_PROTOCOL) + f.close() + if __debugging__ : + xbmc.log("Updated " + str(idStream) + " in stream cache") + + except: + xbmc.log("An error occurred setting stream") def _getStreams(self): path = os.path.join(cacheDir, 'streams.dmp') @@ -997,7 +1014,7 @@ class Grooveshark: streams = pickle.load(f) f.close() except: - streams = [] + streams = {} pass return streams @@ -1029,8 +1046,8 @@ params=get_params() mode=None try: mode=int(params["mode"]) except: pass -id=0 -try: id=int(params["id"]) +itemId=0 +try: itemId=int(params["id"]) except: pass name = None try: name=urllib.unquote_plus(params["name"]) @@ -1059,7 +1076,7 @@ elif mode==MODE_POPULAR_SONGS: grooveshark.popularSongs() elif mode==MODE_ARTIST_POPULAR: - grooveshark.artistPopularSongs() + grooveshark.searchArtistPopularSongs() elif mode==MODE_FAVORITES: grooveshark.favorites() @@ -1072,7 +1089,7 @@ elif mode==MODE_SONG_PAGE: except: pass try: label=urllib.unquote_plus(params["label"]) except: pass - grooveshark.songPage(offset, label, id, name) + grooveshark.songPage(offset, label, itemId, name) elif mode==MODE_SONG: try: album=urllib.unquote_plus(params["album"]) @@ -1081,46 +1098,49 @@ elif mode==MODE_SONG: except: pass try: coverart=urllib.unquote_plus(params["coverart"]) except: pass - song = grooveshark.songItem(id, name, album, artist, coverart) + song = grooveshark.songItem(itemId, name, album, artist, coverart) grooveshark.playSong(song) elif mode==MODE_ARTIST: - grooveshark.artist(id) + grooveshark.artist(itemId) elif mode==MODE_ALBUM: - grooveshark.album(id) + grooveshark.album(itemId) elif mode==MODE_PLAYLIST: - grooveshark.playlist(id, name) + grooveshark.playlist(itemId, name) elif mode==MODE_FAVORITE: - grooveshark.favorite(id) + grooveshark.favorite(itemId) elif mode==MODE_UNFAVORITE: try: prevMode=int(urllib.unquote_plus(params["prevmode"])) except: prevMode = 0 - grooveshark.unfavorite(id, prevMode) + grooveshark.unfavorite(itemId, prevMode) elif mode==MODE_SIMILAR_ARTISTS: - grooveshark.similarArtists(id) + grooveshark.similarArtists(itemId) elif mode==MODE_MAKE_PLAYLIST: - grooveshark.makePlaylist(id, name) + grooveshark.makePlaylist(itemId, name) elif mode==MODE_REMOVE_PLAYLIST: - grooveshark.removePlaylist(id, name) + grooveshark.removePlaylist(itemId, name) elif mode==MODE_RENAME_PLAYLIST: - grooveshark.renamePlaylist(id, name) + grooveshark.renamePlaylist(itemId, name) elif mode==MODE_REMOVE_PLAYLIST_SONG: try: playlistID=urllib.unquote_plus(params["playlistid"]) except: pass - grooveshark.removePlaylistSong(playlistID, name, id) + grooveshark.removePlaylistSong(playlistID, name, itemId) elif mode==MODE_ADD_PLAYLIST_SONG: - grooveshark.addPlaylistSong(id) + grooveshark.addPlaylistSong(itemId) + +elif mode==MODE_ARTIST_POPULAR_FROM_ALBUMS: + grooveshark.artistPopularSongs(itemId) if mode < MODE_SONG: xbmcplugin.endOfDirectory(int(sys.argv[1]))