From OpenHome

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
-
= Architectural Overview =
+
= Overview =
-
The Playlist service provides the means for controlling a Playlist source. If a device's [[Developer:ProductService|Product service]] reports a source of type 'Playlist', then that device is guaranteed to bear the Playlist service.
+
The Playlist service provides access to a list of tracks, which can be played in sequence, starting at any point. ‘Shuffle’ and ‘Repeat’ modes also exist, allowing track order to be randomised and playback to loop.
-
 
+
<br>If a device's [[Developer:ProductService|Product]] service reports a source of type 'Playlist', then that device is guaranteed to bear the Playlist service.
-
The Playlist service provides access to a list of tracks, which can be played starting at any point. Unless repeat mode has been engaged, the playlist will play to the end. Shuffle mode causes playback to skip randomly through the playlist. It is possible for Shuffle and Repeat modes to be engaged simultaneously.
+
-
 
+
-
Using the Playlist service you can read, insert, and delete entries in the playlist. Each entry in the playlist is given unique id.  This unique id is completely unrelated to the play order of the playlist.
+
-
 
+
-
To insert, provide the id you wish to insert 'after' and the associated uri and metadata. The track is inserted into the correct position and the id of the new track is returned.  To insert in the first position in the playlist, insert after the special id of 0.
+
-
 
+
-
There are two read actions. One to read a single entry and the other to read a list of entries.
+
-
 
+
-
In the first, the uri and metadata of the requested id are returned. This operation can fail if the requested id does not exist in the playlist.
+
-
 
+
-
In the second, ReadList, a list of space separated decimal id's is provided and information concerning each of these tracks is returned in xml. ReadList does not fail. Requests for ids that are not in the playlist are silently ignored.
+
-
 
+
-
There are two variants of delete allowing the deletion of a single track or the deletion of the entire playlist. The former requires the id of the entry to delete. The latter takes no parameters. Both variants always succeed.
+
 +
= State Variables =
 +
== TransportState ==
 +
One of <tt>Stopped</tt>, <tt>Playing</tt>, <tt>Paused</tt> or <tt>Buffering</tt>.
 +
== Repeat ==
 +
By default a playlist plays each track in sequence then pauses after playing the final track.  Setting the <tt>Repeat</tt> property changes this behaviour to loop from the last track back to the first, playing it immediately.  The <tt>Next</tt> and <tt>Previous</tt> actions also vary their behaviour according to this property at the ends of a playlist.
 +
<br>By default, <tt>Repeat</tt> is off.
 +
== Shuffle ==
 +
Tracks are played in random order if the <tt>Shuffle</tt> property is enabled.  As with normal playback, each track is played once then the playlist stops.  If <tt>Shuffle</tt> is enabled mid-way through a playlist, each track in the list is shuffled, including any that have just been played.
 +
<br>When combined with <tt>Repeat</tt>, each track is played once before any track is played for a second time.
 +
<br>By default, <tt>Shuffle</tt> is off.
 +
== Id ==
 +
The id of the current track (the track currently playing or that would be played if the <tt>Play</tt> action was invoked).  Or <tt>0</tt> if the playlist is empty.
== IdArray ==
== IdArray ==
-
 
