Пример #1
0
class GMusic(object):
    def __init__(self):
        self.webclient = Webclient(debug_logging=False)
        self.email = None
        self.password = None
        self.authenticated = False
        self.all_songs = list()
        self.playlists = list()

    def authenticate(self, email=None, password=None):
        if email:
            self.email = email
        if password:
            self.password = password

        try:
            Log("AUTHENTICATING!!!!111")
            self.authenticated = self.webclient.login(self.email, self.password)
        except AlreadyLoggedIn:
            self.authenticated = True


        return self.authenticated

    def get_all_songs(self):
        try:
            self.all_songs = self.webclient.get_all_songs()
        except NotLoggedIn:
            if self.authenticate():
                self.all_songs = self.webclient.get_all_songs()
            else:
                Log("LOGIN FAILURE")
                return

        return self.all_songs

    def get_all_playlists(self):
        try:
            self.playlists = self.webclient.get_all_playlist_ids()
        except NotLoggedIn:
            if self.authenticate():
                self.playlists = self.webclient.get_all_playlist_ids()
            else:
                Log("LOGIN FAILURE")
                return

        return self.playlists

    def get_stream_url(self, song_id):
        try:
            stream_url = self.webclient.get_stream_url(song_id)
        except NotLoggedIn:
            if self.authenticate():
                stream_url = self.webclient.get_stream_url(song_id)
            else:
                Log("LOGIN FAILURE")
                return

        return stream_url
Пример #2
0
def main():
	api = Webclient()
	loggedIn = connect(api, raw_input('Username: '******'Password: '))

	if not loggedIn:
		print "Authorization unsuccessful"
		sys.exit(0)
	else:
		print "Authorization successful!"

	print api.get_all_songs()[0]
Пример #3
0
def main():
    api = Webclient()
    loggedIn = connect(api, raw_input('Username: '******'Password: '))

    if not loggedIn:
        print "Authorization unsuccessful"
        sys.exit(0)
    else:
        print "Authorization successful!"

    print api.get_all_songs()[0]
Пример #4
0
class gMusicClient(object):
	logged_in = False
	api = None
	playlists = dict()
	library = dict()

	def __init__(self, email, password):
		self.api = Webclient()
		logged_in = False
		attempts = 0
		if len(password) is 0:
			password = getpass("Google password:"******"title"]
			if song["artist"] == "":
				song_artist = "Unknown Artist"
			else:
				song_artist = song["artist"]
			if song["album"] == "":
				song_album = "Unknown Album"
			else:
				song_album = song["album"]
			if not (song_artist in self.library):
				albums_dict = dict()
				self.library[song_artist] = albums_dict
			if not (song_album in self.library[song_artist]):
				song_list = list()
				self.library[song_artist][song_album] = song_list
			self.library[song_artist][song_album].append(song)
		plists = self.api.get_all_playlist_ids(auto=True, user=True)
		for u_playlist, u_playlist_id in plists["user"].iteritems():
			self.playlists[u_playlist] = self.api.get_playlist_songs(u_playlist_id[0])
		self.playlists["Thumbs Up"] = [song for song in songs if song['rating'] == 5]

	def getSongStream(self, song):
		return self.api.get_stream_urls(song["id"])

	def getStreamAudio(self, song):
		return self.api.get_stream_audio(song["id"])

	def thumbsUp(self, song):
		try:
			song["rating"] = 5
			song_list = [song]
			self.api.change_song_metadata(song_list)
			print "Gave a Thumbs Up to {0} by {1} on Google Play.".format(song["title"].encode("utf-8"), song["artist"].encode("utf-8"))
		except:
			print "Error giving a Thumbs Up on Google Play."
Пример #5
0
def download_song():
	print "Request : Download url"
	mm = Webclient()
	token = request.form['token']
	songid = request.form['songid']
	mm.setToken(token)
	songs = mm.get_all_songs(incremental=False)
	url = mm.get_stream_url(songid)
	return url
Пример #6
0
class User:
	def __init__(self, cshUsername, cshHomeDirectory):
		self.cshlibrary = []
		self.cshUsername = cshUsername
		self.cshHomeDirectory = cshHomeDirectory

	def playLogin(self, username, password):
		self.api = Webclient()
		self.api.login(username, password)
		self.playlibrary = self.api.get_all_songs()
Пример #7
0
class GMusicSession(object):
    def __init__(self):
        super(GMusicSession, self).__init__()
        logger.info('Mopidy uses Google Music')
        self.api = Webclient()

    def login(self, username, password):
        if self.api.is_authenticated():
            self.api.logout()
        try:
            self.api.login(username, password)
        except CallFailure as error:
            logger.error(u'Failed to login as "%s": %s', username, error)
        return self.api.is_authenticated()

    def logout(self):
        if self.api.is_authenticated():
            return self.api.logout()
        else:
            return True

    def get_all_songs(self):
        if self.api.is_authenticated():
            return self.api.get_all_songs()
        else:
            return {}

    def get_stream_url(self, song_id):
        if self.api.is_authenticated():
            try:
                return self.api.get_stream_urls(song_id)[0]
            except CallFailure as error:
                logger.error(u'Failed to lookup "%s": %s', song_id, error)

    def get_all_playlist_ids(self):
        if self.api.is_authenticated():
            return self.api.get_all_playlist_ids()
        else:
            return {}

    def get_playlist_songs(self, playlist_id):
        if self.api.is_authenticated():
            return self.api.get_playlist_songs(playlist_id)
        else:
            return {}
