Ejemplo n.º 1
0
class MyCdList:

    mm = None
    library = None

    def authenticatewithgoogle(self, option):

        self.mm = Musicmanager()
        self.mm.login()  # currently named oauth_login for the Mobileclient

        if option == 0:
            self.library = self.mm.get_purchased_songs()
        elif option == 1:
            self.library = self.mm.get_uploaded_songs()

    def getallartist(self):
        donotaddthis = "The 100 Most Essential Pieces of Classical Music"
        artists = []
        artistsset = set()
        [
            artistsset.add(track['artist']) for track in self.library
            if track['album'] != donotaddthis
        ]
        artists = list(artistsset)
        artists.sort()
        return artists

    def getalbumsforartist(self, artist):

        albums = []
        albumsset = set()
        [
            albumsset.add(track['album']) for track in self.library
            if track['artist'] == artist
        ]
        albums = list(albumsset)
        albums.sort()
        return albums
Ejemplo n.º 2
0
def play_song_by_artist(song, artist):
    if Mobileclient.is_authenticated(gpm):
        mm = Musicmanager()
        mm.login('/home/pi/oauth.cred')

        if Musicmanager.is_authenticated(mm):
            song_dict = mm.get_purchased_songs()
            song_pattern = re.compile(
                r'(?:.)*\s?(' + re.escape(song) + r')\s?(?:.)*', re.IGNORECASE)
            artist_pattern = re.compile(
                r'(?:.)*\s?(' + re.escape(artist) + r')\s?(?:.)*',
                re.IGNORECASE)

            btn = OnButtonPress()
            btn.start()

            for song in song_dict:
                m = re.match(artist_pattern, song['artist'])
                print(m)

                if (re.match(song_pattern, song['title']) is not None and
                        re.match(artist_pattern, song['artist']) is not None):
                    print('Song found!')
                    song_id = song['id']
                    (filename, audio) = mm.download_song(song_id)

                    # get rid of non-ascii characters in file name

                    filename = filename.encode('ascii', errors='ignore')

                    # check if song is already downloaded
                    # path will look something like:
                    # /home/pi/Music/02 - Raindrop Prelude.mp3
                    # forces filename to be a string

                    filename = filename.decode('ascii')
                    path = song_location + filename
                    try:
                        if os.path.isfile(path):
                            print('Song is already downloaded...')
                            print(path)
                            print('Playing song.')

                            vlc_instance = vlc.Instance()

                            p = vlc_instance.media_player_new()
                            media = vlc_instance.media_new(path)

                            p.set_media(media)
                            events = p.event_manager()
                            events.event_attach(
                                vlc.EventType.MediaPlayerEndReached,
                                SongFinished)
                            p.play()
                            p.audio_set_volume(58)

                            while finish == 0:
                                duration = p.get_time() / 1000
                                (m, s) = divmod(duration, 60)

                                print('Current song is: ', path)
                                print('Length:', '%02d:%02d' % (m, s))
                                time.sleep(5)

                            p.stop()
                            break
                        else:
                            with open(path, 'wb') as f:
                                f.write(audio)
                            print('Song has been added to: ' + path)
                            print('Playing song.')

                            vlc_instance = vlc.Instance()

                            p = vlc_instance.media_player_new()
                            media = vlc_instance.media_new(path)

                            p.set_media(media)
                            events = p.event_manager()
                            events.event_attach(
                                vlc.EventType.MediaPlayerEndReached,
                                SongFinished)
                            p.play()
                            p.audio_set_volume(58)

                            while finish == 0:
                                duration = p.get_time() / 1000
                                m, s = divmod(duration, 60)

                                print('Current song is: ', path)
                                print('Length:', '%02d:%02d' % (m, s))
                                time.sleep(5)

                            p.stop()
                            break
                    except (OSError, IOError):
                        print('An error has occurred.')
                        break

                else:
                    print('Song not found yet.')

        else:
            print('Looks like you need to authenticate.')
            mm.perform_oauth('/home/pi/oauth.cred')

        print('Logging out.')
        Mobileclient.logout(gpm)
        mm.logout()

    else:
        print('Mobile client is not authenticated.')
        Mobileclient.logout(gpm)
Ejemplo n.º 3
0
#! /usr/bin/env python3

from gmusicapi import Musicmanager
from os.path import expanduser, join

mm = Musicmanager()
if not mm.login():
    print('Login failed: did you run oauth_login.py?')
    quit()

# No point properly checking for duplicates when overwriting them
# gives the same result.
songs = {}
for song in mm.get_purchased_songs():
    songs[song['id']] = ' - '.join(
        [song['title'], song['artist'], song['album']]
    )
for song in mm.get_uploaded_songs():
    songs[song['id']] = ' - '.join(
        [song['title'], song['artist'], song['album']]
    )

print('Downloading %d songs to ~/.local/share/gpymusic/songs. '
      'This might take a while...' % len(songs))

song_dir = join(expanduser('~'), '.local', 'share', 'gpymusic', 'songs')
i = 1

for id in songs:
    print('%d/%d: %s' % (i, len(songs), songs[id]))
    dl_path = join(song_dir, '%s.mp3' % songs[id].replace('/', '---'))
