Ejemplo n.º 1
0
def spotify_add_album(device, service, service_id, pos=0):
    '''
    Add a spotify album to the queue. Seems to work also with an artist's TopTracks and Radio.

    Parameters:
    device:       a soco device (eg device = list(soco.discover())[0].group.coordinator)
    service:      a spotify music service object (eg soco.music_services.MusicService('Spotify'))
    service_id:   the spotify id of the album to be added (eg 'spotify:album:5qo7iEWkMEaSXEZ7fuPvC3')
    pos:          the desired position in the queue, or 0 for the end of the queue

    Returns:
    The enqueued position of the first item, as returned by device
    '''
    item_id = '0fffffff{0}'.format(quote_url(service_id))
    meta = '''<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" \
xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" \
xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" \
xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">\
<item id="{0}" parentID="DUMMY" restricted="true">\
<dc:title>DUMMY</dc:title>\
<upnp:class>object.container.album.musicAlbum</upnp:class>\
<desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">{1}</desc>\
</item></DIDL-Lite>'''.format(item_id, service.desc)

    try:
        response = device.avTransport.AddURIToQueue([
            ('InstanceID', 0),
            ('EnqueuedURI', 'x-rincon-cpcontainer:' + item_id),
            ('EnqueuedURIMetaData', meta),
            ('DesiredFirstTrackNumberEnqueued', pos),
            ('EnqueueAsNext', 1 if pos == 0 else 0)
        ])
        return int(response['FirstTrackNumberEnqueued'])
    except Exception as ex:
        print(ex)
Ejemplo n.º 2
0
def AddToQueue(artist = '', song = '', url = '', queue_position = 0, playnow = False, keepinqueue = True):
    if not url:
        results = service.search(category='tracks', term=song)
        tracks = results.items().pop()[1]

        for track in tracks:
            currentArtist = track.items()[4][1].items()[1][1]
            if currentArtist == artist:
                break

        #track_id = "spotify:track:2qs5ZcLByNTctJKbhAZ9JE"
        track_id = track.items()[0][1]
    else:
        segmentedurl = urlparse.urlparse(url)
        segmentedpath = segmentedurl[2].split('/')
        trackHash = segmentedpath[len(segmentedpath) - 1]
        track_id = "spotify:track:" + trackHash


    didl = DidlMusicTrack(
        title="DUMMY",  # This is ignored. Sonos gets the title from the item_id
        parent_id="DUMMY",  # Ditto
        item_id="0fffffff{0}".format(quote_url(track_id)),
        desc=service.desc
    )

    meta = to_didl_string(didl)

    # Add it to the queue and play it
    response = sonos.avTransport.AddURIToQueue([
        ("InstanceID", 0),
        ("EnqueuedURI", service.sonos_uri_from_id(
            track_id)),
        ("EnqueuedURIMetaData", meta),
        ("DesiredFirstTrackNumberEnqueued", queue_position),
        ("EnqueueAsNext", 1)
    ])
    index = int(response["FirstTrackNumberEnqueued"]) - 1

    if playnow:
        sonos.play_from_queue(index, True)

    if not keepinqueue:

        thr = threading.Thread(target=RemoveItemFromQueue, args=[index], kwargs={})
        thr.start() # will run "foo"

    return True
Ejemplo n.º 3
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&amp;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)
Ejemplo n.º 4
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)
def add_from_service(item_id, service, device, 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.


    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="DUMMY")]
    didl = DidlItem(title="DUMMY",
        # This is ignored. Sonos gets the title from the item_id
        parent_id="DUMMY",  # Ditto
        item_id=didl_item_id,
        desc=service.desc,
        resources=res)

    device.add_to_queue(didl)