Пример #8
0
def list():
	mm = Webclient()
	token = request.form['token']
	mm.setToken(token)
	playlists = mm.get_all_playlist_ids()
	output = "["

	songs = mm.get_all_songs(incremental=False)
	output += "{'title': 'Full library', 'songs' : "
	output += json.dumps(songs)
	output += "},"

	for (key,values) in playlists['user'].items():
		for playlistid in values:
			output += "{ 'title':'"+key+"', 'songs' :"
			songs=mm.get_playlist_songs(playlistid)
			output += json.dumps(songs)
			output += "},"

	output += "]"

	return output
Пример #9
0
def list():
	mm = Webclient()
	token = request.form['token']
	mm.setToken(token)
	songs = mm.get_all_songs(incremental=False)
	return json.dumps(songs)
Пример #10
0
    def handle(self, *args, **options):
        if GPLAY_PASS == "" or GPLAY_USER == "":
            self.stdout.write(
                'Credentials not set up. Please edit settings.py')
            return

        api = Webclient()
        if not api.login(GPLAY_USER, GPLAY_PASS):
            self.stdout.write('Incorrect credentials, login failed')
            return

        self.stdout.write('Connected to Google Music, downloading data...')
        library = api.get_all_songs()
        self.stdout.write('Data downloaded!')
        self.stdout.write('Clearing DB...')
        cursor = connection.cursor()
        # This can take a long time using ORM commands on the Pi, so lets Truncate
        cursor.execute('DELETE FROM ' + Track._meta.db_table)
        cursor.execute('DELETE FROM ' + Album._meta.db_table)
        cursor.execute('DELETE FROM ' + Artist._meta.db_table)
        cursor.execute('DELETE FROM ' + Playlist._meta.db_table)
        cursor.execute('DELETE FROM ' + PlaylistConnection._meta.db_table)
        self.stdout.write('Parsing new data...')

        # Easier to keep track of who we've seen like this...
        artists = []
        albums = []

        for song in library:
            track = Track()

            if song['albumArtist'] == "":
                if song['artist'] == "":
                    a = "Unknown Artist"
                else:
                    a = song['artist']
            else:
                a = song['albumArtist']

            if a not in artists:
                artist = Artist()
                artist.name = a
                try:
                    artist.art_url = song['artistImageBaseUrl']
                except:
                    artist.art_url = ""
                artist.save()
                artists.append(a)
                self.stdout.write('Added artist: ' + a)
            else:
                artist = Artist.objects.get(name=a)
            track.artist = artist

            if song['album'] not in albums:
                album = Album()
                album.name = song['album']
                album.artist = artist
                try:
                    album.art_url = song['albumArtUrl']
                except:
                    album.art_url = ""
                album.save()
                albums.append(song['album'])
            else:
                album = Album.objects.get(name=song['album'])
            track.album = album

            track.name = song['title']
            track.stream_id = song['id']
            try:
                track.track_no = song['track']
            except:
                track.track_no = 0
            track.save()

        self.stdout.write('All tracks saved!')
        self.stdout.write('Getting Playlists...')
        playlists = api.get_all_playlist_ids(auto=False, user=True)
        self.stdout.write('Saving playlists...')
        for name in playlists['user']:
            for pid in playlists['user'][name]:
                p = Playlist()
                p.pid = pid
                p.name = name
                p.save()

        for playlist in Playlist.objects.all():
            self.stdout.write('Getting playlist contents for ' + playlist.name)
            songs = api.get_playlist_songs(playlist.pid)
            for song in songs:
                track = Track.objects.get(stream_id=song['id'])
                pc = PlaylistConnection()
                pc.playlist = playlist
                pc.track = track
                pc.save()

        self.stdout.write('Library saved!')