Ejemplo n.º 4
0
class TheGoogs:

    DEFAULT_CREDS_DIR = "~/gmusic/.oauth"
    DEFAULT_MOBILE_DEVICE_ID = "342e914abacc484d"  # Galaxy Tab
    DEFAULT_MANAGER_MAC_ADDRESS = "A2:C2:E2:CC:C7:37"  # Made-up

    def __init__(self, creds_dir=DEFAULT_CREDS_DIR):
        self.creds_dir = os.path.expanduser(creds_dir)
        logger.info("Creating TheGoogs from creds at {}".format(
            self.creds_dir))
        self.mobile_creds = os.path.join(self.creds_dir, "mobile.creds")
        self.manager_creds = os.path.join(self.creds_dir, "manager.creds")

        self.mobile = Mobileclient()
        self.manager = Musicmanager()

        logger.debug("Logging in")
        self.mobile.oauth_login(device_id=self.DEFAULT_MOBILE_DEVICE_ID,
                                oauth_credentials=self.mobile_creds)
        self.manager.login(uploader_id=self.DEFAULT_MANAGER_MAC_ADDRESS,
                           oauth_credentials=self.manager_creds)

    def get_libdata(self):
        logger.info("Fetching libdata ...")

        logger.info("... fetching registered devices")
        registered_devices = self.mobile.get_registered_devices()

        logger.info("... fetching all songs")
        library = self.mobile.get_all_songs()

        logger.info("... fetching playlist metadata")
        playlists = self.mobile.get_all_playlists()

        logger.info("... fetching playlist contents")
        playlist_contents = self.mobile.get_all_user_playlist_contents()

        logger.info("... fetching uploaded songs")
        uploaded_songs = self.manager.get_uploaded_songs()

        logger.info("... fetching purchased songs")
        purchased_songs = self.manager.get_purchased_songs()

        return Libdata(timestamp=datetime.utcnow(),
                       registered_devices=registered_devices,
                       all_songs=library,
                       playlist_metadata=playlists,
                       playlists=playlist_contents,
                       uploaded_songs=uploaded_songs,
                       purchased_songs=purchased_songs)

    def get_streamed_song(self, id):
        logger.info("Downloading streamed song id {}".format(id))
        stream_url = self.mobile.get_stream_url(id)
        response = urllib.request.urlopen(stream_url)
        return response.read()

    def get_uploaded_song(self, id):
        logger.info("Downloading uploaded song id {}".format(id))
        suggested_filename, data = self.manager.download_song(id)
        return data
Ejemplo n.º 5
0
class FreeClient(Client):
    """
    Client for free users with limited functionality.
      Free users only have access to songs that they have either purchased
      or uploaded, and they must be downloaded before they can be played.
      Artists and albums cannot be generated, so the expand method has no use.
    """
    def __init__(self):
        """
        Log into Musicmanager and get the library, either by loading an
          existing library file, or by generating a new one.
        """
        self.kind = 'free'
        self.mm = Musicmanager()
        self.mm.login()
        self.songs = []
        self.load_library()
        if not self.songs:
            self.gen_library()

    def load_library(self):
        path = join(common.DATA_DIR, 'library.zip')
        common.w.outbar_msg('Loading library...')
        if not isfile(path):
            common.w.addstr(common.w.infobar, 'Could not find library file.')
            return
        try:
            with zipfile.ZipFile(path) as z:
                try:
                    lib = json.loads(z.read('library.json').decode('utf-8'))
                except json.JSONDecodeError:  # The .json file is invalid.
                    common.w.addstr(common.w.infobar,
                                    'Library file is corrupt.')
                    return
        except zipfile.BadZipFile:  # The .zip file is invalid.
            common.w.addstr(common.w.infobar, 'Library file is corrupt.')
            return

        for item in lib['songs']:
            try:
                self.songs.append(
                    music_objects.LibrarySong(item, source='json'))
            except KeyError:  # The file has the wrong data.
                common.w.addstr(common.w.infobar, 'Library file is corrupt.')
                return

        l = len(self.songs)
        common.w.outbar_msg('Loaded %s song%s.' % (l, '' if l is 1 else 's'))

    def gen_library(self):
        ids = []  # Avoid duplicates between purchased and uploaded songs.
        common.w.outbar_msg('Generating your library...')

        for song in self.mm.get_uploaded_songs():
            if song['id'] not in ids:
                self.songs.append(music_objects.LibrarySong(song))
                ids.append(song['id'])
        for song in self.mm.get_purchased_songs():
            if song['id'] not in ids:
                self.songs.append(music_objects.LibrarySong(song))
                ids.append(song['id'])
        # Todo: Use something other than json for library storage since it
        # doesn't really make logical sense (songs is a list, not a dict),
        # but for now it's very easy to use.
        with zipfile.ZipFile(join(common.DATA_DIR, 'library.zip'), 'w') as z:
            z.writestr('library.json', json.dumps({'songs': self.songs}))
        l = len(self.songs)
        common.w.outbar_msg('Generated %d song%s.' %
                            (l, '' if l is 1 else 's'))
        common.w.now_playing()

    def expand(self, arg=None):
        """
        Artists/albums cannot be generated. so free users cannot expand songs..

        Keyword arguments:
        arg=None: Irrelevant.
        """
        common.q.error_msg('Free users cannot use expand')

    def search(self, query):
        """
        Search the library for some query. and update the
          view with the results.

        Keyword arguments:
        query=None: The search query.
        """
        if query is None:
            common.w.error_msg('Missing search query')
            return

        # Save the current view in case there are no results.
        cache = common.v.copy()

        if common.w.curses:
            limit = common.w.main.getmaxyx()[0] - 4
        else:
            limit = 50
        common.w.outbar_msg('Searching for \'%s\'...' % query)
        common.v.clear()
        count, query = 0, query.lower()  # Search is case-insensitive.
        for song in self.songs:
            if any(query in song[k].lower()
                   for k in ('name', 'artist', 'album')):
                count += 1
                common.v['songs'].append(song)
                if count == limit:
                    break
        common.w.outbar_msg('Search returned %d results.' % len(common.v))

        if common.v.is_empty():
            common.v.replace(cache)
