- no need to leave a Control Point running for playlist track advance to continue as the playlist resides on the renderer
- ability to have multiple CP connected to the same renderer, showing the same playing state and playlist, without chaos happening for control
I have said it a few times before, but people don't seem to realise that most, (if not all), of this is already possible within the existing plain UPnP; (so I will say it again):
If the CP sends a .m3u or .pls playlist (instead of a music track) to the renderer via SetAvTransportUri, and the renderer loads the playlist, then the CP can safely go offline. In such case, the AVtransportUri represents the Uri of the playlist, and CurrentTrackUri represents the Uri of the current playing track within that playlist.
Also it is entirely possible for multiple CPs to follow the status of the same renderer. They can all subscribe to be sent state change event messages. And they can all independently call GetTransportState, GetMediaInfo, GetPositionInfo, GetVolume, GetMute etc. which provide full information about the player's state and the current playing track. None of these actions in anyway affect the renderer's state so they can all be called multi- threaded and in parallel.
You might complain that when playing a .m3u or .pls playlist, GetMediaInfo will return AVtransportUri (the URI of of the playlist) but not the actual playlist; so if the playlist had been stored on a CP, and the CP subsequently goes offline, then the other CPs can no longer retrieve the playlist and would only be able to see the current playing track data. Probably this is not a show stopper. But in any case one can avoid that specific issue, by making sure that the playlist is stored elsewhere (say) on the the same ContentDirectory server where the actual music comes from (because obviously the ContentDirectory server must stay online anyway). You need to remember that the UPnP ContentDirectory is NOT a read only service; in fact it has several write actions that allow a CP to add or delete playlists or music tracks, to/from the ContentDirectory. So in this way, a CP can create a .m3u or .pls playlist, upload it to the ContentDirectory service, send the respective URI to the renderer via SetAvTransportUri, and then it can happily go offline. In this case the renderer and all other CPs can continue to see the playlist even if the original CP goes offline. Edit: an alternative, and much more friendly, solution is for the renderer to cache the .m3u or .pls on itself. The renderer then returns in GetMediaInfo the Uri of the cached version of the playlist, so all other CPS could retrieve it at any time.
Please also bear in mind that when a renderer is playing a .m3u or .pls playlist, it has all the information that it needs in order to do gapless playback. The renderer can prefetch the next track whenever it needs to. In such a case the SetNextAvTransportUri action actually becomes redundant.
When running multiple CPs in parallel, the only issue is when CPs send conflicting actions that change the player's state (Play, Stop, Next, Prev, Seek, SetVolume, SetMute, SetAvTransportUri and SetNextAvTransportUri). In all these cases, the basic principle is that the last issued command will win. This is exactly the same as if you would have two people on the sofa with two remotes both trying to control the same Tv. This is not a technology issue; it is a human issue that no technical standard can aspire to resolve.
PS You may wonder, in the case where the CP sends a .m3u or .pls playlist Uri via SetAvTransportUri to the renderer, how it passes in the metadata for all the tracks in the the playlist. The specs are not clear on this, but it seems implicit that the AvTransportUriMetaData can contain more than one musicTrack item. Hence there would be a musicTrack item containing metadata corresponding to each track in the playlist. The renderer would determine which metadata applies to which track, either by using the musicTrack items sequentially, or perhaps more intelligently, by choosing the musicTrack item whose res element has the same Uri as the current playing track (CurrentTrackUri).