Пример #11
0
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print "Fetching songs from Google..."
        self.songs = self.wc.get_all_songs()
        print "Got %d songs." % len(self.songs)        

    def auth(self):
        self.logged_in = self.wc.login(self.email, self.password)
        if not self.logged_in:
            print "Login failed..."
            exit()

        print "Logged in as %s" % self.email
        
        if not os.path.isfile(OAUTH_FILEPATH):
            print "First time login. Please follow the instructions below:"
            self.mm.perform_oauth()
        self.logged_in = self.mm.login()
        if not self.logged_in:
            print "OAuth failed... try deleting your %s file and trying again." % OAUTH_FILEPATH
            exit()

        print "Authenticated"
        
    def sync_playlist(self, filename, remove_missing=False):
        filename = self.get_platform_path(filename)
        os.chdir(os.path.dirname(filename))
        title = os.path.splitext(os.path.basename(filename))[0]
        print "Syncing playlist: %s" % filename
        if title in self.playlists['user']:
            plid = self.playlists['user'][title][0]        
            goog_songs = self.wc.get_playlist_songs(plid)
            print "  %d songs already in Google Music playlist" % len(goog_songs)
            pc_songs = self.get_files_from_playlist(filename)
            print "  %d songs in local playlist" % len(pc_songs)
            
            # Sanity check max 1000 songs per playlist
            if len(pc_songs) > MAX_SONGS_IN_PLAYLIST:
                print "    Google music doesn't allow more than %d songs in a playlist..." % MAX_SONGS_IN_PLAYLIST
                print "    Will only attempt to sync the first %d songs." % MAX_SONGS_IN_PLAYLIST
                del pc_songs[MAX_SONGS_IN_PLAYLIST:]
    
            existing_files = 0
            added_files = 0
            failed_files = 0
            removed_files = 0
            fatal_count = 0
            # print "Google songs: %s" % goog_songs
            for fn in pc_songs:
                if self.file_already_in_list(fn, goog_songs):
                    existing_files += 1
                    continue
                print "  adding: %s" % os.path.basename(fn)
                online = self.find_song(fn)
                song_id = None
                if online:
                    song_id = online['id']
                    print "  already uploaded [%s]" % song_id
                else:
                    attempts = 0
                    result = []
                    while not result and attempts < MAX_UPLOAD_ATTEMPTS_PER_FILE:
                        print "  uploading... (may take a while)"
                        attempts += 1
                        try:
                            result = self.mm.upload(fn)
                        except (BadStatusLine, CannotSendRequest):
                            # Bail out if we're getting too many disconnects
                            if fatal_count >= MAX_CONNECTION_ERRORS_BEFORE_QUIT:
                               print "Too many disconnections - quitting. Please try running the script again."
                               exit()
    
                            print "Connection Error -- Reattempting login"
                            fatal_count += 1
                            self.wc.logout()
                            self.mm.logout()
                            result = []
                            time.sleep(STANDARD_SLEEP)
    
                        except:
                            result = []
                            time.sleep(STANDARD_SLEEP)
    
                    try:
                        if result[0]:
                            song_id = result[0].itervalues().next()
                        else:
                            song_id = result[1].itervalues().next()
                        print "  upload complete [%s]" % song_id
                    except:
                        print "  upload failed - skipping"
    
                if not song_id:
                    failed_files += 1
                    continue
    
                added = self.wc.add_songs_to_playlist(plid, song_id)
                time.sleep(.3) # Don't spam the server too fast...
                print "  done adding to playlist"
                added_files += 1
    
            if remove_missing:
                for s in goog_songs:
                    print "  removing: %s" % s['title']
                    self.wc.remove_songs_from_playlist(plid, s.id)
                    time.sleep(.3) # Don't spam the server too fast...
                    removed_files += 1
                
            print "%d songs unmodified" % existing_files
            print "%d songs added" % added_files
            print "%d songs failed" % failed_files
            print "%d songs removed" % removed_files
            print "Ended: %s" % filename
        else:
            print "  playlist %s didn't exist - skipping" % filename

    def get_files_from_playlist(self, filename):
        files = []
        f = codecs.open(filename, encoding='utf-8')
        for line in f:
            line = line.rstrip().replace(u'\ufeff',u'')
            if line == "" or line[0] == "#":
                continue
            path  = os.path.abspath(self.get_platform_path(line))
            if not os.path.exists(path):
                print "  file not found: %s" % line
                continue
            files.append(path)
        f.close()
        return files

    def file_already_in_list(self, filename, goog_songs):
        tag = self.get_id3_tag(filename)
        i = 0
        while i < len(goog_songs):
            # print "checking: %s" % tag
            # print "against: %s" % goog_songs[i]
            if self.tag_compare(goog_songs[i], tag):
                goog_songs.pop(i)
                return True
            i += 1
        return False

    def get_id3_tag(self, filename):
        data = mutagen.File(filename, easy=True)
        r = {}
        if 'title' not in data:
            title = os.path.splitext(os.path.basename(filename))[0]
            print '  found song with no ID3 title, setting using filename:'
            print '    %s' % title
            print '    (please note - the id3 format used (v2.4) is invisible to windows)'
            data['title'] = [title]
            data.save()
        r['title'] = data['title'][0]
        r['track'] = int(data['tracknumber'][0].split('/')[0]) if 'tracknumber' in data else 0
        # If there is no track, try and get a track number off the front of the file... since thats
        # what google seems to do...
        # Not sure how google expects it to be formatted, for now this is a best guess
        if r['track'] == 0:
            m = re.match("(\d+) ", os.path.basename(filename))
            if m:
                r['track'] = int(m.group(0))
        r['artist'] = data['artist'][0] if 'artist' in data else ''
        r['album'] = data['album'][0] if 'album' in data else ''
        return r

    def find_song(self, filename):
        tag = self.get_id3_tag(filename)
        
        # NOTE - diagnostic print here to check results if you're creating duplicates
        print "  [%s][%s][%s][%s]" % (tag['title'], tag['artist'], tag['album'], tag['track'])
        for s in self.songs:
            if self.tag_compare(s, tag):
                print "  %s matches %s" % (s['title'], tag['title']) 
                return s
        print "  No matches for %s" % tag['title']
        return None

    def tag_compare(self, g_song, tag):
        # If a google result has no track, google doesn't return a field for it
        if 'track' not in g_song:
            g_song['track'] = 0
        return g_song['title'].lower() == tag['title'].lower() and\
               g_song['artist'].lower() == tag['artist'].lower() and\
               g_song['album'].lower() == tag['album'].lower() and\
               g_song['track'] == tag['track']

    def delete_song(self, sid):
        self.wc.delete_songs(sid)
        print "  deleted song by id [%s]" % sid

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
Пример #12
0
class MusicLibrary(object):
    'Read information about your Google Music library'
    
    def __init__(self, username=None, password=None,
                 true_file_size=False, scan=True, verbose=0):
        self.verbose = False
        if verbose > 1:
            self.verbose = True

        self.__login_and_setup(username, password)
        if scan:
            self.rescan()
        self.true_file_size = true_file_size

    def rescan(self):
        self.__artists = {} # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = [] # [Album(), ...]
        self.__aggregate_albums()

    def __login_and_setup(self, username=None, password=None):
        # If credentials are not specified, get them from $HOME/.gmusicfs
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise NoCredentialException(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.'
                    % cred_path)
            if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
                raise NoCredentialException(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            self.config = ConfigParser.ConfigParser()
            self.config.read(cred_path)
            username = self.config.get('credentials','username')
            password = self.config.get('credentials','password')
            if not username or not password:
                raise NoCredentialException(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
                
        self.api = GoogleMusicAPI(debug_logging=self.verbose)
        log.info('Logging in...')
        self.api.login(username, password)
        log.info('Login successful.')
        
    def __aggregate_albums(self):
        'Get all the tracks in the library, parse into artist and album dicts'
        all_artist_albums = {} # 'Artist|||Album' -> Album()
        log.info('Gathering track information...')
        tracks = self.api.get_all_songs()
        for track in tracks:
            # Prefer the album artist over the track artist if there is one:
            artist = track['albumArtistNorm']
            if artist.strip() == '':
                artist = track['artistNorm']
            # Get the Album object if it already exists:
            key = '%s|||%s' % (formatNames(artist), formatNames(track['albumNorm']))
            album = all_artist_albums.get(key, None)
            if not album:
                # New Album
                if artist == '':
                    artist = 'unknown'
                album = all_artist_albums[key] = Album(
                    self, formatNames(track['albumNorm']))
                self.__albums.append(album)
                artist_albums = self.__artists.get(artist, None)
                if artist_albums:
                    artist_albums[formatNames(album.normtitle)] = album
                else:
                    self.__artists[artist] = {album.normtitle: album}
                    artist_albums = self.__artists[artist]
            album.add_track(track)
        log.debug('%d tracks loaded.' % len(tracks))
        log.debug('%d artists loaded.' % len(self.__artists))
        log.debug('%d albums loaded.' % len(self.__albums))

    def get_artists(self):
        return self.__artists

    def get_albums(self):
        return self.__albums

    def get_artist_albums(self, artist):
        log.debug(artist)
        return self.__artists[artist]

    def cleanup(self):
        pass
Пример #13
0
from gmusicapi import Webclient
import json

api = Webclient()
api.login('*****@*****.**', 'biffyclyro')
# => True

library = api.get_all_songs()
print json.dumps(library)
Пример #14
0
class Music(Command):
    def __init__(self, credentials):
        self.keywords = ['music']
        self.gmusic = Webclient()
        self.gmusic.login(credentials['u'], credentials['pass'])
        self.currentPlaylist = list()
        self.currentSong = dict()
        self.isPlaying = False
        self.playlistIndex = 0
        self.updateSongs()
        self.player = PCM()

    def updateSongs(self):
        self.playlists = self.gmusic.get_all_playlist_ids()["user"]
        if len(self.currentPlaylist) == 0:
            self.currentPlaylist= self.gmusic.get_playlist_songs(self.playlists['Megalist'][0])
            random.shuffle(self.currentPlaylist)

        if not self.currentSong:
            self.currentSong = self.currentPlaylist[self.playlistIndex]

        self.library = self.gmusic.get_all_songs()
            
    def play(self, cs = None):
        if cs == None:
            cs = self.currentPlaylist[self.playlistIndex]
        self.currentSong = cs
        self.isPlaying = True
#       self.player.write(self.gmusic.get_stream_audio(self.currentSong[u'id']))
        print 'play' + self.currentSong['title']

    def pause(self):
        self.isPlaying = False
        print 'pausing'

    def nextSong(self):
        self.playlistIndex += 1
        if self.playlistIndex >= len(self.currentPlaylist):
            self.playlistIndex = 0
            self.pause()
        else:
            self.play()

    def previousSong(self):
        self.playlistIndex -= 1
        if self.playlistIndex < 0:
            self.playlistIndex = 0
        self.play()

    def rickRoll(self):
        self.playlist = list()
        for song in self.library:
            if song['titleNorm'] == 'never gonna give you up':
                self.currentPlaylist = [song]
                self.playlistIndex = 0
                self.play()

    def playSong(self, songname):
        for song in self.library:
            if songname in song['titleNorm']:
                self.play(cs = song)
                self.currentPlaylist = [song]
#               tempplaylist = self.gmusic.get_playlist_songs(self.playlists['Megalist'][0])
#               random.shuffle(tempplaylist)
#               self.currentPlaylist += tempplaylist
                break
    def playAlbum(self, albumname):
        tempplaylist = list()
        for song in self.library:
            if albumname in song["albumNorm"] or albumname in song["album"]:
                tempplaylist += [song]
        if len(tempplaylist) > 0:
            self.currentPlaylist = sorted(tempplaylist, key=lambda k: k['track'])
            self.play()

    def playArtist(self, artistname):
        tempplaylist = list()
        for song in self.library:
            if artistname in song["artistNorm"] or artistname in song["artist"]:
                tempplaylist += [song]    
        if len(templaylist) > 0:
            self.currentPlaylist = tempplaylist
            random.shuffle(self.currentPlaylist)
            self.playlistIndex = 0
            self.play()

    def playPlaylist(self, playlistname):
        self.currentPlaylist = self.gmusic.get_playlist_songs(self.playlists[playlistname][0])
        random.shuffle(self.currentPlaylist)
        self.playlistIndex = 0
        self.play()

    def run(self, commandlist):
        if len(commandlist) == 0:
            if self.isPlaying == True:
                self.pause()
            else:
                self.play()
            print "music toggle"

        elif commandlist[0] == "play":
            if len(commandlist) == 1:
                if self.isPlaying == False:
                    self.play()
                    print "play music"

            elif commandlist [1] == "playlist":
                self.playPlaylist(" ".join(commandlist[2:]))

            elif commandlist [1] == "song":
                self.playSong(" ".join(commandlist[2:]))

            elif commandlist [1] == "artist":
                self.playArtist(" ".join(commandlist[2:]))

            elif commandlist[1] == "album":
                self.playAlbum(" ".join(commandlist[2:]))
            
            
        elif commandlist[0] == "pause":
            if self.isPlaying == True:
                self.pause()

        elif commandlist[0] == "next":
            self.nextSong()

        elif commandlist[0] == "previous":
            self.previousSong()

        else:
            print "m err"
Пример #15
0
    def handle(self, *args, **options):
        if GPLAY_PASS == "" or GPLAY_USER == "":
            self.stdout.write('Credentials not set up. Please edit settings.py')
            return

        api = Webclient()
        if not api.login(GPLAY_USER,GPLAY_PASS):
            self.stdout.write('Incorrect credentials, login failed')
            return

        self.stdout.write('Connected to Google Music, downloading data...')
        library = api.get_all_songs()
        self.stdout.write('Data downloaded!')
        self.stdout.write('Clearing DB...')
        cursor = connection.cursor()
        # This can take a long time using ORM commands on the Pi, so lets Truncate
        cursor.execute('DELETE FROM ' + Track._meta.db_table)
        cursor.execute('DELETE FROM ' + Album._meta.db_table)
        cursor.execute('DELETE FROM ' + Artist._meta.db_table)
        cursor.execute('DELETE FROM ' + Playlist._meta.db_table)
        cursor.execute('DELETE FROM ' + PlaylistConnection._meta.db_table)
        self.stdout.write('Parsing new data...')

        # Easier to keep track of who we've seen like this...
        artists = []
        albums = []

        for song in library:
            track = Track()

            if song['albumArtist'] == "":
                if song['artist'] == "":
                    a = "Unknown Artist"
                else:
                    a = song['artist']
            else:
                a = song['albumArtist']

            if a not in artists:
                artist = Artist()
                artist.name = a
                try:
                    artist.art_url = song['artistImageBaseUrl']
                except:
                    artist.art_url = ""
                artist.save()
                artists.append(a)
                self.stdout.write('Added artist: '+ a)
            else:
                artist = Artist.objects.get(name=a)
            track.artist = artist

            if song['album'] not in albums:
                album = Album()
                album.name = song['album']
                album.artist = artist
                try:
                    album.art_url = song['albumArtUrl']
                except:
                    album.art_url = ""
                album.save()
                albums.append(song['album'])
            else:
                album = Album.objects.get(name=song['album'])
            track.album = album

            track.name = song['title']
            track.stream_id = song['id']
            try:
                track.track_no = song['track']
            except:
                track.track_no = 0
            track.save()

        self.stdout.write('All tracks saved!')
        self.stdout.write('Getting Playlists...')
        playlists = api.get_all_playlist_ids(auto=False, user=True)
        self.stdout.write('Saving playlists...')
        for name in playlists['user']:
            for pid in playlists['user'][name]:
                p = Playlist()
                p.pid = pid
                p.name = name
                p.save()

        for playlist in Playlist.objects.all():
            self.stdout.write('Getting playlist contents for ' + playlist.name)
            songs = api.get_playlist_songs(playlist.pid)
            for song in songs:
                track = Track.objects.get(stream_id=song['id'])
                pc = PlaylistConnection()
                pc.playlist = playlist
                pc.track = track
                pc.save()

        self.stdout.write('Library saved!')
Пример #16
0
class MusicLibrary(object):
    'Read information about your Google Music library'
    
    def __init__(self, username=None, password=None, true_file_size=False):
        self.__artists = {} # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = [] # [Album(), ...]
        self.__login(username, password)
        self.__aggregate_albums()
        self.true_file_size = true_file_size

    def __login(self, username=None, password=None):
        # If credentials are not specified, get them from $HOME/.gmusicfs
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise NoCredentialException(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.'
                    % cred_path)
            if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
                raise NoCredentialException(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            config = ConfigParser.ConfigParser()
            config.read(cred_path)
            username = config.get('credentials','username')
            password = config.get('credentials','password')
            if not username or not password:
                raise NoCredentialException(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
            
        self.api = GoogleMusicAPI()
        log.info('Logging in...')
        self.api.login(username, password)
        log.info('Login successful.')
        
    def __aggregate_albums(self):
        'Get all the tracks in the library, parse into artist and album dicts'
        all_artist_albums = {} # 'Artist|||Album' -> Album()
        log.info('Gathering track information...')
        tracks = self.api.get_all_songs()
        for track in tracks:
            # Prefer the album artist over the track artist if there is one:
            artist = track['albumArtistNorm']
            if artist.strip() == '':
                artist = track['artistNorm']
            # Get the Album object if it already exists:
            key = '%s|||%s' % (formatNames(artist), formatNames(track['albumNorm']))
            album = all_artist_albums.get(key, None)
            if not album:
                # New Album
                if artist == '':
                    artist = 'unknown'
                album = all_artist_albums[key] = Album(
                    self, formatNames(track['albumNorm']))
                self.__albums.append(album)
                artist_albums = self.__artists.get(artist, None)
                if artist_albums:
                    artist_albums[formatNames(album.normtitle)] = album
                else:
                    self.__artists[artist] = {album.normtitle: album}
                    artist_albums = self.__artists[artist]
            album.add_track(track)
        log.debug('%d tracks loaded.' % len(tracks))
        log.debug('%d artists loaded.' % len(self.__artists))
        log.debug('%d albums loaded.' % len(self.__albums))

    def get_artists(self):
        return self.__artists

    def get_albums(self):
        return self.__albums

    def get_artist_albums(self, artist):
        log.debug(artist)
        return self.__artists[artist]
Пример #17
0
class Pygmy( Gtk.Window ):
    #directories = [
        #"/home/kevin/player/songs"# ,
        # "/mnt/stuff/tunez"
    #]

    artist_dictionary = {}

    def __init__( self ):
        Gtk.Window.__init__( self, title = "pygmy" )

        # set default window size
        self.set_default_size( 800, 400 )

        # initialize gobject threads
        GObject.threads_init()

        # initialize glib threads
        # glib.threads_init()

        # initialize gstreamer
        Gst.init( None )

        # need to switch from webclient eventually, because it's being deprecated
        # i don't think mobileclient works because of the android id thing
        self.api = Webclient()

        self.player = Gst.ElementFactory.make( "playbin", None )

        #self.bus = self.player.get_bus()
        #self.bus.connect("message", self.on_message)

        self.playing = False

        self.artist_store = Gtk.ListStore( str )

        self.artist_sorted = Gtk.TreeModelSort( model = self.artist_store )

        self.album_store = Gtk.ListStore( str )

        self.album_sorted = Gtk.TreeModelSort( model = self.album_store )

        # full file path, track #, title, artist, album, year, time
        self.song_store = Gtk.ListStore( str, str, int, str, str, str, str, str )

        self.song_sorted = Gtk.TreeModelSort( model = self.song_store )

        # self.album_store.append(["test"])

        self.build_login()

    def on_message( self, bus, message ):
        t = message.type
        print(message)
        if t == Gst.Message.EOS:
            self.player.set_state(Gst.State.NULL)
            self.playing = False
        elif t == Gst.Message.ERROR:
            self.player.set_state(Gst.State.NULL)
            err, debug = message.parse_error()
            #print "Error: %s" % err, debug
            self.playing = False

    def build_login( self ):
        self.login_box = Gtk.Grid()

        self.login_box.set_halign( Gtk.Align.CENTER )
        self.login_box.set_valign( Gtk.Align.CENTER )

        login_label = Gtk.Label( label = "Login to Google Play" )

        self.entry_username = Gtk.Entry()
        self.entry_username.set_placeholder_text( "User" )

        self.entry_password = Gtk.Entry()
        self.entry_password.set_visibility( False )
        self.entry_password.set_placeholder_text( "Password" )

        login_button = Gtk.Button( label = "Login" )
        login_button.connect( "clicked", self.do_login )

        self.login_box.add( login_label )
        self.login_box.attach_next_to( self.entry_username, login_label, Gtk.PositionType.BOTTOM, 1, 1 )
        self.login_box.attach_next_to( self.entry_password, self.entry_username, Gtk.PositionType.BOTTOM, 1, 1 )
        self.login_box.attach_next_to( login_button, self.entry_password, Gtk.PositionType.BOTTOM, 1, 1 )

        self.add( self.login_box )

    def do_login( self, widget ):
        # add a loading bar up here
        if self.api.login( self.entry_username.get_text(), self.entry_password.get_text() ):
            self.login_box.destroy()
            self.build_ui()
        else:
            print( "Authentication with Google failed" )

    def build_ui( self ):
        grid = Gtk.Grid()
        self.add( grid )

        # toolbar stuff
        #fixed = Gtk.Fixed()
        # fixed.set_size_request( -1, 38 )
        toolbar_parent = Gtk.VBox()

        toolbar = Gtk.HBox()
        toolbar_parent.pack_start( toolbar, True, True, 3 )
        #fixed.add( toolbar )

        # previous button
        self.button_previous = Gtk.Button()
        self.button_previous.set_image( self.get_image( icon = Gtk.STOCK_MEDIA_PREVIOUS ) )
        #self.button_previous.connect("clicked", self.on_button_previous_clicked)
        toolbar.pack_start( self.button_previous, False, False, 1 )

        # play/pause button
        self.button_play = Gtk.Button()
        self.button_play.set_image( self.get_image( icon = Gtk.STOCK_MEDIA_PLAY ) )
        self.button_play.connect( "clicked", self.play_pause )
        toolbar.pack_start( self.button_play, False, False, 1 )

        # stop button
        self.button_stop = Gtk.Button()
        self.button_stop.set_sensitive( False )
        self.button_stop.set_image( self.get_image( icon = Gtk.STOCK_MEDIA_STOP ) )
        self.button_stop.connect( "clicked", self.do_stop )
        toolbar.pack_start( self.button_stop, False, False, 1 )

        # next button
        self.button_next = Gtk.Button()
        self.button_next.set_image( self.get_image( icon = Gtk.STOCK_MEDIA_NEXT ) )
        #self.button_next.connect("clicked", self.on_button_play_clicked)
        toolbar.pack_start( self.button_next, False, False, 1 )

        #box.pack_start(fixed, True, True, 0)

        # add the fixed button bar to the grid
        grid.add( toolbar_parent )

        # browser stuff
        browser = Gtk.VPaned()
        #browser_paned = Gtk.VPaned()
        #browser.add(browser_paned)
        grid.attach_next_to( browser, toolbar_parent, Gtk.PositionType.BOTTOM, 1, 1 )

        # create columns for artist/album filters
        columns = Gtk.HBox()
        columns.set_size_request( 0, 150 )

        # define cell renderer
        cell_renderer = Gtk.CellRendererText()

        # add ellipsis with pango
        cell_renderer.props.ellipsize = Pango.EllipsizeMode.END

        # artist list
        artists_scroll = Gtk.ScrolledWindow( hexpand = True, vexpand = True )
        self.artists = Gtk.TreeView( self.artist_sorted )
        artist_column = Gtk.TreeViewColumn( "Artist", cell_renderer, text = 0 )
        self.artists.append_column( artist_column )
        self.artists.get_selection().set_mode( Gtk.SelectionMode.MULTIPLE )
        self.artist_sorted.set_sort_column_id( 0, Gtk.SortType.ASCENDING )
        artists_scroll.add( self.artists )

        #album list
        albums_scroll = Gtk.ScrolledWindow( hexpand = True, vexpand = True )
        self.albums = Gtk.TreeView( self.album_sorted )
        album_column = Gtk.TreeViewColumn( "Album", cell_renderer, text = 0 )
        self.albums.append_column( album_column )
        self.albums.get_selection().set_mode( Gtk.SelectionMode.MULTIPLE )
        self.album_sorted.set_sort_column_id( 0, Gtk.SortType.ASCENDING )
        albums_scroll.add( self.albums )

        # add items to the columns
        columns.pack_start( artists_scroll, False, True, 0 )
        columns.pack_start( albums_scroll, False, True, 0 )
        #columns.add(self.artists)

        # song list
        songs_scroll = Gtk.ScrolledWindow( hexpand = True, vexpand = True )
        self.songs = Gtk.TreeView( self.song_sorted )

        self.songs.get_selection().set_mode( Gtk.SelectionMode.MULTIPLE )

        self.songs.connect( "row-activated", self.on_song_activate )

        songs_columns = {
            "playing": Gtk.TreeViewColumn(
                title = "",
                cell_renderer = cell_renderer,
                text = 0
            ),
            "track": Gtk.TreeViewColumn(
                title = "#",
                cell_renderer = cell_renderer,
                text = 2
            ),
            "title": Gtk.TreeViewColumn(
                title = "Title",
                cell_renderer = cell_renderer,
                text = 3
            ),
            "artist": Gtk.TreeViewColumn(
                title = "Artist",
                cell_renderer = cell_renderer,
                text = 4
            ),
            "album": Gtk.TreeViewColumn(
                title = "Album",
                cell_renderer = cell_renderer,
                text = 5
            ),
            "year": Gtk.TreeViewColumn(
                title = "Year",
                cell_renderer = cell_renderer,
                text = 6
            ),
            "time": Gtk.TreeViewColumn(
                title = "Time",
                cell_renderer = cell_renderer,
                text = 7
            )
        }

        # set all columns except playing as resizable
        for column in songs_columns:
            if column != "playing":
                songs_columns[column].set_sizing( Gtk.TreeViewColumnSizing.AUTOSIZE )
                songs_columns[column].set_resizable( True )
                songs_columns[column].set_reorderable( True )

        # songs_columns[ "track" ].set_sort_column_id( 2 )
        songs_columns[ "title" ].set_sort_column_id( 3 )
        songs_columns[ "artist" ].set_sort_column_id( 4 )
        songs_columns[ "album" ].set_sort_column_id( 5 )
        songs_columns[ "year" ].set_sort_column_id( 6 )
        songs_columns[ "time" ].set_sort_column_id( 7 )

        self.song_sorted.set_sort_column_id( 4, Gtk.SortType.ASCENDING )

        # self.song_sorted.set_sort_func( 2, self.compare, None )

        # set title, artist, and album to expand
        #songs_columns[ "title" ].set_expand( True )
        #songs_columns[ "artist" ].set_expand( True )
        #songs_columns[ "album" ].set_expand( True )

        # make sure we add them in the proper order
        self.songs.append_column( songs_columns[ "playing" ] )
        self.songs.append_column( songs_columns[ "track" ] )
        self.songs.append_column( songs_columns[ "title" ] )
        self.songs.append_column( songs_columns[ "artist" ] )
        self.songs.append_column( songs_columns[ "album" ] )
        self.songs.append_column( songs_columns[ "year" ] )
        self.songs.append_column( songs_columns[ "time" ] )

        songs_scroll.add( self.songs )

        # put together the browser window
        browser.add( columns )
        browser.add( songs_scroll )

        self.find_songs()

    # demo comparison for sorting treemodelsorted
    def compare( self, model, row1, row2, user_data ):
        sort_column, _ = model.get_sort_column_id()
        value1 = model.get_value(row1, sort_column)
        value2 = model.get_value(row2, sort_column)
        if value1 < value2:
            return -1
        elif value1 == value2:
            return 0
        else:
            return 1

    def on_song_activate( self, widget, path, col ):
        # set the player state to null
        self.player.set_state( Gst.State.NULL )
        # set the player uri to the activated song url
        # HEYYYYYY
        self.player.set_property( "uri", self.api.get_stream_urls( self.song_store[ path ][ 1 ] )[ 0 ] )
        # set the player state to playing
        self.player.set_state( Gst.State.PLAYING )

    def add_artist_to_store( self, artist ):
        if not artist in self.artist_dictionary:
            self.artist_dictionary[ artist ] = 0
            
        self.artist_dictionary[ artist ] += 1

    def add_song_to_store( self, track ):
        this_artist = track[ "artist" ] if not track[ "artist" ] == "" else "Unknown"

        self.add_artist_to_store( this_artist )

        # format the time to minutes:seconds and remove the leading 0
        time_string = re.sub(
            "^0", "",
            time.strftime( "%H:%M:%S", time.gmtime( int( track[ "durationMillis" ] ) / 1000 ) )
        )

        self.song_store.append([
            "",
            track["id"],
            track["track"],
            track["title"] if not track[ "title" ] == "" else "Unknown",
            this_artist,
            track["album"] if not track[ "album" ] == "" else "Unknown",
            str( track[ "year" ] if not track[ "year" ] == 0 else "" ),
            str( time_string )
        ])

    def find_songs( self ):
        if not self.api.is_authenticated() == True:
            return

        self.library = self.api.get_all_songs()

        for track in self.library:
            self.add_song_to_store( track )

        for artist in self.artist_dictionary:
            self.artist_store.append([
                artist + " (" + str( self.artist_dictionary[ artist ] ) + ")"
            ])

        self.artist_store.append([
            "All " + str( len( self.artist_dictionary ) ) + " artists (" + str( len( self.song_store ) ) + ")"
        ])

        self.show_all()

        # parse through every directory listed in the library
        #for directory in self.directories:
            # parse through all sub-folders looking for audio audio files
            #for r,d,f in os.walk( directory ):
                #for filename in f:
                    # mime = mimetypes.guess_type( filename )
                    #mime = magic.from_file( os.path.join( r, filename ), mime = True )
                    #print(mime)
                    # make sure mime-type is not None, otherwise the match will throw an error on some files
                    #if not mime == None:
                        #match = re.match( "^audio", mime )
                        #if match:
                            # it's an audio file, add it to the library even though we're not sure gstreamer can play it
                            #self.add_song_to_store( r, filename )

    def get_image( self, icon ):
        image = Gtk.Image()
        image.set_from_stock( icon, Gtk.IconSize.BUTTON )
        return image

    def play_pause( self, widget ):
        if self.playing == False:
            #filepath = self.entry.get_text()
            #if os.path.isfile(filepath):
            self.playing = True
            self.button_stop.set_sensitive( True )
            image = self.get_image( Gtk.STOCK_MEDIA_PAUSE )
            #self.player.set_property("uri", "file://" + filepath)
            #self.player.set_state(gst.STATE_PLAYING)
        else:
            self.playing = False
            image = self.get_image( Gtk.STOCK_MEDIA_PLAY )
        self.button_play.set_image( image )

    def do_stop( self, w ):
        self.button_play.set_image( self.get_image( Gtk.STOCK_MEDIA_PLAY ) )
        #self.player.set_state(gst.STATE_NULL)
        self.playing = False
        self.button_stop.set_sensitive( False )
Пример #18
0
class GoogleMusic(RadiopieModule):
	def run(self):
		log.info("Google Music started")
		self._lcd.setFirst(" Google")
		self.__player = None
		self.__api = None
		self.__library = None
		self.loadConfiguration()
		self.googleMusicConnection()
		while not self._terminate.isSet():
			if(self._ok.isSet()):
				self._ok.clear()
				self.playCurrentSong()
			if(self._left.isSet()):
				self._left.clear()
				self._terminate.set()
			time.sleep(1)
		self.setdown()

	def googleMusicConnection(self):
		log.info("Login as user " + self.__user + " ...")
		self._lcd.setLast(" Login..")
		self.__api = Webclient()
		self.__api.login(self.__user, self.__password)
		log.info("Loading Library")
		self._lcd.setLast(" Loading")
		self.__library = self.__api.get_all_songs()
		self._lcd.setLast(" Ready")

	def playCurrentSong(self):
		log.info("Playing a song")
		if(self.__player == None):
			self.setup()
		else:
			self.__player.set_state(gst.STATE_NULL)
		self.__currentsong = self.__library[random.randint(0,len(self.__library))]
		self._lcd.setLast(self.__currentsong["title"].encode("utf-8"))
		url = self.__api.get_stream_urls(self.__currentsong["id"])
		self.__player.set_property("uri", url[0])
		self.__player.set_state(gst.STATE_PLAYING)
		log.info("Playing song " + self.__currentsong["title"] + " ... ")
	

	def setup(self):
		self.__player = gst.element_factory_make("playbin2", "player")
		bus = self.__player.get_bus()
		bus.add_signal_watch()
		bus.connect("message", self.on_status)

	def loadConfiguration(self):
		log.info("Loading settings from json ...")
		json_data = open('defaults.json')
		data = json.load(json_data)
		self.__user = data["google-music-user"]
		self.__password = data["google-music-password"]

	def setdown(self):
		self.__player.set_state(gst.STATE_NULL)

	def on_status(self, bus, message):
		t = message.type
		if(t == gst.MESSAGE_EOS):
			log.info("Song end")
			self.playCurrentSong()
		if(t == pygst.MESSAGE_ERROR):
			err, debug = message.parse_error()
			log.error(err)
			log.debug(debug)
			self.__player.set_state(gst.STATE_NONE)
	
	@staticmethod
	def getName():
		return "Google Music"