Ejemplo n.º 6
0
class FreeClient(Client):
    """
    Client for free users with limited functionality.
      Free users only have access to songs that they have either purchased
      or uploaded, and they must be downloaded before they can be played.
      Artists and albums cannot be generated, so the expand and radio methods
      have no use.
    """
    def __init__(self):
        """
        Log into Musicmanager and get the library, either by loading an
          existing library file, or by generating a new one.
        """
        self.kind = 'free'
        self.mm = Musicmanager()
        self.mm.login()
        self.songs = []
        self.load_library()
        if not self.songs:
            self.gen_library()

    def load_library(self):
        path = join(common.DATA_DIR, 'library.zip')
        common.w.outbar_msg('Loading library...')
        if not isfile(path):
            common.w.addstr(common.w.infobar, 'Could not find library file.')
            return
        try:
            with zipfile.ZipFile(path) as z:
                try:
                    lib = json.loads(z.read('library.json').decode('utf-8'))
                except json.JSONDecodeError:  # The .json file is invalid.
                    common.w.addstr(
                        common.w.infobar, 'Library file is corrupt.'
                    )
                    return
        except zipfile.BadZipFile:  # The .zip file is invalid.
            common.w.addstr(common.w.infobar, 'Library file is corrupt.')
            return

        for item in lib['songs']:
            try:
                self.songs.append(
                    music_objects.LibrarySong(item, source='json'))
            except KeyError:  # The file has the wrong data.
                common.w.addstr(common.w.infobar, 'Library file is corrupt.')
                return

        l = len(self.songs)
        common.w.outbar_msg('Loaded %s song%s.' % (l, '' if l is 1 else 's'))

    def gen_library(self):
        ids = []  # Avoid duplicates between purchased and uploaded songs.
        common.w.outbar_msg('Generating your library...')

        for song in self.mm.get_uploaded_songs():
            if song['id'] not in ids:
                self.songs.append(music_objects.LibrarySong(song))
                ids.append(song['id'])
        for song in self.mm.get_purchased_songs():
            if song['id'] not in ids:
                self.songs.append(music_objects.LibrarySong(song))
                ids.append(song['id'])
        # Todo: Use something other than json for library storage since it
        # doesn't really make logical sense (songs is a list, not a dict),
        # but for now it's very easy to use.
        with zipfile.ZipFile(join(common.DATA_DIR, 'library.zip'), 'w') as z:
            z.writestr('library.json', json.dumps({'songs': self.songs}))
        l = len(self.songs)
        common.w.outbar_msg(
            'Generated %d song%s.' % (l, '' if l is 1 else 's')
        )
        common.w.now_playing()

    def expand(self, arg=None):
        """
        Artists/albums cannot be generated. so free users cannot expand songs..

        Keyword arguments:
        arg=None: Irrelevant.
        """
        common.q.error_msg('Free users cannot use expand')

    def radio(self, arg=None):
        """
        Artists/albums cannot be generated. so free users cannot create radio
        stations.

        Keyword arguments:
        arg=None: Irrelevant.
        """
        common.q.error_msg('Free users cannot use radio')

    def search(self, query):
        """
        Search the library for some query. and update the
          view with the results.

        Keyword arguments:
        query=None: The search query.
        """
        if query is None:
            common.w.error_msg('Missing search query')
            return

        # Save the current view in case there are no results.
        cache = common.v.copy()

        if common.w.curses:
            limit = common.w.ylimit - 4
        else:
            limit = 10
        common.w.outbar_msg('Searching for \'%s\'...' % query)
        common.v.clear()
        count, query = 0, query.lower()  # Search is case-insensitive.
        for song in self.songs:
            if any(query in song[k].lower()
                   for k in ('name', 'artist', 'album')):
                count += 1
                common.v['songs'].append(song)
                if count == limit:
                    break
        common.w.outbar_msg('Search returned %d results.' % len(common.v))

        if common.v.is_empty():
            common.v.replace(cache)