X-Git-Url: https://git.hcoop.net/clinton/xbmc-groove.git/blobdiff_plain/8817bb2e053406c493509aff02fc4f91db3143b9..3fcef5ba80eb63c54c4220ff91ebf79ac4390957:/default.py diff --git a/default.py b/default.py index 49c0e85..b0a86e9 100644 --- a/default.py +++ b/default.py @@ -1,4 +1,4 @@ -import urllib, urllib2, re, xbmcplugin, xbmcgui, xbmc, sys, os +import urllib, urllib2, re, xbmcplugin, xbmcgui, xbmc, sys, os, time # plugin constants __plugin__ = "Grooveshark" @@ -21,18 +21,20 @@ MODE_PLAYLIST = 9 MODE_SONG = 10 MODE_FAVORITE = 11 MODE_UNFAVORITE = 12 +MODE_SIMILAR_SONG = 13 +MODE_SIMILAR_ARTIST = 14 +MODE_FROWN = 15 -songsearchlimit = 25 -albumsearchlimit = 15 -artistsearchlimit = 15 +songsearchlimit = 0 +albumsearchlimit = 0 +artistsearchlimit = 0 lastID = 0 -rootDir = os.getcwd() - -resDir = xbmc.translatePath(os.path.join(rootDir, 'resources')) +resDir = xbmc.translatePath(os.path.join(os.getcwd(), 'resources')) libDir = xbmc.translatePath(os.path.join(resDir, 'lib')) imgDir = xbmc.translatePath(os.path.join(resDir, 'img')) +thumbDir = os.path.join('special://masterprofile/plugin_data/music', os.path.basename(os.getcwd())) sys.path.append (libDir) from GrooveAPI import * @@ -41,6 +43,27 @@ groovesharkApi = GrooveAPI() class _Info: def __init__( self, *args, **kwargs ): self.__dict__.update( kwargs ) + +class GrovesharkPlayer(xbmc.Player): + # Player Class: calls function when song changes or playback ends + def __init__(self, *args, **kwargs): + xbmc.Player.__init__(self) + self.function = kwargs[ "function" ] + + def onPlayBackStopped(self): + print "onPlayBackStopped" + xbmc.sleep(300) + if (not xbmc.Player().isPlayingAudio()): + self.function(stop=1) + + def onPlayBackEnded(self): + print "onPlayBackEnded" + xbmc.sleep(300) + if (not xbmc.Player().isPlayingAudio()): + self.function(stop=0) + + def onPlayBackStarted(self): + print "onPlayBackStarted" class Groveshark: @@ -54,24 +77,31 @@ class Groveshark: songsearchlimit = xbmcplugin.getSetting('songsearchlimit') albumsearchlimit = xbmcplugin.getSetting('albumsearchlimit') artistsearchlimit = xbmcplugin.getSetting('artistsearchlimit') - + + musicplaylist = xbmc.PlayList(xbmc.PLAYLIST_MUSIC) + def __init__( self ): self._handle = int(sys.argv[1]) - + def categories(self): + userid = self._get_login() - self._addDir('Search songs', '', MODE_SEARCH_SONGS, self.songImg, 0) - self._addDir('Search albums', '', MODE_SEARCH_ALBUMS, self.albumImg, 0) - self._addDir('Search artists', '', MODE_SEARCH_ARTISTS, self.artistImg, 0) - self._addDir('Popular', '', MODE_POPULAR, self.popularImg, 0) + + # Setup + groovesharkApi.setRemoveDuplicates(True) + + 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) if (userid != 0): - self._addDir('Favorites', '', MODE_FAVORITES, self.favoritesImg, 0) - self._addDir('Playlists', '', MODE_PLAYLISTS, self.playlistImg, 0) - + self._add_dir('Favorites', '', MODE_FAVORITES, self.favoritesImg, 0) + self._add_dir('Playlists', '', MODE_PLAYLISTS, self.playlistImg, 0) + def searchSongs(self): query = self._get_keyboard(default="", heading="Search songs") if (query): - songs = groovesharkApi.searchSongs(query, limit = songsearchlimit) + songs = groovesharkApi.searchSongs(query, limit = xbmcplugin.getSetting('songsearchlimit')) if (len(songs) > 0): self._get_songs(songs) else: @@ -82,7 +112,7 @@ class Groveshark: def searchAlbums(self): query = self._get_keyboard(default="", heading="Search albums") if (query): - albums = groovesharkApi.searchAlbums(query, limit = albumsearchlimit) + albums = groovesharkApi.searchAlbums(query, limit = xbmcplugin.getSetting('albumsearchlimit')) if (len(albums) > 0): self._get_albums(albums) else: @@ -93,7 +123,7 @@ class Groveshark: def searchArtists(self): query = self._get_keyboard(default="", heading="Search artists") if (query): - artists = groovesharkApi.searchArtists(query, limit = artistsearchlimit) + artists = groovesharkApi.searchArtists(query, limit = xbmcplugin.getSetting('artistsearchlimit')) if (len(artists) > 0): self._get_artists(artists) else: @@ -113,7 +143,7 @@ class Groveshark: self.categories() def popular(self): - popular = groovesharkApi.popularGetSongs(limit = songsearchlimit) + popular = groovesharkApi.popularGetSongs(limit = xbmcplugin.getSetting('songsearchlimit')) if (len(popular) > 0): self._get_songs(popular) else: @@ -135,7 +165,7 @@ class Groveshark: def favorite(self, songid): userid = self._get_login() if (userid != 0): - xbmc.log("Favorite song: " + str(songid)) + xbmc.log("Favorite playSong: " + str(songid)) groovesharkApi.favoriteSong(songID = songid) else: dialog = xbmcgui.Dialog() @@ -144,35 +174,82 @@ class Groveshark: def unfavorite(self, songid): userid = self._get_login() if (userid != 0): - xbmc.log("Unfavorite song: " + str(songid)) + xbmc.log("Unfavorite playSong: " + str(songid)) groovesharkApi.unfavoriteSong(songID = songid) else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark', 'You must be logged in', 'to remove favorites.') + + def frown(self, songid): + userid = self._get_login() + if (userid != 0): + xbmc.log("Frown playSong: " + str(songid)) + if groovesharkApi.radioFrown(songId = songid) != True: + xbmc.log("Unable to frown song " + str(songid)) + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You must be logged in', 'to frown a song.') + + def similarSong(self, songid): + userid = self._get_login() + if (userid != 0): + xbmc.log("Frown playSong: " + str(songid)) + if groovesharkApi.radioSong(songId = songid) and groovesharkApi.radioStartSongs() == True: + self.playRadio() + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'Cannot start radio') + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You must be logged in', 'to update radio song.') + + def similarArtist(self, artistId): + userid = self._get_login() + if (userid != 0): + xbmc.log("Add radio artist of playSong: " + str(artistId)) + if groovesharkApi.radioArtist(artistId = artistId) and groovesharkApi.radioStartArtists() == True: + self.playRadio() + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'Cannot start radio') + else: + dialog = xbmcgui.Dialog() + dialog.ok('Grooveshark', 'You must be logged in', 'to update radio artists.') def album(self,albumid): - album = groovesharkApi.albumGetSongs(albumId = albumid, limit = songsearchlimit) + album = groovesharkApi.albumGetSongs(albumId = albumid, limit = xbmcplugin.getSetting('songsearchlimit')) self._get_songs(album) def artist(self, artistid): - albums = groovesharkApi.artistGetAlbums(artistId = artistid, limit = albumsearchlimit) + albums = groovesharkApi.artistGetAlbums(artistId = artistid, limit = xbmcplugin.getSetting('albumsearchlimit')) self._get_albums(albums) def playlist(self, playlistid): userid = self._get_login() if (userid != 0): - songs = groovesharkApi.playlistGetSongs(playlistId = playlistid, limit = songsearchlimit) + songs = groovesharkApi.playlistGetSongs(playlistId = playlistid, limit = xbmcplugin.getSetting('songsearchlimit')) self._get_songs(songs) else: dialog = xbmcgui.Dialog() dialog.ok('Grooveshark', 'You must be logged in', 'to get playlists.') - def song(self, url, name, album, artist, duration): + def playSong(self, songItem): + url = songItem.getProperty('url') xbmc.log("Playing: " + url) - songItem = xbmcgui.ListItem(name + " - " + artist, path=url) - songItem.setInfo( type="Music", infoLabels={ "Title": name, "Duration": duration, "Album": album, "Artist": artist} ) - xbmc.Player().stop() - xbmc.Player(xbmc.PLAYER_CORE_PAPLAYER).play(url, songItem, False) + player = GrovesharkPlayer(xbmc.PLAYER_CORE_PAPLAYER, function=self._add_next) + player.play(url, songItem, False) + + def playRadio(self): + song = self._get_next() + self._get_next() + self.playSong(song) + + def songItem(self, url, name, album, artist, duration, thumb, image): + songItem = xbmcgui.ListItem(label = name, path=url, thumbnailImage=thumb, iconImage=image) + songItem.setInfo( type="Music", infoLabels={ "title": name, "duration": duration, "album": album, "artist": artist} ) + songItem.setProperty('mimetype', 'audio/mpeg') + songItem.setProperty('url', url) + return songItem def _get_keyboard(self, default="", heading="", hidden=False): kb = xbmc.Keyboard(default, heading, hidden) @@ -191,10 +268,7 @@ class Groveshark: else: if groovesharkApi.loggedInStatus() == 1: groovesharkApi.logout() - try: - userid = groovesharkApi.loginExt(username, password) - except (LoginUnknownError): - userid = 0 + userid = groovesharkApi.loginExt(username, password) if (userid != 0): xbmc.log("Logged in") return userid @@ -203,6 +277,21 @@ class Groveshark: dialog.ok('Grooveshark', 'Unable to login.', 'Check username and password in settings.') return 0 + def _get_next(self): + song = groovesharkApi.radioNextSong()[0] + print song + url = groovesharkApi.getStreamURL(song[1]) + songImg = self._get_thumb(song[9], str(song[1]) + "-image") + if songImg == "": + songImg = song[9] + songThm = self._get_thumb(song[5], str(song[1]) + "-thumb") + if songThm == "": + songThm = song[5] + item = self.songItem(url, song[0], song[3], song[6], song[2], songThm, songImg) + self.musicplaylist.add(url, item) + print item + return item + def _get_songs(self, songs): xbmc.log("Found " + str(len(songs)) + " songs...") i = 0 @@ -213,12 +302,13 @@ class Groveshark: songDuration = song[2] songAlbum = song[3] songArtist = song[6] + songArtistId = song[7] + songThumb = song[8] songImage = song[9] - xbmc.log(songName) - self._addSong(songID, songName, groovesharkApi.getStreamURL(songID), songDuration, songAlbum, songArtist, songImage) + songUrl = groovesharkApi.getStreamURL(songID) + self._add_song(songID, songName, songUrl, songDuration, songAlbum, songArtist, songArtistId, songThumb, songImage) i = i + 1 xbmcplugin.setContent(self._handle, 'songs') - xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE) def _get_albums(self, albums): xbmc.log("Found " + str(len(albums)) + " albums...") @@ -229,8 +319,7 @@ class Groveshark: albumName = album[2] albumID = album[3] albumImage = album[4] - xbmc.log(albumName) - self._addDir(albumName + " - " + albumArtistName, '', MODE_ALBUM, albumImage, albumID) + self._add_dir(albumName + " - " + albumArtistName, '', MODE_ALBUM, albumImage, albumID) i = i + 1 xbmcplugin.setContent(self._handle, 'albums') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ALBUM_IGNORE_THE) @@ -242,8 +331,7 @@ class Groveshark: artist = artists[i] artistName = artist[0] artistID = artist[1] - xbmc.log(artistName) - self._addDir(artistName, '', MODE_ARTIST, self.artistImg, artistID) + self._add_dir(artistName, '', MODE_ARTIST, self.artistImg, artistID) i = i + 1 xbmcplugin.setContent(self._handle, 'artists') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_ARTIST_IGNORE_THE) @@ -255,36 +343,74 @@ class Groveshark: playlist = playlists[i] playlistName = playlist[0] playlistID = playlist[1] - xbmc.log(playlistName) - self._addDir(playlistName, '', MODE_PLAYLIST, self.playlistImg, playlistID, ) + self._add_dir(playlistName, '', MODE_PLAYLIST, self.playlistImg, playlistID) i = i + 1 xbmcplugin.setContent(self._handle, 'files') xbmcplugin.addSortMethod(self._handle, xbmcplugin.SORT_METHOD_PLAYLIST_ORDER) - def _addSong(self, songid, songname, songurl, songduration, songalbum, songartist, songimage): + # File download + def _get_thumb(self, url, id): + # Get the channel icon + localThumb = os.path.join(xbmc.translatePath(os.path.join(thumbDir, str(id)))) + '.tbn' + try: + if os.path.isfile(localThumb) == False: + loc = urllib.URLopener() + loc.retrieve(url, localThumb) + except: + xbmc.log('URL download failed of ' + url + ' to ' + localThumb) + return "" + + return os.path.join(os.path.join(thumbDir, str(id))) + '.tbn' + + def _add_song(self, songid, songname, songurl, songduration, songalbum, songartist, songartistid, songthumb, songimage): + songImg = self._get_thumb(songimage, str(songid) + "-image") + if songImg == "": + songImg = songimage + songThm = self._get_thumb(songthumb, str(songid) + "-thumb") + if songThm == "": + songThm = songthumb u=sys.argv[0]+"?url="+urllib.quote_plus(songurl)+"&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) - songItem = xbmcgui.ListItem(songname + " - " + songartist, iconImage=songimage, thumbnailImage=songimage, path=songurl) - songItem.setInfo( type="Music", infoLabels={ "Title": songname, "Duration": songduration, "Album": songalbum, "Artist": songartist} ) + +"&duration="+str(songduration) \ + +"&thumb="+urllib.quote_plus(songThm) \ + +"&image="+urllib.quote_plus(songImg) + songItem = xbmcgui.ListItem(label = songartist + " - " + songalbum + " - " + songname, iconImage=songImg, thumbnailImage=songThm, path=songurl) + songItem.setInfo( type="Music", infoLabels={ "title": songname, "duration": songduration, "album": songalbum, "artist": songartist} ) 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) + similarArtist=sys.argv[0]+"?mode="+str(MODE_SIMILAR_ARTIST)+"&id="+str(songartistid) + similarSong=sys.argv[0]+"?mode="+str(MODE_SIMILAR_SONG)+"&id="+str(songid) + frown=sys.argv[0]+"?mode="+str(MODE_FROWN)+"&id="+str(songid) menuItems = [] - menuItems.append(("Grooveshark Favorite", "XBMC.RunPlugin("+fav+")")) + menuItems.append(("Grooveshark Favorite", "XBMC.RunPlugin("+fav+")")) menuItems.append(("Not Grooveshark Favorite", "XBMC.RunPlugin("+unfav+")")) + menuItems.append(("Listen to similar artist", "XBMC.RunPlugin("+similarArtist+")")) + menuItems.append(("Listen to similar song", "XBMC.RunPlugin("+similarSong+")")) + menuItems.append(("No thanks!", "XBMC.RunPlugin("+frown+")")) songItem.addContextMenuItems(menuItems, replaceItems=False) - return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=songItem,isFolder=False) + xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=songItem,isFolder=False) + return songItem + + def _add_next(self, stop=0): + print "_add_next " + str(stop) + if stop == 1: + groovesharkApi.radioEnabled = False + self.playlist.clear() + elif groovesharkApi.radioTurnedOn() == True: + next = self._get_next() + self.playlist.add(url, next) - def _addDir(self, name, url, mode, iconimage, id): + def _add_dir(self, name, url, mode, iconimage, id): u=sys.argv[0]+"?url="+urllib.quote_plus(url)+"&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 } ) + dir.setInfo( type="Music", infoLabels={ "title": name } ) # Codes from http://xbmc-scripting.googlecode.com/svn/trunk/Script%20Templates/common/gui/codes.py menuItems = [] menuItems.append(("Select", "XBMC.executebuiltin(Action(7))")) dir.addContextMenuItems(menuItems, replaceItems=True) return xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=dir,isFolder=True) + def get_params(): param=[] @@ -354,7 +480,12 @@ elif mode==MODE_SONG: except: pass try: duration=int(params["duration"]) except: pass - grooveshark.song(url, name, album, artist, duration) + try: thumb=urllib.unquote_plus(params["thumb"]) + except: pass + try: image=urllib.unquote_plus(params["image"]) + except: pass + song = grooveshark.songItem(url, name, album, artist, duration, thumb, image) + grooveshark.playSong(song) elif mode==MODE_ARTIST: grooveshark.artist(lastID) @@ -370,6 +501,15 @@ elif mode==MODE_FAVORITE: elif mode==MODE_UNFAVORITE: grooveshark.unfavorite(lastID) + +elif mode==MODE_SIMILAR_ARTIST: + grooveshark.similarArtist(lastID) + +elif mode==MODE_SIMILAR_SONG: + grooveshark.similarSong(lastID) + +elif mode==MODE_FROWN: + grooveshark.frown(lastID) if (mode < MODE_SONG): xbmcplugin.endOfDirectory(int(sys.argv[1]))