DLNA / UPNP binding

Built and testing… this one will be fun!

It’s almost hop harvest time, so I’ve been distracted with getting everything setup for a fresh brew! I’ve got logging at DEBUG while updating the binding, so hopefully there will be something to find in there.

@5iver I just realized the UP command may not behave correct anymore when the parent is a single container. I will be looking into that.

1 Like

@5iver

I adjusted it and committed. You should use the new version, as I now believe the currentId was not always correct in the previous version.

1 Like

Search is working great! I’m now thinking of a way to script the holiday sounds. They are stored in playlists and when any motion or door sensor changes state, I play a random sound from the shuffled list on the nearest speaker. Everything seems to be in place for it with the binding, except for a way to return just one track from a shuffled playlist… something like a “play first track” functionality. Or maybe a Thing configuration for number of search results returned, but then would it be shuffled?.

In watching UPnP Spy while playing a playlist, I spotted an issue with the playback of the tracks in a playlist. Here is what I’m seeing…

  1. CurrentURI and NextURI are populated and CurrentURI plays,
  2. NextURI moves to CurrentURI and then goes empty, CurrentURI plays
  3. CurrentURI goes empty, then both are populated again, but CurrentURI is the same track as played last

Hopefully, this is what you fixed… trying the new one…

2020-09-06 17:06:40.763 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device Butler Pantry invoke upnp action GetTransportInfo on service AVTransport with inputs {InstanceID=0}
2020-09-06 17:06:40.780 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device Living Room invoke upnp action GetTransportInfo on service AVTransport reply {CurrentSpeed=1, CurrentTransportState=NO_MEDIA_PRESENT, CurrentTransportStatus=OK}
2020-09-06 17:06:40.780 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler] - Upnp device Living Room received variable CurrentSpeed with value 1 from service AVTransport
2020-09-06 17:06:40.780 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler] - Upnp device Living Room received variable CurrentTransportState with value NO_MEDIA_PRESENT from service AVTransport
2020-09-06 17:06:40.780 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler] - Upnp device Living Room received variable CurrentTransportStatus with value OK from service AVTransport

I don’t see any references to NO_MEDIA_PRESENT in the binding. From the AVTransport spec…

image

Looks to me that NO_MEDIA_PRESENT is not handled for AVTransport. IMO, the control Channel should update to PAUSE.

This is a new bug, purely on the renderer thing. I never tested with a renderer that supported next URI, my test renderer didn’t, but put code in there believing that it should fill the new NextURI when the renderer is able to advance by itself.
I will check.
EDIT: I put the developer renderer in a mode supporting SetNextAVTransportURI. I see the binding setting it correctly and the renderer replying with it being set at the right time. There must be a difference in the sequence value and/or sequence of received messages between my and your renderer to explain this. I would need a log of the renderer transitioning between two media entries to analyze further.
I put in some trace logs to analyze why it doesn’t work in your case.

But there is nothing that can be played when you have a NO_MEDIA_PRESENT state. If at all, I should actually put the control to UNDEF, as a play command cannot do anything. There is no known URI to play in the renderer.
I believe it is typically more used to control a player with changeable media (like a CD player). So I am a bit surprised to see it with your renderer, but the impact is still the same. NO_MEDIA_PRESENT = nothing to play. When an URI gets set, I also expect the TransportState to automatically change to STOPPED (possibly with TRANSITIONING in between).

What about a “onlyplayone” switch channel on the renderer? When on, a play command will only play one entry and then stop. You would need another play command before playing the next. Shuffle, repeat etc. should still work, but the playing will not be continuous anymore. I need to think about this, because it may impact quite a bit of the continuous play logic again.
EDIT: I added the channel on the renderer for this and documented it in the README.

Here you go… upnp repeats track.log (277.4 KB). This was initiated from a search from a script (I now have the script logs in with the binding logs).

Agreed

Sounds good! I’m getting two tracks playing though. Maybe related to first issue. Will wait to test again with the next version. It seems the CurrentURI is not being cleared.

After setting currentid to 0, the binding seems to be briowsing on it’s own, which then causes a Search expecting to be in root to fail. Browsing up three times does not have this issue.

2020-09-07 19:29:46.669 [WARN ] [org.openhab.binding.upnpcontrol.test_script] - START: Twonky_Search_Criteria: upnp:class = "object.container.playlistContainer" and dc:title = "HA_Thanksgiving", Twonky_Browse: .., Twonky_ID: 0$1$9$154677
2020-09-07 19:29:46.684 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command 0 for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:currentid on server TwonkyMedia [NAS01]
2020-09-07 19:29:46.684 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Setting currentId to 0
2020-09-07 19:29:46.684 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Browse on service ContentDirectory with inputs {SortCriteria=+dc:title, ObjectID=0, Filter=*, BrowseFlag=BrowseDirectChildren, RequestedCount=0, StartingIndex=0}
2020-09-07 19:29:46.720 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Browse on service ContentDirectory reply {TotalMatches=3, UpdateID=60, NumberReturned=3, Result=<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><container id="0$1" parentID="0" restricted="1" childCount="5" searchable="1" pv:persistentID="music"><dc:title>Music</dc:title><pv:childCountContainer>5</pv:childCountContainer><pv:modificationTime>79979</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$2" parentID="0" restricted="1" childCount="2" searchable="1" pv:persistentID="picture"><dc:title>Photos</dc:title><pv:childCountContainer>2</pv:childCountContainer><pv:modificationTime>2403237</pv:modificationTime><pv:containerContent>object.item.imageItem.photo</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$3" parentID="0" restricted="1" childCount="3" searchable="1" pv:persistentID="video"><dc:title>Videos</dc:title><pv:childCountContainer>3</pv:childCountContainer><pv:modificationTime>2017121042</pv:modificationTime><pv:containerContent>object.item.videoItem.movie</pv:containerContent><upnp:class>object.container</upnp:class></container></DIDL-Lite>}
2020-09-07 19:29:46.721 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 3 from service ContentDirectory
2020-09-07 19:29:46.721 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 60 from service ContentDirectory
2020-09-07 19:29:46.721 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 3 from service ContentDirectory
2020-09-07 19:29:46.721 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable Result with value <DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><container id="0$1" parentID="0" restricted="1" childCount="5" searchable="1" pv:persistentID="music"><dc:title>Music</dc:title><pv:childCountContainer>5</pv:childCountContainer><pv:modificationTime>79979</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$2" parentID="0" restricted="1" childCount="2" searchable="1" pv:persistentID="picture"><dc:title>Photos</dc:title><pv:childCountContainer>2</pv:childCountContainer><pv:modificationTime>2403237</pv:modificationTime><pv:containerContent>object.item.imageItem.photo</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$3" parentID="0" restricted="1" childCount="3" searchable="1" pv:persistentID="video"><dc:title>Videos</dc:title><pv:childCountContainer>3</pv:childCountContainer><pv:modificationTime>2017121042</pv:modificationTime><pv:containerContent>object.item.videoItem.movie</pv:containerContent><upnp:class>object.container</upnp:class></container></DIDL-Lite> from service ContentDirectory
2020-09-07 19:29:46.722 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-07 19:29:46.722 [TRACE] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 0$1 added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:29:46.722 [TRACE] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 0$2 added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:29:46.722 [TRACE] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 0$3 added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:29:46.722 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 3 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:29:46.722 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-07 19:29:46.722 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list [Music, Photos, Videos]
2020-09-07 19:29:46.722 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-07 19:29:46.722 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable
2020-09-07 19:29:47.670 [WARN ] [org.openhab.binding.upnpcontrol.test_script] - BEFORE SEARCH: Twonky_Search_Criteria: upnp:class = "object.container.playlistContainer" and dc:title = "HA_Thanksgiving", Twonky_Browse: .., Twonky_ID: 0
2020-09-07 19:29:47.690 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command upnp:class = "object.container.playlistContainer" and dc:title = "HA_Thanksgiving" for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:search on server TwonkyMedia [NAS01]
2020-09-07 19:29:47.690 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Navigating to node 0$1$9$154677 on server TwonkyMedia [NAS01]
2020-09-07 19:29:47.690 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Search container 0$1$9$154677 for upnp:class = "object.container.playlistContainer" and dc:title = "HA_Thanksgiving"
2020-09-07 19:29:47.691 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Search on service ContentDirectory with inputs {SortCriteria=+dc:title, ContainerID=0$1$9$154677, Filter=*, RequestedCount=0, SearchCriteria=upnp:class = "object.container.playlistContainer" and dc:title = "HA_Thanksgiving", StartingIndex=0}
2020-09-07 19:29:47.752 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Search on service ContentDirectory reply {TotalMatches=0, UpdateID=0, NumberReturned=0, Result=<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"></DIDL-Lite>}
2020-09-07 19:29:47.752 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 0 from service ContentDirectory
2020-09-07 19:29:47.752 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 0 from service ContentDirectory
2020-09-07 19:29:47.753 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 0 from service ContentDirectory
2020-09-07 19:29:47.753 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable Result with value <DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"></DIDL-Lite> from service ContentDirectory
2020-09-07 19:29:47.753 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-07 19:29:47.753 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - UP added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:29:47.753 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 1 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:29:47.753 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-07 19:29:47.754 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list []
2020-09-07 19:29:47.754 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-07 19:29:47.754 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable
2020-09-07 19:29:52.671 [WARN ] [org.openhab.binding.upnpcontrol.test_script] - AFTER SEARCH: Twonky_Search_Criteria: upnp:class = "object.container.playlistContainer" and dc:title = "HA_Thanksgiving", Twonky_Browse: .., Twonky_ID: 0$1$9$154677
2020-09-07 19:29:52.691 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command PLAY for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:control on server TwonkyMedia [NAS01]
2020-09-07 19:29:52.691 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler] - Handle command PLAY for channel upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-30f9ed4f6395:control on renderer Portable
2020-09-07 19:29:55.192 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler] - Timeout exception, media URI not yet set in the renderer, trying to play anyway
2020-09-07 19:29:55.192 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device Portable invoke upnp action Play on service AVTransport with inputs {Speed=1, InstanceID=0}
2020-09-07 19:29:55.260 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device Portable invoke upnp action Play on service AVTransport reply {}
2020-09-07 19:30:39.277 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command .. for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse on server TwonkyMedia [NAS01]
2020-09-07 19:30:39.277 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Navigating to node 0 on server TwonkyMedia [NAS01]
2020-09-07 19:30:39.277 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Browse target 0
2020-09-07 19:30:39.278 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Browse on service ContentDirectory with inputs {SortCriteria=+dc:title, ObjectID=0, Filter=*, BrowseFlag=BrowseDirectChildren, RequestedCount=0, StartingIndex=0}
2020-09-07 19:30:39.333 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Browse on service ContentDirectory reply {TotalMatches=3, UpdateID=61, NumberReturned=3, Result=<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><container id="0$1" parentID="0" restricted="1" childCount="5" searchable="1" pv:persistentID="music"><dc:title>Music</dc:title><pv:childCountContainer>5</pv:childCountContainer><pv:modificationTime>79979</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$2" parentID="0" restricted="1" childCount="2" searchable="1" pv:persistentID="picture"><dc:title>Photos</dc:title><pv:childCountContainer>2</pv:childCountContainer><pv:modificationTime>2403237</pv:modificationTime><pv:containerContent>object.item.imageItem.photo</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$3" parentID="0" restricted="1" childCount="3" searchable="1" pv:persistentID="video"><dc:title>Videos</dc:title><pv:childCountContainer>3</pv:childCountContainer><pv:modificationTime>2017121042</pv:modificationTime><pv:containerContent>object.item.videoItem.movie</pv:containerContent><upnp:class>object.container</upnp:class></container></DIDL-Lite>}
2020-09-07 19:30:39.333 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 3 from service ContentDirectory
2020-09-07 19:30:39.333 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 61 from service ContentDirectory
2020-09-07 19:30:39.333 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 3 from service ContentDirectory
2020-09-07 19:30:39.333 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable Result with value <DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><container id="0$1" parentID="0" restricted="1" childCount="5" searchable="1" pv:persistentID="music"><dc:title>Music</dc:title><pv:childCountContainer>5</pv:childCountContainer><pv:modificationTime>79979</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$2" parentID="0" restricted="1" childCount="2" searchable="1" pv:persistentID="picture"><dc:title>Photos</dc:title><pv:childCountContainer>2</pv:childCountContainer><pv:modificationTime>2403237</pv:modificationTime><pv:containerContent>object.item.imageItem.photo</pv:containerContent><upnp:class>object.container</upnp:class></container><container id="0$3" parentID="0" restricted="1" childCount="3" searchable="1" pv:persistentID="video"><dc:title>Videos</dc:title><pv:childCountContainer>3</pv:childCountContainer><pv:modificationTime>2017121042</pv:modificationTime><pv:containerContent>object.item.videoItem.movie</pv:containerContent><upnp:class>object.container</upnp:class></container></DIDL-Lite> from service ContentDirectory
2020-09-07 19:30:39.334 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-07 19:30:39.334 [TRACE] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 0$1 added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:30:39.334 [TRACE] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 0$2 added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:30:39.334 [TRACE] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 0$3 added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:30:39.334 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 3 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-07 19:30:39.334 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-07 19:30:39.334 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list [Music, Photos, Videos]
2020-09-07 19:30:39.335 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-07 19:30:39.335 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable

