Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing Sonos Favorites #50

Open
Nibbler73 opened this issue May 4, 2016 · 6 comments
Open

Accessing Sonos Favorites #50

Nibbler73 opened this issue May 4, 2016 · 6 comments
Assignees
Milestone

Comments

@Nibbler73
Copy link
Contributor

Hello,

I'm experimenting by building a simple and child-proof controller for the sonos box. Based on a RPi with the Touchscreen and as I'm developing this in PHP, your sonos library seems to be the awesome tool to talk to Sonos.

I'd like to list the Sonos Favorites in a cover-flow style and start playing the selected Spotify/Radio/Whatever if tapped on.

I can fetch the Playlists from the Network which works great including the Album-Art.

Is there a way to fetch the Sonos Favorites, as only these are able to include Radio Stations (that is, internet radio, Spotify Radio, Amazon Prime Radio, ...).

Thanks

@duncan3dc duncan3dc self-assigned this May 5, 2016
@duncan3dc
Copy link
Owner

Hi, the library doesn't support Sonos Favourites at the moment. I'll take a look at adding this when I get some time

@duncan3dc
Copy link
Owner

I've done a bit of work on this (on the favourites branch), but as these lists can contain tracks, streams, and collections of tracks. It's not simple to handle them, eg:

$controller = $sonos->getControllerByRoom("The Hall");
$queue = $controller->getQueue();

$favourites = new Favourites($controller);

foreach ($favourites->getTracks() as $track) {
    if (isset($track->title)) {
        echo $track->title . "\n";
    } else {
        echo $track->getName() . "\n";
    }

    if ($track instanceof Stream) {
        echo "\tIgnoring Stream\n";
        continue;
    }

    if ($track instanceof \Countable) {
        if (count($track) < 1) {
            echo "\tIgnoring empty countable\n";
            continue;
        }
    }

    $queue->addTrack($track);
}

I'll continue to think about it, but it might require changing some existing classes and therefore need to be part of 2.0

@Nibbler73
Copy link
Contributor Author

This looks promising, thanks.

From the Controller-App on mobile devices, I would assume the Collection or Countable returned is most probably a Playlist from the Favourites.

Should fetching the favorites work like this?

$favourites = $sonos->getFavourites();

I'll give it a try and see if I can start working with the new Favourites() object.

Thanks for the quick reaction.

@duncan3dc
Copy link
Owner

Yeh a countable would be a playlist, it could be a Spotify playlist, or a Sonos playlist, or anything else though.
I've not added a $sonos->getFavourites() method yet, but that would probably make it in once I've figured everything else out

@duncan3dc duncan3dc added this to the 2.0 milestone Jun 15, 2017
@zoic21
Copy link

zoic21 commented Jan 14, 2018

Hi,
I test this on 2.0 version. I can get list of favourites but I can't find how to add it in queue...

@kvanisterdael
Copy link

I have done this from my code with the following methods and a SonosFavorite class. Maybe this can help...

class SonosFavorite implements UriInterface 
{
    protected $title;    
    protected $uri;    
    protected $metadata;
    
    public function __construct($title, $uri, $metadata) {
        $this->title = $title;
        $this->uri = $uri;
        $this->metadata = $metadata;
    }
    
    public function getTitle() {
        return $this->title;
    }
    
    public function getUri(): string {
        return $this->uri;
    }
    
    public function getMetaData(): string {
        return $this->metadata;
    }
    
    public function isRadio() {
        return (strpos($this->uri, 'x-sonosapi-stream:') !== false
            || strpos($this->uri, 'x-sonosapi-radio:') !== false
            || strpos($this->uri, 'pndrradio:') !== false
            || strpos($this->uri, 'x-sonosapi-hls:') !== false
            || strpos($this->uri, 'x-sonosprog-http:') !== false
            || strpos($this->uri, 'x-rincon-mp3radio:') !== false);
    }
    
    public function isLineIn() {
        return (strpos($this->uri, 'x-rincon-stream:') !== false 
            || strpos($this->uri, 'x-sonos-htastream:') !== false);
    }
}
private function getFavorites() 
    {
        // Get favorites
        if ($this->setController())
        {
            $data = $this->controller->soap("ContentDirectory", "Browse", [
                "ObjectID"          =>  "FV:2",
                "BrowseFlag"        =>  "BrowseDirectChildren",
                "Filter"            =>  "*",
                "StartingIndex"     =>  0,
                "RequestedCount"    =>  100,
                "SortCriteria"      =>  "",
            ]);
            $parser = new XmlParser($data["Result"]);
            $favorites = [];
            foreach ($parser->getTags("item") as $item) {
                $id = $item->getAttribute("id");
                $title = $item->getTag("title")->nodeValue;
                $uri = $item->getTag("res")->nodeValue;
                $metadata = $item->getTag("resMD")->nodeValue;
                $fav = new SonosFavorite($title, $uri, $metadata);
                $favorites[] = $fav;
            }
            return $favorites;
        }
        return array();
    }

private function playFavorite($fav) 
    {
        if ($this->setController())
        {
            if ($fav->isRadio() || $fav->isLineIn()) {
                // Playing radio station favorite works!
                $stream = new Stream($fav->getUri());
                $this->controller->useStream($stream)->play();
            }
            else {
                $queue = $this->controller->getQueue();
                $queue->clear();
                $this->controller->soap("AVTransport", "AddURIToQueue", [
                    "InstanceID"                        =>  0,
                    "EnqueuedURI"                       =>  $fav->getUri(),
                    "EnqueuedURIMetaData"               =>  $fav->getMetaData(),
                    "DesiredFirstTrackNumberEnqueued"   =>  0,
                    "EnqueueAsNext"                     =>  0,
                ]);                
                $this->controller->useQueue();
                $this->controller->setShuffle(true); // Always play lists in Shuffle mode
                $this->controller->play();
            }
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants