Thursday 7 August 2014

Sonos UPnP Development - Controlling Playback

In previous posts I have introduced the important concepts of UPnP Services, and that they offer Events and Actions. We have seen how it is possible to subscribe to an Event in order to be notified of when something interesting happens.

Now we are going to look at how we can use Actions to actually control something. This is a very simplistic example, but should illustrate the basic concepts.

The following code, when run, will do a "Pause All" of the renderer devices it finds on your network. This code is based mostly on the version from my previous post UPnP Discovery with Sonos, event driven:


The main changes to this version are that that we no longer print anything out. The device_info method which was used to print out device details in v3 has been replaced by a new function pause_device which pauses the device instead (lines 20-35). The key function call is on lines 32-34. This requires a little explanation.

The call takes multiple parameters including the service being addressed (in our case, the AVTransport service which we have previously obtained a reference to, the action requested, which "Pause", a flag to pass back en error and then a bunch of parameters. The parameters depending on the action being triggered, and this is within the device description document. In the case of AVTransport it's also within the UPnP specifications at upnp.org.

The following image shows how this looks when using a development tool such as Device Spy. The left column shows the Actions supported by AVTransport. I have selected "Pause" and the right column shows me the parameter this Action requires. It needs a single parameter called "InstanceID" of type "ui4".
Using Device Spy developer tool to examine the AVTransport interface
So in our call on line 32 (and according the the GUPnP documentation for "gupnp_service_proxy_send_action") we need to specify this parameter a as a "tuple" comprising the parameter name, the parameter type and the parameter value. In this case we want the first (and only) AVTransport control. The count starts at 0. We finish wth a "NULL" to indicate there are no more parameters.

This call is a simple one with no return parameters. If we had return parameters to deal with we would need to handle this differently.

Also, the function returns an error if the action failed. In our case it will fail if the "Pause" cannot be carried out. One reason for this would be that the devices is already paused. In this case we don't care about this so we ignore it. A more complete version might keep track of the transport state of the player, and only send a "Pause" action to those which were not already paused.

When run, this program does not give any output. It simply pauses every discovered player on the network. Clearly this could be used to connect to a home automation system, such that when the phone rang or the doorbell was pressed, all of the zones were paused.

No comments:

Post a Comment