Пример #1
0
    def add_album_to_queue(self, spotify_album):
        """ Add a spotify album to the queue using the SpotifyAlbum class """
        if not spotify_album.satisfied():
            spotify_album = self._add_album_metadata(spotify_album)

        res = [
            DidlResource(uri=spotify_album.uri,
                         protocol_info="x-rincon-playlist:*:*:*"),
        ]
        item = DidlObject(spotify_album.title,
                          '',
                          spotify_album.spotify_uri,
                          resources=res)

        return self.soco.add_to_queue(item)
Пример #2
0
    def add_track_to_queue(self,
                           track: Union[deezer.resources.Track, str, int],
                           position: Optional[int] = None):
        """Add a track into Sonos queue.

        :param track: Deezer Track object or Deezer track identifier
        :param position: Position into the queue, None to the end of the queue.
        """
        if isinstance(track, deezer.resources.Track):
            track_id = str(track.id)
        elif isinstance(track, (str, int)):
            track_id = str(track)
        else:
            raise TypeError("Invalid `track` argument")
        del track

        track_id = str(track_id)

        dz_track = self.__dz.get_track(track_id)
        album_id = dz_track.get_album().id

        position = self.__valid_queue_position(position)

        prefix_item_id = prefix_id.get('track')
        prefix_parent_id = prefix_id.get('album')

        item_id = quote_url(f"tr:{track_id}")
        uri = f"x-sonos-http:{item_id}?sid=2&sn=0"

        resource = DidlResource(protocol_info="sonos.com-http:*:audio/mp4:*",
                                uri=uri)

        didl = DidlAudioItem(item_id=f"{prefix_item_id}{item_id}",
                             parent_id=f"{prefix_parent_id}album-{album_id}",
                             title=dz_track.title,
                             desc=self.__ms.desc,
                             resources=[
                                 resource,
                             ],
                             restricted=False)
        self.__add_uri_to_queue(uri, didl, position)
Пример #3
0
    def add_album_to_queue(self,
                           album: Union[deezer.resources.Album, str, int],
                           position: Optional[int] = None):
        """Add an album into Sonos queue.

        :param album: Deezer Album object or Deezer album identifier
        :param position: Position into the queue, None to the end of the queue.
        """
        if isinstance(album, deezer.resources.Album):
            album_id = str(album.id)
        elif isinstance(album, (str, int)):
            album_id = str(album)
        else:
            raise TypeError("Invalid `album` argument")
        del album

        dz_album = self.__dz.get_album(album_id)
        artist_id = dz_album.get_artist().id

        position = self.__valid_queue_position(position)

        prefix_item_id = prefix_id.get('album')
        prefix_parent_id = prefix_id.get('user-albums')

        item_id = f"{prefix_item_id}album-{album_id}"
        uri = f"x-rincon-cpcontainer:{item_id}"

        resource = DidlResource(protocol_info="x-rincon-cpcontainer:*:*:*",
                                uri=uri)

        didl = DidlAlbum(
            item_id=item_id,
            parent_id=f"{prefix_parent_id}user-albums-{artist_id}",
            title=dz_album.title,
            desc=self.__ms.desc,
            resources=[
                resource,
            ],
            restricted=False)
        self.__add_uri_to_queue(uri, didl, position)
Пример #4
0
    def add_playlist_to_queue(self,
                              playlist: Union[deezer.resources.Playlist, str,
                                              int],
                              position: Optional[int] = None):
        """Add an playlist into Sonos queue.

        :param playlist: Deezer playlist object or Deezer playlist identifier
        :param position: Position into the queue, None to the end of the queue.
        """
        if isinstance(playlist, deezer.resources.Playlist):
            playlist_id = str(playlist.id)
        elif isinstance(playlist, (str, int)):
            playlist_id = str(playlist)
        else:
            raise TypeError("Invalid `playlist` argument")
        del playlist

        dz_playlist = self.__dz.get_playlist(playlist_id)

        position = self.__valid_queue_position(position)

        prefix_parent_id = prefix_id.get('user-albums')

        item_id = f"{prefix_parent_id}playlist_spotify%3aplaylist-{playlist_id}"
        uri = f"x-rincon-cpcontainer:{item_id}"

        resource = DidlResource(protocol_info="x-rincon-cpcontainer:*:*:*",
                                uri=uri)

        didl = DidlPlaylistContainer(
            item_id=item_id,
            parent_id=
            f"{prefix_parent_id}playlist_spotify:playlist-{playlist_id}",
            title=dz_playlist.title,
            desc=self.__ms.desc,
            resources=[
                resource,
            ],
            restricted=False)
        self.__add_uri_to_queue(uri, didl, position)
