jishi / node-sonos-http-api

An HTTP API bridge for Sonos easing automation. Hostable on any node.js capable device, like a raspberry pi or similar.
http://jishi.github.io/node-sonos-http-api/
MIT License
1.85k stars 463 forks source link

FeatureRequest: show current cover #143

Closed MartinEhg closed 8 years ago

MartinEhg commented 8 years ago

is it possible to implement a feature to show the current cover?

Maybe with the action 'cover' you can implement it. I'm not able to understand nodejs, but in your state.js you implement a function called fixAlbumArtURI. Are you able to show this cover?

command: .../room/cover or better .../room/cover/80 for a coversize of 80x80

I've add a cover function like ...

function cover(player, values, callback) { var state = player.getState(); state.currentTrack.absoluteAlbumArtURI = fixAlbumArtURI(player.address, state.currentTrack.albumArtURI); callback(state.currentTrack.absoluteAlbumArtURI); }

and registerAction:

module.exports = function (api) { api.registerAction('state', state); api.registerAction('cover', cover); }

this show me the hyperlink to the cover, but I want to see the cover instead! ;-)

Hope you will help!

jishi commented 8 years ago

Please describe in what way you would like to utilize this instead. Getting a url to a cover is usually what people want, because the would like to update some interface with it when changes occur.

Maybe you find it convenient to get the image in your browser, or whatever, but that is not really the intended use case. Also, your code basically just output the url in plain text, which is even weirder? The concept is that you receive a JSON data object, from which you would access the album art with something like:

state.currentTrack.absoluteAlbumArtURI

after you have parsed the JSON data.

MartinEhg commented 8 years ago

OK, i understand. I used an android tablet and inside the home control app (Mediola NEO) it is only possible to show websites. So I need an url which show the cover directly.

Do you have a hint for me how to show a cover? I will use your code and didn't want to use a second api in php for example. I'm able to code php but node js is new for me.

I start with a php api which called your api. But if you could give me a tip how I can show the cover with node, it was very useful for me.

jishi commented 8 years ago

But are you expecting a direct link to the image (like, http://localhost:5005/your/image.jpg), or a webpage with just the image embedded like an html file with an img src-tag?

Both of them are possible, but I need to know before giving you a solution.

MartinEhg commented 8 years ago

In the past, I used the following code inside my php. So you can see that I need an image embedded inside an html file.

[..] echo '<br>URL:' . $coverurl; echo "<body bgcolor=$_bkcolor>"; echo "<p><img src='$coverurl' align='top' align='left' WIDTH=$size HEIGHT=$size/></p>"; } [..]

jishi commented 8 years ago

On a second thought, this will not be possible without some major changes in the api, since this was build with api calls in mind, and not html/image serving. It's fairly simple to build your own system for it though, but it would mean that you would host it as a second node process. I don't know if that would be better than your PHP solution, it depends on why you want to remove the PHP solution.

MartinEhg commented 8 years ago

It is ok for me, if you wouldn't support this feature, but please give me a tipp how I can do.

It would be great, if you can show me an example how I build an html page with node with the embedded cover. I will use it in my cover function. See first post. I use your api to control my sonos and the only function l miss, is to show the cover. I don't want to use a second (php) script to do this.

NovaGL commented 8 years ago

It is possible, I made my own PHP file which looks at the JSON and converts it to a readable JPEG file.

The problem is sometimes the albumart is absoluteAlbumArtURI and sometimes it's albumArtURI.

Also I linked it to Last.fm so if neither field has a JPG then it searches for a relevant one from Last.fm.

Can't share my code as it took a long time to do, but just wanted to say it's possible.

MartinEhg commented 8 years ago

Hello Jishi , I'm writing a php sonos api, now. Every api I've found at githib isn't able to read the AlbumCoverUri if the player plays a radiostream. But it works if the player plays a song from spotify for example. I try the SOAP message 'GetPositionInfo' but the answer is empty for the AlbumCoverUri.

Could you give me a hint? What Soap-massage are you send to get this Informationen also for radiostreams?

My decision to write my own api, is the cover feature (Show the cover als html). Your api support everything instead of this.

jishi commented 8 years ago

The position info is an endpoint which is polled primarily to update the progress for a time bar. There should be a call names GetTransportInfo or similar, which would contain the info you are talking about.

MartinEhg commented 8 years ago

Hi,

first of all, thank you for your help.

In my opinion, only the Soap-Message „GetPositionInfo“ return the track and album datas like the ‚albumArtURI'. Your mentioned message ‚GetTransportInfo‘ return the player status (playing, stopped, paused).

I’ve tested a lot of php apis, but only you are able to read the albumArtURI if a radio stream is playing. So my question is: What do you do?

Please look at the difference of the answers at . At the second answer, you can find the substring 'upnp:albumArtURI'. This substing give me the possibility to read out the location of the album cover. Why isn't this substing returned when I hear a streaming radio channel?

My-SOAP-Massage:

0
    /u:GetPositionInfo
/s:Body

/s:Envelope'

Answer while playing a radio stream:

1
        <TrackDuration>0:00:00</TrackDuration>
        <TrackMetaData>&lt;DIDL-Lite xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot; xmlns:r=&quot;urn:schemas-rinconnetworks-com:metadata-1-0/&quot; xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot;&gt;&lt;item id=&quot;-1&quot; parentID=&quot;-1&quot; restricted=&quot;true&quot;&gt;&lt;res protocolInfo=&quot;x-rincon-mp3radio:_:_:*&quot;&gt;x-rincon-mp3radio://1live.akacast.akamaistream.net/7/706/119434/v1/gnl.akacast.akamaistream.net/1live&lt;/res&gt;&lt;r:streamContent&gt;1LIVE mit Olli Briesch und dem Imhof Die tägliche, aktuelle Morgen-Show in 1LIVE&lt;/r:streamContent&gt;&lt;dc:title&gt;1live&lt;/dc:title&gt;&lt;upnp:class&gt;object.item&lt;/upnp:class&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData>
        <TrackURI>x-rincon-mp3radio://1live.akacast.akamaistream.net/7/706/119434/v1/gnl.akacast.akamaistream.net/1live</TrackURI>
        <RelTime>0:01:56</RelTime>
        <AbsTime>NOT_IMPLEMENTED</AbsTime>
        <RelCount>2147483647</RelCount>
        <AbsCount>2147483647</AbsCount>
    /u:GetPositionInfoResponse
/s:Body

/s:Envelope'

Answer while playing a single track (spotify):

1
        <TrackDuration>0:02:46</TrackDuration>
        <TrackMetaData>&lt;DIDL-Lite xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot; xmlns:r=&quot;urn:schemas-rinconnetworks-com:metadata-1-0/&quot; xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot;&gt;&lt;item id=&quot;-1&quot; parentID=&quot;-1&quot; restricted=&quot;true&quot;&gt;&lt;res protocolInfo=&quot;sonos.com-spotify:_:audio/x-spotify:_&quot; duration=&quot;0:02:46&quot;&gt;x-sonos-spotify:spotify%3atrack%3a6lDo13SSgTv0WbyUQKgnjk?sid=9&amp;amp;flags=8224&amp;amp;sn=4&lt;/res&gt;&lt;r:streamContent&gt;&lt;/r:streamContent&gt;&lt;upnp:albumArtURI&gt;/getaa?s=1&amp;amp;u=x-sonos-spotify%3aspotify%253atrack%253a6lDo13SSgTv0WbyUQKgnjk%3fsid%3d9%26flags%3d8224%26sn%3d4&lt;/upnp:albumArtURI&gt;&lt;dc:title&gt;Light It Up (feat. Nyla &amp;amp; Fuse ODG) - Remix&lt;/dc:title&gt;&lt;upnp:class&gt;object.item.audioItem.musicTrack&lt;/upnp:class&gt;&lt;dc:creator&gt;Major Lazer&lt;/dc:creator&gt;&lt;upnp:album&gt;Peace Is The Mission: Extended&lt;/upnp:album&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData>
        <TrackURI>x-sonos-spotify:spotify%3atrack%3a6lDo13SSgTv0WbyUQKgnjk?sid=9&amp;flags=8224&amp;sn=4</TrackURI>
        <RelTime>0:00:04</RelTime>
        <AbsTime>NOT_IMPLEMENTED</AbsTime>
        <RelCount>2147483647</RelCount>
        <AbsCount>2147483647</AbsCount>
    /u:GetPositionInfoResponse
/s:Body

/s:Envelope

Here my PHP script to do this:

<?php

    $IP    = '192.168.179.210';
    $PORT  = '1400';

    $url = '/MediaRenderer/AVTransport/Control';
    $action = 'GetPositionInfo';
    $service = 'urn:schemas-upnp-org:service:AVTransport:1';
    $args = '<InstanceID>0</InstanceID>';

    $SOAP_action = $action;
    $SOAP_service = $service;
    $SOAP_arguments = $args;
    $XML_filter = '';

    $POST_xml = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">';
    $POST_xml .= '<s:Body>';
    $POST_xml .= '<u:'.$SOAP_action.' xmlns:u="'.$SOAP_service.'">';
    $POST_xml .= $SOAP_arguments;
    $POST_xml .= '</u:'.$SOAP_action.'>';
    $POST_xml .= '</s:Body>';
    $POST_xml .= '</s:Envelope>';

     print_r($POST_xml);

    $POST_url = $IP.":".$PORT.$url;

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_URL, $POST_url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/xml", "SOAPAction: ".$SOAP_service."#".$SOAP_action));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $POST_xml);
    $r = curl_exec($ch);
    curl_close($ch);

    var_dump($r);

?>

Am 15.02.2016 um 09:49 schrieb Jimmy Shimizu - notifications@github.com github.meb.d53d6d3e05.notifications#github.com@ob.0sg.net:

The position info is an endpoint which is polled primarily to update the progress for a time bar. There should be a call names GetTransportInfo or similar, which would contain the info you are talking about.

— Reply to this email directly or view it on GitHub https://github.com/jishi/node-sonos-http-api/issues/143#issuecomment-184117301.

jishi commented 8 years ago

Well, the difference might be that I only rely on the events for trackinfo. This means that I don't poll the players for this info, the players push it to me when things change. If my API actually has a correct album art, that means that the evented data differs from the data that you can poll, unless there is some sort of bug where it just "remembers" the last cover art that was available, and what you actually see is the remnant of a bug.

ErwinvanderZwart commented 8 years ago

Hi Jishi,

Thanks for the great work!

I have a question and maybe you can help me out...

I'm looking for a way to extract the absolute URL from the TrackMetaData when playing streaming content. I can get album art from any local media, but when i use a streaming source i cannot find any documentation / solution on the net to resolve the albumart.

Do you know how to do this? i assume you do (:

Thanks!

BR,

Erwin