Another thing I am seeing is that after a renderer or media server is restarted, the subscriptions appear to fail. As a workaround, you can disable and reenable the Thing.

I fixed some issues with setting currentId and browsing on the server, and an issue with setting NextURI on the renderer. I hope the fix on the renderer also solves playing entries double. But as I didn’t have the issue myself, you will need to test again.

I may have to look into improving this. The status is supposed to refresh every 60s, but I may have missed something on that.

1 Like

Thank you, Mark… I will go test it out!

  • After searching for a specific playlist, the CurrentURI is not being populated. So, when playing, you get an old track and not something from the new search. After the old one plays, new ones play, but each track repeats twice. old track after search and double tracks.log (331.7 KB)
  • After restarts, my Items linked to shuffle, repeat, and playonlyone always change to OFF, even though they are persisted and have been set to ON before the restart. I then have to reconfigure them for each speaker.
  • In order to search from a script, you almost always need to set currentid to 0, but you then need to pause before starting the search. I suggest making a separate Channel that searches from the root. Or, a Channel to switch the search behavior from root to current ID.

I’ll play some more later tonight! Does reporting these issues and features in the forum work for you, or would you prefer me to be submitting issues and PRs to your fork? I’ve been staying out of the code until your development efforts have settled down a bit, so we don’t step on each other.

