Thursday, 7 August 2014

Sonos UPnP Development - Getting more information from the renderer

This next version is an evolution of the version in my previous post Sonos UPnP Development - Accessing the AV Transport service.  It has been extended to display some basic metadata for any tracks that are found.

The main changes from the previous version (UPnPClient4) are:

  1.  A new callback function on_didl_object_available (lines 31-44) which prints out metadata for a track object including the full URL of the album art.
  2. New code in the existing on_last_change callback which creates a parser for the XML track object (lines 86-96)
  3. A change to the service subscription to indicate we want to get the "CurrentTrackMetaData" information (line 69).
  4. I have also added the ability to specify the timeout on the command line (lines 155-158 & line 194). For brevity I haven't done any serious condition/error checking here.
If you run this program with no parameter it will default to run forever. You will need to force close it with CTRL-C. If you specify a parameter in seconds, it will run for that many seconds before exiting.

The way this works is similar to UPnPClient4, on which it is based. However, within the last_changed callback handler (which, as you recall, is called whenever the AVTransport service changes state) we request and process the track metadata.

The track metadata is contained in an XML document which looks like this:

If you uncomment the "g_print" on line 88 it will print out this XML document for you to see (it prints on a single line - I have formatted the above sample to make it easier to read).

Looking through this document you can see it contains quite a lot of information about the currently playing track. This is contained in an XML schema known as "DIDL-LIte" which is a cut-down version of DIDL. In UPnP AV this is used for a lot of things including content directories.

Luckily in our case the gupnp toolkit provides us with some nice capabilities to make it easy to parse this and extract information from it. The way this works is you needs to create a parser (line 58). When the parser is run it scans the DIDL document and signals every time it gets a new sub-object. In our case, the sub-object is a DIDL Item containing the track metadata. We need to create a callback function to handle this (which we have called on_didl_object_available and connect this to the parse before we execute it (line 84). We then run the parser and let it do it's thing.

In the parser callback handler on_didl_object_available (lines 30 -38) we receive the metadata object from the parser as a GUPnPDIDLLiteObject object. We can then use the gupnp convenience functions to extract specific data from this.

If you run this, you should get something similar to:

If you play tracks whilst the program is running, or if the track changes, the new details will print out.

Of particular note is the "Album Art:" information. The metadata returns a partial URL of the Album Art. This URL is relative to the Device URL. To get the full url we have to append the device URL to it (http://<ZP_IP_ADDRESS>:1400). This version of the code does this for us so that the URL output (highlighted above) can be cut and paste into the address bar of a web brower in order to view the album art.  If you are listening to Internet radio you should get the station logo for the station, if there is one.

The change in this updated version is achieved by pushing a pointer to the renderer object into the on_didl_object_available callback so that the callback code can reference it (the change here is made at line 89). Then in on_didl_object_available we dereference the renderer object and use it to look up the base URL (line 39) and then construct a new URL using the device base URL and the album art partial URL (line 40).

Clearly this basic capability could be extended to a number of uses, such as:

  • Keep a GUI client up to date with current playing information
  • Create a logging service to monitor what tracks had been played
  • Create a "most played" or "recently played" playlist from the log
  • Create a screensaver or media centre display based on what a specified zone was playing
  • Look up artist information, artwork, or lyrics on the Internet and display them
  • Push Album Art of currentply playing track to a UPnP TV or picture frame
As well as many more applications of this.

No comments:

Post a Comment