Пример #5
0
    def add_from_service(self, item_id, service, is_track=True):
        # The DIDL item_id is made of the track_id (url escaped), but with an 8
        # (hex) digit prefix. It is not clear what this is for, but it doesn't
        # seem to matter (too much) what it is. We can use junk (thought the
        # first digit must be 0 or 1), and the player seems to do the right
        # thing. Real DIDL items sent to a player also have a title and a
        # parent_id (usually the id of the relevant album), but they are not
        # necessary. The flow charts at http://musicpartners.sonos.com/node/421
        # and http://musicpartners.sonos.com/node/422 suggest that it is the job
        # of the player, not the controller, to call get_metadata with a track
        # id, so this might explain why no metadata is needed at this stage.

        # NB: quote_url will break if given unicode on Py2.6, and early 2.7. So
        # we need to encode.

        if self.device is None:
            return

        item_id = quote_url(item_id.encode('utf-8'))
        didl_item_id = "0fffffff{0}".format(item_id)

        # For an album:
        if not is_track:
            uri = 'x-rincon-cpcontainer:' + didl_item_id

        else:
            # For a track:
            uri = service.sonos_uri_from_id(item_id)

        res = [DidlResource(uri=uri, protocol_info="Snips")]
        didl = DidlItem(
            title="Snips",
            # This is ignored. Sonos gets the title from the item_id
            parent_id="Snips",  # Ditto
            item_id=didl_item_id,
            desc=service.desc,
            resources=res)

        self.device.add_to_queue(didl)
Пример #6
0
def handle_library_item(uri):
    global spkr
    global album_prefix

    logger.info('PLAYING FROM LIBRARY: ' + uri)
    # TODO: re-implement queue-building as in chrispcampbell original
    ############
    #
    # Playing albums
    #
    #############

    # to playback, construct a dummy DidlMusicAlbum to send to sonos queue
    # needed to play album: URI, and album_id
    # all albums share URI, which is:
    # x-rincon-playlist:RINCON_[uuid of sonos zone]
    # album_id can be got from QR code. It looks like:
    # alb:A:ALBUM/Bone%20Machine
    # albums can also be hashed. they look like:
    # alb:hsh:[hashed_id]

    if 'alb:' in uri:
        # if this is a 'hashed' album, get album id from hashed resource
        if 'hsh:' in uri:
            with open(hashed_albums, 'rb') as r:
                b = pickle.loads(r.read())
            album_id = b[uri]
        else:
            album_id = uri[4:]
        album_fullURI = album_prefix + '#' + album_id
        logging.info('sending full uri %s' % (album_fullURI))

        # SoCo needs a DidlResource object to play albums
        # We can construct a 'dummy' DidlResource with generic metadata,
        # and when this is passed to the speaker, SoCo/Sonos will be able to fetch
        # the album from the music library.
        res = [DidlResource(uri=album_fullURI, protocol_info='dummy')]
        didl = soco.data_structures.DidlMusicAlbum(title='dummy',
                                                   parent_id='dummy',
                                                   item_id=album_id,
                                                   resources=res)
        spkr.clear_queue()
        spkr.add_to_queue(didl)
        spkr.play()

    ########
    #
    # Playing playlists or tracks
    #
    #########

    # to playback, you need only the URI of the playlist/track,
    # which comes in one of two forms.
    # Sonos playlist looks like:
    # file:///jffs/settings/savedqueues.rsq#0
    # Imported itunes playlist looks like:
    # x-file-cifs://computer/music/iTunes/iTunes%20Music%20Library.xml#9D1D3FDCFDBB6751
    # Track looks like:
    # x-file-cifs://computer/music/iTunes/Music/Original%20Soundtrack/Chants%20From%20The%20Thin%20Red%20Line/01%20Jisas%20Yu%20Hand%20Blong%20Mi.mp3

    elif 'pl:' in uri:
        pluri = uri[3:]
        spkr.clear_queue()
        spkr.add_uri_to_queue(uri=pluri)
        spkr.play()
    elif 'trk:' in uri:
        # look up hashuri in hashed tracks
        with open(hashed_tracks, 'rb') as r:
            b = pickle.loads(r.read())
        trkuri = b[uri]
        spkr.clear_queue()
        spkr.add_uri_to_queue(uri=trkuri)
        spkr.play()