Are you sure it does not work without pause? After setting currentId to 0, a browse on 0 is started. But the search should not start before the browse command finished (there is a completableFuture blocking it for 2.5s max). And I set the internal representation of currentId to the 0 value before doing the browse.

That should be OK now.

Are you sure the previous one was not already playing? I can’t see that from the start of the log. The principle is, when doing a browse or search, the resulting media are immediately sent to the renderer if one is selected. But if the renderer is already playing something, don’t put it on the renderer as CurrentURI, but as NextURI (and next media entry to play). Stopping the player before sending something would avoid this, as it would end up at the start of the queue.
I will go through the state flags again to check if I missed something. Renderer state representation in the handler is very tricky, with state being influenced by received state from the renderer through the AVTransport, commands and queues received from the servers, favorites and playlists restored directly on the renderer.

I put in a lot more logging and made a few changes. Please try with the latest. Not sure it is correct yet, but I will hopefully be able to analyze better.

I made it a configuration parameter on the thing.

Let’s keep on for a bit this way. Happy if you look at the code and suggest improvements, but especially the renderer logic is tricky. And it would not be helpful changing oposing things.

Yes, since the browse command has not finished. Originally, I used a sleep command. I then used a while loop, watching for a change in currentid. That was not enough, since I needed to watch for the change in browse.

Separate Channels would make this a lot easier. However, since search is currently only useful from scripts and is not useful in a UI without a TextBox widget, a better option is to remove the search Channel and move that functionality into a binding Action. This would allow for the ContainerID, SearchCriteria, Filter, StartIndex, RequestedCount, and SortCriteria to be provided as arguments to the Action.

I see you’ve added a configuration parameter for this :+1:.

Yes, it was not playing. IIRC, the log shows all tracks are duplicated.Also, if playonlyone is ON, you only get the old track the first time you play, and subsequent plays are the new tracks.

Yikes… I see you may have fixed this! I won’t be able to test until later this evening.

I did changes there and I hope it improves things. At least I should have more logging to track what is happening.