+
An [[Developer:IdArray|IdArray]] containing the ids of the tracks currently in the playlist.  Contains <tt>[0.. TracksMax]</tt> elements.
-
The Playlist service has a state variable called IdArray. This IdArray is a [http://en.wikipedia.org/wiki/Base64 base64] encoded array of 32 bit, big endian unsigned integers. Each Id represents a track in the playlist. An empty IdArray indicates an empty playlist.
+
== TracksMax ==
-
 
+
The maximum number of tracks a playlist can contain.  Set on startup and invariant thereafter.
-
For example the IdArray of:
+
== ProtocolInfo ==
-
 
+
Audio formats and networking protocols supported by the device. Will be the same as reported by [[Developer:RadioService|Radio]] and <tt>AVTransport</tt> if these services are present. Set on startup and invariant thereafter.
-
<pre>0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x14 0x00 0x00 0x00 0x13</pre>
+
-
 
+
-
indicates a playlist of 3 tracks with the id's of 2, 20, and 19 in that order.
+
-
 
+
-
Control point authors are interested in both:
+
-
 
+
-
* the order of tracks in the playlist, and
+
-
* the metadata of those tracks
+
-
 
+
-
Whether you acquire the IdArray via [[Developer:PlaylistService#Events|events]] or [[Developer:PlaylistService#Polling|polling]], you immediately know the order of the ids in the playlist.  What you don't necessarily know is the metadata for those ids.
+
-
 
+
-
As the metadata for a large playlist can easily be several megabytes of xml, blindly fetching all the metadata every time the playlist changes is inefficient and will give a poor user experience. In order to quickly display playlist updates and ensure interoperability with other control points on the network, it is strongly recommended that you maintain the following two data structures:
+
-
 
+
-
* A copy of the latest IdArray
+
-
* A cache mapping id's to their associated metadata.
+
-
 
+
-
With this decoupled approach, you only need to fetch the metadata for the ids added to the playlist.  Changes to the order of ids in the playlist require no action.
+
-
 
+
-
As a further enhancement, when an insert completes successfully, you know both the metadata (as you supplied it), and the new id (returned by the DS on completion of the insert action).  This information can be directly inserted into the cache, saving subsequent unnecessary retrieval.
+
-
 
+
-
== Events ==
+
-
 
+
-
A short while (approx 300ms) after any change to the playlist, the DS will event all subscribers the current IdArray. The eventing of this state variable is moderated to prevent excessive updates.
+
-
 
+
-
== Polling ==
+
-
 
+
-
For control points that can't subscribe to events, two additional actions are provided. The first, IdArray, reads the id array directly. This action also returns an IdArrayToken, which should be saved and periodically passed to a second action, IdArrayChanged, which reports whether or not your copy of the IdArray is out of date. If it is, calling IdArray again will ensure you have an up to date version.
+
= Actions =
= Actions =
-
 
+
== Play ==
-
== IdArray ==
+
If <tt>TransportState</tt> is <tt>Stopped</tt> or <tt>Paused</tt>, start playing the track indicated by the <tt>Id</tt> state variable.
-
Report the current id array.
+
<br>If <tt>TransportState</tt> is <tt>Playing</tt> or <tt>Buffering</tt>, re-start playing the current track from the beginning.
-
 
+
<br>If the Playlist source is not active, deactivates the current source and activates Playlist.
-
The IdArray is an ordered array of ids that represent each track in the playlist.  
+
<br>Disables <tt>Standby</tt> in the [[Developer:ProductService|Product]] service if that was enabled (and if the product is controllable over the network in this mode).
-
 
+
== Pause ==
-
This action also reports a Token, which can be used to quickly detect if the id array has changed since it was last read (see IdArrayChanged).
+
Pause the current track.  The <tt>TransportState</tt> will change to <tt>Paused</tt>, possibly after a short delay allowing the volume to be ramped down.
-
 
+
<br>This will be converted to <tt>Stop</tt> if the track cannot be paused e.g. for internet radio.
-
== IdArrayChanged ==
+
== Stop ==
-
Check to see if the id array has changed since gathering the specified Token.
+
Stop the current track and move the current position to the start of this track.  The <tt>TransportState</tt> will change to <tt>Stopped</tt>, possibly after a short delay allowing the volume to be ramped down.
-
This Token must have been previously collected from the IdArray action.
+
== Next ==
-
 
+
Halt playback of the current track and start playing the next item in the playlist.
-
This mechanism is provided specifically for clients unable to partake in UPnP eventing.
+
<br>If the last track in a playlist is being played and <tt>Repeat</tt> is off, the playlist will pause.  The first track in the playlist will be played from the beginning if the <tt>Play</tt> action is invoked.
-
 
+
<br>If the last track in a playlist is being played and <tt>Repeat</tt> is on, the first last track in the playlist is played.
-
== TracksMax ==
+
== Previous ==
-
Report the maximum number of tracks in the id array. This remains constant while a particular OpenHome device remains registerted on the network, but may vary between different models of OpenHome device from different manufacturers.
+
Halt playback of the current track and start playing the previous item in the playlist.
-
 
+
<br>If the first track in a playlist is being played and <tt>Repeat</tt> is off, the playlist will pause.  The first track will be played from the beginning if the <tt>Play</tt> action is invoked.
-
==Id==
+
<br>If the first track in a playlist is being played and <tt>Repeat</tt> is on, the last track in the playlist is played.
-
Report the Id of the current track. If the reported id is zero, the playlist is empty.
+
<br>Behaviour when <tt>Shuffle</tt> is enabled is implementation defined.
-
 
+
== SetRepeat ==
-
==ProtocolInfo==
+
Enable or disable repeat mode.
-
Report the Playlist source protocol info.
+
== Repeat ==
-
 
+
Return the value of the <tt>Repeat</tt> state variable.
-
==Read==
+
== SetShuffle ==
-
Given a track Id, report its associated Uri and Metadata.
+
Enable or disable shuffle mode.
-
 
+
== Shuffle ==
-
==ReadList==
+
Return the value of the <tt>Shuffle</tt> state variable.
-
Given a space separated list of track Id's, report their associated Uri and Metadata in the following xml form:
+
== SeekSecondAbsolute ==
-
 
+
Seek to an absolute second within the current track. This is only available if the current track has a finite length.
 +
== SeekSecondRelative ==
 +
Seek to a relative second within the current track. This is only available if the current track has a finite length.
 +
== SeekId ==
 +
Halt playback of the current track and switch to the track with the specified id.
 +
<br>Should return a <tt>800</tt> fault code if the id is invalid.
 +
== SeekIndex ==
 +
Halt playback of the current track and switch to the track with the specified index.
 +
<br>Use of this function is discouraged as it results in an unpredictable track being played in the presence of multiple control points.  Try to use <tt>SeekId</tt> in preference to this.
 +
<br>May return a <tt>800</tt> fault code if the index is beyond the end of the playlist.
 +
== TransportState ==
 +
Return the value of the <tt>TransportState</tt> state variable.
 +
== Id ==
 +
Return the value of the <tt>Id</tt> state variable.
 +
== Read ==
 +
Report the uri and metadata for a given track id.
 +
<br>Returns a <tt>800</tt> fault code if the given id is not in the playlist.
 +
== ReadList ==
 +
Given a space separated list of track Id's, report their associated uri and metadata in the following xml form:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
-
 
   <TrackList>
   <TrackList>
     <Entry>
     <Entry>
Line 90: Line 79:
     </Entry>
     </Entry>
   </TrackList>
   </TrackList>
-
 
</syntaxhighlight>
</syntaxhighlight>
-
 
+
Any ids not in the playlist are ignored.
-
== TransportState ==
+
== Insert ==
-
 
+
Adds the given uri and metadata as a new track to the playlist.
-
Report the current transport state, which can be: 'Playing', 'Paused', 'Stopped', or 'Buffering'.
+
<br>Set the <tt>AfterId</tt> argument to <tt>0</tt> to insert a track at the start of the playlist.
-
 
+
<br>Reports a <tt>800</tt> fault code if <tt>AfterId</tt> is not <tt>0</tt> and doesn’t appear in the playlist.
-
== Play ==
+
<br>Reports a <tt>801</tt> fault code if the playlist is full (i.e. already contains <tt>TracksMax</tt> tracks).
-
Begin playback from the current position.
+
-
 
+
-
== Pause ==
+
-
Pause the current track. This will be converted to Stop if the track cannot be paused e.g. internet radio.
+
-
 
+
-
== Stop ==
+
-
Stop playback and move the current position to the start of the current track.
+
-
 
+
-
== Next ==
+
-
Move the current position to the start of the next track in the playlist.
+
-
 
+
-
== Previous ==
+
-
Move the current position to the start of the next track in the playlist.
+
-
 
+
-
== SeekId ==
+
-
Move the current position to the start of the track represented by the given Id.
+
-
 
+
-
== SeekIndex ==
+
-
Move the current position to the start of the track with the given Index into the playlist.
+
-
 
+
-
This action should only be used by primitive control points that do not have a rich way of representing the playlist to the user.
+
-
 
+
-
== SeekSecondAbsolute ==
+
-
Seek to an absolute second within the current track. This is only available if the current track has a finite length.
+
-
 
+
-
== SeekSecondRelative ==
+
-
Seek to a relative second within the current track.  This is only available if the current track has a finite length.
+
-
 
+
-
== Repeat ==
+
-
Report the state of repeat mode.
+
-
 
+
-
== SetRepeat ==
+
-
Set the state of repeat mode.
+
-
 
+
-
== Shuffle ==
+
-
Report the state of shuffle mode.
+
-
 
+
-
== SetShuffle ==
+
-
Set the state of shuffle mode.
+
-
 
+
== DeleteId ==
== DeleteId ==
-
Delete from the playlist the track with the speciofied Id.
+
Delete the track with a given id from the playlist.
-
 
+
<br>If the id to be deleted is currently playing, the next track becomes current.
 +
<br>Returns a <tt>800</tt> fault code if the given id is not in the playlist.
== DeleteAll ==
== DeleteAll ==
-
Clear the playlist.
+
Delete all tracks from the playlist.
 +
== TracksMax ==
 +
Return the value of the <tt>TracksMax</tt> state variable.
 +
== IdArray ==
 +
Return the value of the <tt>IdArray</tt> state variable.  Also returns a token which can be used with the IdArrayChanged action.
 +
== IdArrayChanged ==
 +
Check to see if the id array has changed since gathering the specified <tt>Token</tt>. This <tt>Token</tt> must have been previously collected from the <tt>IdArray</tt> action.
 +
<br>This mechanism is provided specifically for clients unable to partake in UPnP eventing.
 +
== ProtocolInfo ==
 +
Return the value of the <tt>ProtocolInfo</tt> state variable.
= Technical Details =
= Technical Details =
Line 151: Line 109:
</code>
</code>
-
== Playlist Service Description (XML) ==
+
== Service Description (XML) ==
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">

Revision as of 10:40, 2 August 2013

Contents

Overview

The Playlist service provides access to a list of tracks, which can be played in sequence, starting at any point. ‘Shuffle’ and ‘Repeat’ modes also exist, allowing track order to be randomised and playback to loop.
If a device's Product service reports a source of type 'Playlist', then that device is guaranteed to bear the Playlist service.

State Variables

TransportState

One of Stopped, Playing, Paused or Buffering.

Repeat

By default a playlist plays each track in sequence then pauses after playing the final track. Setting the Repeat property changes this behaviour to loop from the last track back to the first, playing it immediately. The Next and Previous actions also vary their behaviour according to this property at the ends of a playlist.
By default, Repeat is off.

Shuffle

Tracks are played in random order if the Shuffle property is enabled. As with normal playback, each track is played once then the playlist stops. If Shuffle is enabled mid-way through a playlist, each track in the list is shuffled, including any that have just been played.
When combined with Repeat, each track is played once before any track is played for a second time.
By default, Shuffle is off.

Id

The id of the current track (the track currently playing or that would be played if the Play action was invoked). Or 0 if the playlist is empty.

IdArray

An IdArray containing the ids of the tracks currently in the playlist. Contains [0.. TracksMax] elements.

TracksMax

The maximum number of tracks a playlist can contain. Set on startup and invariant thereafter.

ProtocolInfo

Audio formats and networking protocols supported by the device. Will be the same as reported by Radio and AVTransport if these services are present. Set on startup and invariant thereafter.

Actions

Play

If TransportState is Stopped or Paused, start playing the track indicated by the Id state variable.
If TransportState is Playing or Buffering, re-start playing the current track from the beginning.
If the Playlist source is not active, deactivates the current source and activates Playlist.
Disables Standby in the Product service if that was enabled (and if the product is controllable over the network in this mode).

Pause

Pause the current track. The TransportState will change to Paused, possibly after a short delay allowing the volume to be ramped down.
This will be converted to Stop if the track cannot be paused e.g. for internet radio.

Stop

Stop the current track and move the current position to the start of this track. The TransportState will change to Stopped, possibly after a short delay allowing the volume to be ramped down.

Next

Halt playback of the current track and start playing the next item in the playlist.
If the last track in a playlist is being played and Repeat is off, the playlist will pause. The first track in the playlist will be played from the beginning if the Play action is invoked.
If the last track in a playlist is being played and Repeat is on, the first last track in the playlist is played.

Previous

Halt playback of the current track and start playing the previous item in the playlist.
If the first track in a playlist is being played and Repeat is off, the playlist will pause. The first track will be played from the beginning if the Play action is invoked.
If the first track in a playlist is being played and Repeat is on, the last track in the playlist is played.
Behaviour when Shuffle is enabled is implementation defined.

SetRepeat

Enable or disable repeat mode.

Repeat

Return the value of the Repeat state variable.

SetShuffle

Enable or disable shuffle mode.

Shuffle

Return the value of the Shuffle state variable.

SeekSecondAbsolute

Seek to an absolute second within the current track. This is only available if the current track has a finite length.

SeekSecondRelative

Seek to a relative second within the current track. This is only available if the current track has a finite length.

SeekId

Halt playback of the current track and switch to the track with the specified id.
Should return a 800 fault code if the id is invalid.

SeekIndex

Halt playback of the current track and switch to the track with the specified index.
Use of this function is discouraged as it results in an unpredictable track being played in the presence of multiple control points. Try to use SeekId in preference to this.
May return a 800 fault code if the index is beyond the end of the playlist.

TransportState

Return the value of the TransportState state variable.

Id

Return the value of the Id state variable.

Read

Report the uri and metadata for a given track id.
Returns a 800 fault code if the given id is not in the playlist.

ReadList

Given a space separated list of track Id's, report their associated uri and metadata in the following xml form:

  <TrackList>
    <Entry>
      <Id></Id>
      <Uri></Uri>
      <Metadata></Metadata>
    </Entry>
  </TrackList>

Any ids not in the playlist are ignored.

Insert

Adds the given uri and metadata as a new track to the playlist.
Set the AfterId argument to 0 to insert a track at the start of the playlist.
Reports a 800 fault code if AfterId is not 0 and doesn’t appear in the playlist.
Reports a 801 fault code if the playlist is full (i.e. already contains TracksMax tracks).

DeleteId

Delete the track with a given id from the playlist.
If the id to be deleted is currently playing, the next track becomes current.
Returns a 800 fault code if the given id is not in the playlist.

DeleteAll

Delete all tracks from the playlist.

TracksMax

Return the value of the TracksMax state variable.

IdArray

Return the value of the IdArray state variable. Also returns a token which can be used with the IdArrayChanged action.

IdArrayChanged

Check to see if the id array has changed since gathering the specified Token. This Token must have been previously collected from the IdArray action.
This mechanism is provided specifically for clients unable to partake in UPnP eventing.

ProtocolInfo

Return the value of the ProtocolInfo state variable.

Technical Details

   Domain  : av.openhome.org
   Name    : Playlist
   Version : 1

Service Description (XML)

<?xml version="1.0" encoding="utf-8"?>
 
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
 
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
 
    <actionList>
        <action>
            <name>Play</name>
        </action>
        <action>
            <name>Pause</name>
        </action>
        <action>
            <name>Stop</name>
        </action>
        <action>
            <name>Next</name>
        </action>
        <action>
            <name>Previous</name>
        </action>
        <action>
            <name>SetRepeat</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Repeat</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>Repeat</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>Repeat</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SetShuffle</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Shuffle</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>Shuffle</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>Shuffle</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SeekSecondAbsolute</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Absolute</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SeekSecondRelative</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Relative</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SeekId</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Id</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>SeekIndex</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Index</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>TransportState</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>TransportState</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>Id</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>Id</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>Read</name>
            <argumentList>
                <argument>
                    <name>Id</name>
                    <direction>in</direction>
                    <relatedStateVariable>Id</relatedStateVariable>
                </argument>
                <argument>
                    <name>Uri</name>
                    <direction>out</direction>
                    <relatedStateVariable>Uri</relatedStateVariable>
                </argument>
                <argument>
                    <name>Metadata</name>
                    <direction>out</direction>
                    <relatedStateVariable>Metadata</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>ReadList</name>
            <argumentList>
                <argument>
                    <name>IdList</name>
                    <direction>in</direction>
                    <relatedStateVariable>IdList</relatedStateVariable>
                </argument>
                <argument>
                    <name>TrackList</name>
                    <direction>out</direction>
                    <relatedStateVariable>TrackList</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>Insert</name>
            <argumentList>
                <argument>
                    <name>AfterId</name>
                    <direction>in</direction>
                    <relatedStateVariable>Id</relatedStateVariable>
                </argument>
                <argument>
                    <name>Uri</name>
                    <direction>in</direction>
                    <relatedStateVariable>Uri</relatedStateVariable>
                </argument>
                <argument>
                    <name>Metadata</name>
                    <direction>in</direction>
                    <relatedStateVariable>Metadata</relatedStateVariable>
                </argument>
                <argument>
                    <name>NewId</name>
                    <direction>out</direction>
                    <relatedStateVariable>Id</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>DeleteId</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>in</direction>
                    <relatedStateVariable>Id</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>DeleteAll</name>
        </action>
        <action>
            <name>TracksMax</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>TracksMax</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>IdArray</name>
            <argumentList>
                <argument>
                    <name>Token</name>
                    <direction>out</direction>
                    <relatedStateVariable>IdArrayToken</relatedStateVariable>
                </argument>
                <argument>
                    <name>Array</name>
                    <direction>out</direction>
                    <relatedStateVariable>IdArray</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>IdArrayChanged</name>
            <argumentList>
                <argument>
                    <name>Token</name>
                    <direction>in</direction>
                    <relatedStateVariable>IdArrayToken</relatedStateVariable>
                </argument>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>IdArrayChanged</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>ProtocolInfo</name>
            <argumentList>
                <argument>
                    <name>Value</name>
                    <direction>out</direction>
                    <relatedStateVariable>ProtocolInfo</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
    </actionList>
 
    <serviceStateTable>
        <stateVariable sendEvents="yes">
            <name>TransportState</name>
            <dataType>string</dataType>
            <allowedValueList>
                <allowedValue>Playing</allowedValue>
                <allowedValue>Paused</allowedValue>
                <allowedValue>Stopped</allowedValue>
                <allowedValue>Buffering</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>Repeat</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>Shuffle</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>Id</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>IdArray</name>
            <dataType>bin.base64</dataType>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>TracksMax</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>ProtocolInfo</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Index</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Relative</name>
            <dataType>i4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Absolute</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>IdList</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>TrackList</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Uri</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Metadata</name>
            <dataType>string</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>IdArrayToken</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>IdArrayChanged</name>
            <dataType>boolean</dataType>
        </stateVariable>
    </serviceStateTable>
</scpd>