Getting metadata (track info, artist name etc.) for radio stream - sonos

I have already checked the following links but they weren't much helpful (in parenthesis I've explained why it didn't work in my case as suggested in their answers)
Streams - hasOutOfBandMetadata and getStreamingMetadata (our content is already HLS)
Sonos player not calling GetStreamingMetadata (getMetdata is not called, only getMediaMetada is called since radio stream has unique id and is not a collection)
In Sonos API documentation it is mentioned that "hasOutOfBandMetadata" is deprecated and it is recommended that metadata be embedded inline with the content. However due to some limitations it can't be achieved in our service thus I have to go with the old way itself (whatsoever it is).
I suppose, ideally "getStreamingMetadata" should be called after setting "hasOutOfBandMetadata" to true but it's not happening.
Secondly, for testing purposes I set "secondsRemaining" and "secondsToNextShow" for different values to find out that "description" is also being displayed for those different time intervals (if I set secondsRemaining/secondsToNextShow to 20 then description is displayed for 20 seconds, if set to 200 then for 200 seconds and likewise). After the time lapses, information inside "description" disappears. So I guess there must be some call going to refresh metadata after the time lapses but couldn't figure out which call.
Kindly explain what is the proper way to get metadata for a continuous radio stream. On TuneIn radio you can find Radio Paradise for which metadata is getting updated as track changes. Even if they use metadata inline with their content there must be some way to achieve this.

Can you please post the calls and the the response that you are sending? This would help with troubleshooting this issue. Also what mimeType are you trying to use?
At this time the only full supported method for getting metadata for a continuous radio stream on Sonos that will be guaranteed to work in future releases is to embed metadata in line.

Related

REST API signature guidance

Seeking guidance on REST API Signature for an API.
To handle logistics, we want to support shipping label generation for courier packages.
Which of these would be a more RESTFul way to model these APIs.
Generate Label API : POST /package/{package-id}/label.
Regenerate Label API : POST /package/{package-id}/label/regenerate.
vs
Generate Label API : POST /package/{package-id}/label?operation=generate.
Regenerate Label API : POST /package/{package-id}/label?operation=regenerate.
Regenerate API ends up creating a new Label for the package, based on updated shipping dates, etc passed as part of request payload.
Just use:
POST /package/{package-id}/label
PUT/PATCH /package/{package-id}/label
https://restfulapi.net/http-methods/
If the /package/{package-id}/label is a 'label resource' that you're creating, then the appropriate method is probably PUT here.
But 'regenerating' is a bit hard to explain here. Could you just fetch the label over and over again by doing a GET request on /package/{package-id}/label.
If 'creating a label' or 'regenerating a label' doesn't have side-effects (such as a physical printer printing a label), then a GET might work best.
If 'creating a label' or 'regenerating a label' is not really returning a label but causing some external effect in a different system, then it feels better for this to be more like the RPC call you mentioned.
POST /package/{package-id}/label
Then my question is, why is there a difference between 'generating' and 'regenerating'. It sounds like you're just doing the same thing twice. Do you really need 2 endpoints? Can't the system figure out if a label was created before for the {package-id}?
If the system doesn't know the label is generated vs regenerated, and only the client can know I would be inclined to use the same endpoint and add some flag to the request body instead of having 2 different URLS.

Audiobook chapters that don't start at beginning of file

We've implemented a SMAPI service and are attempting to serve up an audiobook. We can select the audiobook and start playback, but we run into issues when we want to move between chapters because our audio files are not split by chapter. Each audiobook is divided into roughly equal-length parts, and we have information on which part and how far into the part each chapter starts.
So we've run into an issue where our getMetadata response is giving back the chapters of the audiobook because that's how we'd like a user to be able to navigate the book, but our getMediaURI responses for each chapter are giving back URLs for the parts the audio files are divided into, and we seem to be unable to start at a specific position in those files.
Our first attempt to resolve the issue was to include positionInformation in our getMediaURI response. That would still leave us with an issue of ending a chapter at the appropriate place, but might allow us to start at the appropriate place. But according to the Sonos docs, you're not meant to include position information for individual audiobook chapters, and it seems to be ignored.
Our second thought, and possibly a better solution, was to use the httpHeaders section of the getMediaURI response to set a Range header for only the section of the file that corresponds to the chapter. But Sonos appears to have issues with us setting a Range header, and seems to either ignore our header or break when we try to play a chapter. We assume this is because Sonos is trying to set its own Range headers.
Our current thought is that we might be able to pass the media URLs through some sort of proxy, adjusting the Sonos Range header by adding an offset to the start and end values based on where the chapter starts in the audio file.
So right now we return <fileUrl> from getMediaURI and Sonos sends a request like this:
<fileUrl>
Range: bytes=100-200
Instead we would return <proxyUrl>?url=<urlEncodedFileUrl>&offset=3000 from getMediaURI. Sonos would send something like this:
<proxyUrl>?url=<htmlEncodedFileUrl>&offset=3000
Range: bytes=100-200
And the proxy would redirect to something like this:
<fileUrl>
Range: bytes=3100-3200
Has anyone else dealt with audio files that don't match up one-to-one with their chapters? How did you deal with it?
The simple answer is that Sonos players respect the duration of the file, not the duration expressed in the metadata. You can't get around this with positionInformation or Cloud Queues.
However, the note that you shouldn't use positonInformation for chapters in an audiobook seems incorrect, so I removed it. The Saving and Resuming documentation states that you should include it if a user is resuming listening. You could use this to start playback at a specific position in the audio file. Did you receive an error when you attempted to do this?
Note that you would not be able to stop playback within the file (for example, if a chapter ended before the file ended). The player would play the entire file before stopping. The metadata would also not change until the end of the file. So, for example, if the metadata for the file is "Chapter 2" and chapter 2 ends before the end of the file, the Sonos app would still display "Chapter 2" until the end of the file.
Also note that the reporting APIs have been deprecated. See Add Reporting for the new reporting endpoint that your service should host.