The currentID is set a first time just before browse or search. However, it may get set a second time when only one container is returned, triggering a second browse. That means you can only use the result when the browse has completely finished. But once the currentId is set to 0, you can trigger a search, as it will get queued after the search. So therefore I believe an immediate search should be possible (search uses the currentId). The always search from root flag should help on this as well I believe.

Search and browse channels (and playlists) are multiple ways to fill a unique queue. Therefore I don’t think it gets clearer by putting one of them in an action. I hope 3.0 will get us some UI that can accept text also. In principle, I do like actions, I am just not convinced here as the ultimate goal is also to be able to do this interactively. I may reconsider at one point though.

I did a major refactoring of the device parameters and reconnection logic. Let me know if it still behaves OK.

@5iver I have pushed some more commits.
I am focussing on getting some unit test classes to test the main interactions. I hope this will reduce the number of regressions we see when I do some development or fix some other issues. I have it more or less done for the server, but still need to do the renderer tests. The interactions are more complex there. It has been a very steep learning curve for me, and I very much realized that may implementations may not have been done in the best way to easily add unit tests. And, unfortunately, I will have to adapt them for OH3 as the framework moved to JUnit 5.
Anyway, I am still keen on improving the implementation and ultimately get it submitted. I keep on developing for 2.5 for the time being, and will get it on OH3 when I am ready to submit. But I intend to submit on OH3 and not keep 2.5 maintained afterwards. It is just too much of a hassle to keep two separate development environments on Jave 8 and 11. I will switch completely just before I submit.
In the mean time, if you still have feedback, please let me know.

Thank you, Mark… you have done an amazing job with this binding! I have not had much time for OH lately, but I will take a look at your updates. The binding is working great for everything that I normally use it for, but I still have some work to do to transition to using search.

I have added an extra audio sink to each renderer thing in the binding (the renderer id with “-notify” appended to the id). When playing through this audio sink, playing of other media that were playing before will resume at the same position after the notification (provided UPnP seek is supported for the renderer and media).
There are 2 configuration parameters on the renderer, one to set the notification volume specifically for this channel, and the other one for a maximum notification duration. The notification will be cut off at the end of the maximum duration.
I considered defining a specific action for this, but it turned out to be a lot easier to reuse the audio sink actions (that take care of files and streams already).
The volume can be overriden in the playSound and say actions (unfortunately not for playStream) as a parameter of the action. This volume override will only be for the specific notification.

A compiled .jar for 2.5.9 can be found here.

My intention is to add a few test for this notification functionality and get some feedback before porting it over to OH3 and submitting for review. I consider it code complete.

1 Like

This sounds great! I haven’t tested the notifications yet, but I will let you know how it goes! I have two suggestions though…

  1. The override sound level requires a value and I do not want to override the volume of certain speakers. For example, in two our our bathrooms, I set the volume based on whether there is activity in the shower, so that the sound is loud enough to hear in the shower and not too loud when not in the shower. For a notification, I’d want the volume to stay at the level that it was set to. I suggest allowing the override volume to be blank (null), and this should be the default. The notification should then just play at the current volume. Currently, if it is cleared, the notification volume reverts to the default (60). With the volume always being forced, this feature would be unusable for me.
  2. Similar to the notification volume, the maximum duration should be allowed to be left blank, and this should be the default. I use notifications of variable length and they may be as long as a few minutes, maybe more. I could guess at a maximum, but I think it makes more sense to just leave it blank and not force a maximum. This one is not a big deal though.
  1. This is difficult. I don’t touch the audioSink command logic, and it always sets a volume, doesn’t accept null. What may make sense is to redefine the parameter as a % difference from current sound volume. That would allow to play the notifications x % louder than what is currently playing (if no volume is explicitly set). Setting it to 0 would be your requested behavior.
  2. If you set maxnotificationduration to 0, it already does that. I still think the parameter makes a lot of sense. It allows to interrupt for instance online streams with no end used as notifications. You can also put it very high. If the notification ends, it will switch back anyway.

I have some concern that the renderer handler class has become huge and difficult to maintain. I expect this will be a concern in review. It would be a major effort to split it in multiple classes though and I don’t have a clear idea yet on how to split it.

I now solved it by not having a default value, but a default % difference.

Some test have been added.

All feedback is welcome. I will give it a few days before moving the code to OH3.

1 Like