Asynchronous Pluggable Protocol for CID: (email), how to handle duplicate URLs

This is somewhat a duplicate of this question, but that question has no (valid) answer and is 1.5 years old so asking my own with hopes people have more info now.
If you are using multiple instances of a WebBrowser control, MSHTML, IHTMLDocument, or whatever... from inside the APP instance, mostly IInternetProtocol::Start, is there a way to know which instance is loading the resource? Or is there a way to use a different APP for each instance of the control, maybe by providing one via IDocHostUIHandler or ICustomDoc or otherwise? I'm currently using IInternetSession::RegisterNameSpace to make it process wide.
Optional reading below, don't feel you need to read it unless above isn't clear.
I'm working on a legacy (Win32 C++) email client that uses the MS ActiveX WebBrowser control (MSHTML or other names it goes by) to display HTML emails. It was saving everything to temp files, updating the cid: URLs, and then having the control load that. Now I want to do it the correct way, using APP. I've got it all working with some test code that just uses static variables/globals and loads one email.
My problem now is, the app might have several instances of the control all loading different emails (and other stuff) at the same time... not really multiple threads so much, just the asynchronous nature of the control. I can give each instance of the control a unique URL to load the email, say, cid:email-GUID, and then in my APP code I can use that URL to know which email to load. However, when it comes to loading any content inside the email, like attached images using src="cid:", those will not always be unique so I will not always know which image it is, for which email. I'd like to avoid having to modify the URLs of the HTML before displaying it (I'm doing that now for the temp file thing, but want to do it a better way).
IInternetBindInfo::GetBindString can return the referrer, BINDSTRING_XDR_ORIGIN, or the root URL, BINDSTRING_ROOTDOC_URL, but those require newer versions of IE and my legacy app must support older XP installs that might even have IE6 or IE7, so I'd rather not use these.
Tagged as TWebBrowser because that is actually what I'm using (Borland Builder 6 C++), but don't need answers specific to that platform.
As the Asynchronous Pluggable Protocol Handler us very low level, you cannot attach handlers individually to different rendering controls.
Here is a way to get the referrer:
Obtain BINDSTRING_HEADERS
Extract the referrer by parsing the line Referer: http://....
See also How can I add an extra http header using IHTTPNegotiate?
Here is another crazy way:
Create another Asynchronous Pluggable Protocol Handler by calling RegisterMimeFilter.
Monitor text/plain and text/html
Scan the incoming email source (content comes incrementally) and parse store all image links in a dictionary
In NameSpaceHandler you can use this dictionary to find the reference of any image resources.

Worklight - Updatable static content

I have this requirement : My WL application have a set of static pages that might be updated any time. Originally the source of all static content is a desktop page that will be transformed by xsl to a mobile friendly content. The problem that I don't want to do that on each request (HA requirement).
I want to get some inspiration on how to architect that without using direct update mechanism (don't want the end user to get notified of these updates).
I should note that pages will change rarely every few month maybe.
I'm thinking about 2 ways of doing that :
1- Making the transformation on adapter side and rely on WL caching so that transformation is not made each time (does that exist ?). But how the adapter will get notified of page change and flush the cache ? Should I program some advanced java based adapter ? (Storing in the cache and having a kind of a job that scans every day for content changes ?)
2- Doing it mobile side but I don't know how to get notified of changes !
Is your only problem with Worklight's Direct Update that the user is being notified and is required to explicitly approve the transfer?
In this case why not use the option of Silent Direct Update?
The property you're looking for is updateSliently set to true in initOptions.js.
For this to work it is required, obviously, that connectOnStartup will be set to true as well.
perhaps what is doable is to use an adapter to fetch the HTML (or whatever it is) and save it to the device's local storage and then have the app display this content, this way you do not alter the app's web resources and not trigger Direct Update.

How can I pass data to the success callback of an ExtJS-based AJAX file upload?

So, I've read a lot about using ExtJS's fileuploadfield to submit a form via an IFRAME. I understand that I'm supposed to reply with a JSON object indicating success or failure; fine. What I want to know is, how can I get more information back to the calling code? I don't want to simple send a file and say "yup, that worked fine" -- I want to submit a document, act on it, and return a result.
Say I have the user upload an XML document -- I might want to do a lookup or conversion based on it and update the contents of a form on my page accordingly. Is this even possible? I'd strongly prefer to avoid involving Flash or embedded applets if at all possible. If need be, I could even restrict this behavior to HTML5-compliant browsers...
I honestly thought I wasn't seeing the response I sent, but it was a server-side error. My success callback is now firing, with the full text of my server's response available as f.responseText (where f is the first argument to the success callback). My mistake!