DLNA / UPNP binding

I think I may have found the issue. When I send a media URI to my renderer, it always sends back a GENA Last Change event with the URI. But as it is a Last Change event, it is only expected to send something back when the URI has changed. I was waiting for this URI to come back before playing to make sure it was set. In your logs, these events are not there.
I now changed it to not wait when the URI being set is the same as the last known one. I will also try to play anyway after a timeout. Info in the UI might get out of sync, but it will do a best effort attempt to play something. Give me a bit of time to push the changes.

Edit: My Github should be updated. I also loaded the .jar here.

Wow! There are a lot of changes! I’m restarting OH after…

2020-08-27 12:44:20.183 [INFO ] [org.apache.felix.fileinstall] - Updating bundle org.openhab.binding.upnpcontrol / 2.5.9.202008251218
2020-08-27 12:44:20.607 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler tried updating the thing status although the handler was already disposed.
2020-08-27 12:44:20.620 [WARN ] [org.eclipse.smarthome.core.internal.common.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception: 
java.lang.NullPointerException: null
        at org.openhab.binding.upnpcontrol.internal.UpnpControlHandlerFactory.registerAudioSink(UpnpControlHandlerFactory.java:152) ~[?:?]
        at org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler.registerAudioSink(UpnpRendererHandler.java:1033) ~[?:?]
        at org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler.updateProtocolInfo(UpnpRendererHandler.java:1020) ~[?:?]
        at org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler.onValueReceived(UpnpHandler.java:463) ~[?:?]
        at org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler.onValueReceived(UpnpRendererHandler.java:775) ~[?:?]
        at org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler.lambda$4(UpnpHandler.java:379) ~[?:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_242]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_242]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_242]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_242]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_242]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_242]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_242]
2020-08-27 12:44:20.725 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler tried updating the thing status although the handler was already disposed.
2020-08-27 12:44:20.745 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler tried updating the thing status although the handler was already disposed.
2020-08-27 12:44:20.749 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler tried updating the thing status although the handler was already disposed.
2020-08-27 12:44:20.867 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler tried updating the thing status although the handler was already disposed.
2020-08-27 12:44:20.949 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler of thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f521099e tried updating channel title although the handler was already disposed.
2020-08-27 12:44:20.949 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler of thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f521099e tried updating channel album although the handler was already disposed.
2020-08-27 12:44:20.950 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler of thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f521099e tried updating channel albumart although the handler was already disposed.
2020-08-27 12:44:20.950 [WARN ] [org.eclipse.smarthome.core.thing.binding.BaseThingHandler] - Handler UpnpRendererHandler of thing upnpcontrol:upnprenderer:5f9ec1b3-ed59-1900-4530-0007f521099e tried updating channel creator although the handler was already disposed.

That’s got it! I’ve not seen any timeouts after repeatedly playing/stopping/playing the same URL using playStream. I have also tested repeatedly sending the same URL without stopping and everything worked properly. UI looks fine.

I also forgot to mention that I had tested out shuffle and it worked beautifully. The very first time, I thought something was wrong, since it played the first track in the playlist, but I just got lucky with 1 out of 7!

Very low level feature request… allow Previous to sequentially cycle through the previous tracks, even when shuffle is enabled. Currently, it plays another random track.

THANK YOU! This binding is on par with Z-Wave and Zigbee for me… I love it!

5iver @Thanks for the praise. However, I don’t think I am in the same league as Chris.

I don’t keep track of the sequence for shuffle at the moment. And shuffle will also never end. I look for a random entry each time a new entry is needed for playing. I thought about being able to play previous, but that would force me to keep a full play sequence, as you can go back multiple times.

To make it work, I would need to change to:

  • when switching on shuffle, or when serving a new queue when shuffle is on, do a random sort of the queue.
  • server in that random sort order.

What happens when I switch off shuffle while playing? Would I go back to the orignal order and serve the one after the current entry from the original order? What if the current one is the last one in the original queue?

Should shuffle still be continuous play, or only when repeat is also turned on?

The shuffle logic is in the queue management, so should be fairly easy to adapt. I was just not sure what the best approach was and settled on the easy option for now.

Did you try search? Does it behave as expected now?

Do you feel it is ready for submitting a PR?

I implemented it. Let me know what you think.

1 Like

I meant this as a comparison of functionality :slightly_smiling_face:. Having AV UPnP in OH is huge… people just don’t realize it yet!

Save it for a rainy day! For me it’s very low in priority and I do not think many people will even notice it or care. Building out a queue though… that would be some effort but really put some icing on this as a control point. Did you look at the AudioNet app? You can enable/disable shuffle, build out a queue, play from the queue, remove things from the queue, etc. And you can select another renderer and manipulate its queue too. When we have people over, I set up multiple genres on a few renderers throughout the house.

It sounds like you have not implemented Shuffle but Random. Random plays a random song in the list, so there can be repeats before all songs in the list have played. Shuffle plays all songs in a list in a random order. If you add repeat to shuffle, it would be neat to have it start in a random order, which is what I have implemented in my scripts.

Go back to the original order and continue from where the current track is located in the list.

If repeat is ON, go to first. If not, stop.

Definitely only when repeat is on!

Search is now unpredictable and I’m still trying to understand what it’s doing. Search is also buggered. If you stop, browse, play, browse, play… nothing happens… upnp testing.log (145.2 KB). If you stop, browse, play, stop, browse, play… everything is OK.

No, not yet. But even with the bugs fixed, considering how slow the maintainers are, you may want to get in some more stuff in before submitting. There will be less reviews that way, but definitely try to get a PR in within the next week or two so that it can be approved for 2.5.9, which is the last of 2.5.x except bug fixes.

How about Channels on the media server to select the behavior of the Search? I could see two switches… one for whether or not to play the result after a Seach, and another for whether to always start the search from the root. Or these could be different types of Search Criteria Channels (I think I like this option best). You could also do this with a single Channel with a selection for…

  • Search
  • Search from root
  • Search and play
  • Search from root and play

The ability to Search from the root and play afterward the search would save a LOT of headaches in getting aomething to play after a search. For example, you could search for a playlist of spooky Halloween sounds and randomly play one of them, all by setting the renderer and sending a string to the search criteria. Motion in another room… set the renderer and set the criteria. I currently do this with a lot of Python and API calls to Twonky.

Nice! It seems to work perfectly and you now have implemented true Shuffle! With Repeat turned on though, it played the same random order the second and third time through. IMO, this should be random each time. If you were really serious about it, remove the last played track too, in order to remove the possibility of repeating the last track played. With two tracks, you end up playing the original random order, but who cares! If there is only one track in the playlist, ignore Shuffle.

So, you have a source_list and a working_list. When browsing, populate both the source_list and working_list. If Shuffle it ON and len(source_list) > 1, working_list should be shuffled. When playing, pop the tracks out of the working_list. When it is empty, repopulate it from source_list. If Shuffle is ON and len(source_list) > 1, pop the last track played and then shuffle.

I had a quick look. Do I undertstand it well that the playlists are saved locally in the app (control point)? So no new playlists are created on the media server?

It’s been a while since I looked into how and what it was doing, but IIRC, it maintains it’s own queue of tracks and listens for when the CurrentURI changes. It then sends the next track to NextURI. It maintains a queue for each renderer too, which is pretty cool.

Come to think of it, these Channels should be included in the binding (CurrentURI and NextURI). This is actually functionality I would need, at least CurrentURI, since I use it in my scripts to restore audio after playing an announcement (presence detected in area, a random radio stream plays, something triggers and announcement to play, the radio station resumes after the alert). Then again, that all may change a bit when using Search Criteria.

That is also what the binding is doing. However, setting the next URI is not supported by many renderers.

You can do that with the binding. Select a renderer and make a selection. The selection will be sent to the renderer. Then select another renderer and make another selection. This second selection will be sent to the second renderer.
I am working on a feature to create playlists that can be reused.

Adding the channels is probably OK, but It will be challenging keeping consistency with the meta data. An URI alone does not contain metadata, so that would all get lost when setting the URI directly. I now take special care to remove the metadata when using the playSound or playStream commands, but when you then push next, it will go to the next entry on the selection from the server.
The better solution to play notifications and resume afterwards would be a separate play Notification action I believe. When using the action, I could store the current state an resume from there. When playing from an audio file iso stream, I should use seek to try to go back to the last position in the track. For streaming media, that would of course not work.

I am not sure what to do with search yet. For me, it is working as designed. If you search on individual items, that’s what will get into the browse selection. Pressing play will play these immediately. Searching on containers (folders, playlists) will not get individual items, but containers. Hence you need to browse the appropriate one again to go down to individual items to be able to play. For that reason, there is a challenge with a feature like automatic play. It can only play media entries, not containers. Otherwise it is not consistent with browse anymore.

I have a first version of playlists implemented. It is not working entirely as I want yet, but it gives an idea about where I want to go with it.

The current code also supports better shuffle (new shuffle when back at the beginning of the list, and not starting with last one).

@5iver I have implemented a few more things:

  • URI channel on renderer
  • Playlists on server thing, with possibility to select, create, save, append, delete
  • Favorites on renderer thing, with possiblity to select (and play), create, delete. This is useful for streams as well. Streams can by definition not be part of a playlist. You could use it to make a radio channel selection list.

Playlists and favorites are saved on disk, by default in the user runtime directory. But this is configurable as a binding parameter.

All of this needs much more testing and documenting. The code is online.

Ah… I understand your question better now. Yes, AudioNet allows you to save/load the playlists created in the app. Doing this in OH would be interesting.

That would be fantastic… the app for SmartThings that I mentioned provided this functionality.

I have been testing the previous build and everything has been working well as far as using playStream through automations. There seemed to be a regression though, when sending “0” to currentID, since it was not properly navigating to root. Sending “…” three times was working though. There was a recent change in this area.

I’ll go try the latest!

I am a bit surprised about this. According to the UPnP ContentServer standard, browsing 0 should always browse from directory root. Root could be another Id though, therefore it may immediately set another Id as a result of the browse. “…” is nowhere defined as a standard id or destination. That may be Twonky specific.
Could you send me a log of what it is doing when setting the current id to 0?

This was Discourse being helpful… I was only sending two periods ".." three times. Discourse is changing it to three.

Here you go… upnp.log (100.5 KB)

This might help too…

2020-08-28 22:38:01.541 [WARN ] [jython.TEST_3] - START: Twonky_Search_Criteria: dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer", Twonky_Browse: 0$1$9$154588, Twonky_ID: 0$1$9$154588P0R11221772
2020-08-28 22:38:02.542 [WARN ] [jython.TEST_3] - BEFORE SEARCH: Twonky_Search_Criteria: dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer", Twonky_Browse: 0$1$9$154588, Twonky_ID: 0$1
2020-08-28 22:38:03.043 [WARN ] [jython.TEST_3] - AFTER SEARCH: Twonky_Search_Criteria: dc:title = "Dance" and upnp:class = "object.container.playlistContainer", Twonky_Browse: 0$1$9$154588, Twonky_ID: 0$1$9$154588
2020-08-28 22:38:03.294 [WARN ] [jython.TEST_3] - AFTER setting BROWSE: Twonky_Search_Criteria: dc:title = "Dance" and upnp:class = "object.container.playlistContainer", Twonky_Browse: 0$1$9$154588, Twonky_ID: 0$1$9$154633

@5iver I believe I fixed the issue with setting the current id. And this should also fix an issue with search.
I did some testing on playlists and favorites, and that seems to work fine now.
It is probably best to read through the README to get a full understanding on how it works. I hope you like it.
Again, more testing is required and very much appreciated.

I am not sure I wil still be able to make it for 2.5.9. There is so much change to the code and so much additional code and functionality that it will be a major task for a reviewer to review this. But that will mean switching to 3.0 in a few weeks. Before I can do that, I need to also get my production system on 3.0. So expect some more time before we can get this through.
Anyway, that should give me the chance to also implement notifications before submitting for review.

After selecting the renderer for the media server, neither the server Player or renderer Player states were populated. Restarting the binding and OH did not help.

In reading through the readme.md, it would be helpful to know whether the Channels are read-write, read-only, or write-only.

I found the URI Channel! I’ll need to change a few things in my scripts to transition over to it.

I’m still having trouble with Search. Sending currentid 0 seems to be working properly, but the search does not populate the Browse commands or currentid properly. Here is the result of running the following simple script twice…

from time import sleep

events.sendCommand("Twonky_ID", "0")
sleep(1)

LOG.warn("BEFORE SEARCH: Twonky_Search_Criteria: {}, Twonky_Browse: {}, Twonky_ID: {}".format(items["Twonky_Search_Criteria"], items["Twonky_Browse"], items["Twonky_ID"]))

if items["Twonky_Search_Criteria"].toString() == 'dc:title = "Dance" and upnp:class = "object.container.playlistContainer"':
    #events.sendCommand("Twonky_Search_Criteria", 'dc:title = "_Wake up!" and upnp:class = "object.container.playlistContainer"')
    events.sendCommand("Twonky_Search_Criteria", 'dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer"')
else:
    events.sendCommand("Twonky_Search_Criteria", 'dc:title = "Dance" and upnp:class = "object.container.playlistContainer"')

sleep(0.5)
LOG.warn("AFTER SEARCH: Twonky_Search_Criteria: {}, Twonky_Browse: {}, Twonky_ID: {}".format(items["Twonky_Search_Criteria"], items["Twonky_Browse"], items["Twonky_ID"]))
2020-09-04 05:10:08.168 [WARN ] [jython.TEST_3] - BEFORE SEARCH: Twonky_Search_Criteria: dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer", Twonky_Browse: .., Twonky_ID: 0
2020-09-04 05:10:08.670 [WARN ] [jython.TEST_3] - AFTER SEARCH: Twonky_Search_Criteria: dc:title = "Dance" and upnp:class = "object.container.playlistContainer", Twonky_Browse: .., Twonky_ID: 0
2020-09-04 05:10:14.072 [WARN ] [jython.TEST_3] - BEFORE SEARCH: Twonky_Search_Criteria: dc:title = "Dance" and upnp:class = "object.container.playlistContainer", Twonky_Browse: .., Twonky_ID: 0
2020-09-04 05:10:14.574 [WARN ] [jython.TEST_3] - AFTER SEARCH: Twonky_Search_Criteria: dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer", Twonky_Browse: .., Twonky_ID: 0
2020-09-04 05:10:08.181 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command dc:title = "Dance" and upnp:class = "object.container.playlistContainer" for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:search on server TwonkyMedia [NAS01]
2020-09-04 05:10:08.181 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Navigating to node 0 on server TwonkyMedia [NAS01]
2020-09-04 05:10:08.181 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Search container 0 for dc:title = "Dance" and upnp:class = "object.container.playlistContainer"
2020-09-04 05:10:08.182 [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, Filter=*, RequestedCount=0, SearchCriteria=dc:title = "Dance" and upnp:class = "object.container.playlistContainer", StartingIndex=0}
2020-09-04 05:10:08.250 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Search on service ContentDirectory reply {TotalMatches=1, UpdateID=0, NumberReturned=1, 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$9$154552" parentID="0$1$9" restricted="0" childCount="2" searchable="1"><res protocolInfo="http-get:*::application/vnd.ms-wpl">http://10.5.5.10:9000/download/P0$1$9$154552.wpl</res><dc:title>Dance</dc:title><upnp:album>Dance</upnp:album><upnp:albumArtURI dlna:profileID="JPEG_TN" >http://10.5.5.10:9000/disk/DLNA-PNJPEG_TN-OP01-CI1-FLAGS00d00000/defaa/C/O0$1$9$154552.jpg?scale=org</upnp:albumArtURI><pv:childCountContainer>0</pv:childCountContainer><pv:modificationTime>497693</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container.playlistContainer</upnp:class></container></DIDL-Lite>}
2020-09-04 05:10:08.251 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 1 from service ContentDirectory
2020-09-04 05:10:08.251 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 0 from service ContentDirectory
2020-09-04 05:10:08.251 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 1 from service ContentDirectory
2020-09-04 05:10:08.251 [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$9$154552" parentID="0$1$9" restricted="0" childCount="2" searchable="1"><res protocolInfo="http-get:*::application/vnd.ms-wpl">http://10.5.5.10:9000/download/P0$1$9$154552.wpl</res><dc:title>Dance</dc:title><upnp:album>Dance</upnp:album><upnp:albumArtURI dlna:profileID="JPEG_TN" >http://10.5.5.10:9000/disk/DLNA-PNJPEG_TN-OP01-CI1-FLAGS00d00000/defaa/C/O0$1$9$154552.jpg?scale=org</upnp:albumArtURI><pv:childCountContainer>0</pv:childCountContainer><pv:modificationTime>497693</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container.playlistContainer</upnp:class></container></DIDL-Lite> from service ContentDirectory
2020-09-04 05:10:08.253 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-04 05:10:08.253 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - UP added to selection list on server TwonkyMedia [NAS01]
2020-09-04 05:10:08.253 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 2 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-04 05:10:08.254 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-04 05:10:08.254 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list [Dance]
2020-09-04 05:10:08.254 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-04 05:10:08.254 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable
2020-09-04 05:10:13.080 [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-04 05:10:13.080 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Setting currentId to 0
2020-09-04 05:10:13.081 [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-04 05:10:13.144 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Browse on service ContentDirectory reply {TotalMatches=3, UpdateID=1726, 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-04 05:10:13.144 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 3 from service ContentDirectory
2020-09-04 05:10:13.144 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 1726 from service ContentDirectory
2020-09-04 05:10:13.145 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 3 from service ContentDirectory
2020-09-04 05:10:13.145 [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-04 05:10:13.146 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-04 05:10:13.146 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 3 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-04 05:10:13.146 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-04 05:10:13.146 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list [Music, Photos, Videos]
2020-09-04 05:10:13.146 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-04 05:10:13.146 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable
2020-09-04 05:10:14.087 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer" for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:search on server TwonkyMedia [NAS01]
2020-09-04 05:10:14.087 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Navigating to node 0 on server TwonkyMedia [NAS01]
2020-09-04 05:10:14.087 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Search container 0 for dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer"
2020-09-04 05:10:14.088 [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, Filter=*, RequestedCount=0, SearchCriteria=dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer", StartingIndex=0}
2020-09-04 05:10:14.155 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Search on service ContentDirectory reply {TotalMatches=1, UpdateID=0, NumberReturned=1, 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$9$154588" parentID="0$1$9" restricted="0" childCount="7" searchable="1"><res protocolInfo="http-get:*::application/vnd.ms-wpl">http://10.5.5.10:9000/download/P0$1$9$154588.wpl</res><dc:title>Donnie Darko</dc:title><upnp:album>Donnie Darko</upnp:album><upnp:albumArtURI dlna:profileID="JPEG_TN" >http://10.5.5.10:9000/disk/DLNA-PNJPEG_TN-OP01-CI1-FLAGS00d00000/defaa/C/O0$1$9$154588.jpg?scale=org</upnp:albumArtURI><pv:childCountContainer>0</pv:childCountContainer><pv:modificationTime>506476</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container.playlistContainer</upnp:class></container></DIDL-Lite>}
2020-09-04 05:10:14.155 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 1 from service ContentDirectory
2020-09-04 05:10:14.155 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 0 from service ContentDirectory
2020-09-04 05:10:14.155 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 1 from service ContentDirectory
2020-09-04 05:10:14.155 [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$9$154588" parentID="0$1$9" restricted="0" childCount="7" searchable="1"><res protocolInfo="http-get:*::application/vnd.ms-wpl">http://10.5.5.10:9000/download/P0$1$9$154588.wpl</res><dc:title>Donnie Darko</dc:title><upnp:album>Donnie Darko</upnp:album><upnp:albumArtURI dlna:profileID="JPEG_TN" >http://10.5.5.10:9000/disk/DLNA-PNJPEG_TN-OP01-CI1-FLAGS00d00000/defaa/C/O0$1$9$154588.jpg?scale=org</upnp:albumArtURI><pv:childCountContainer>0</pv:childCountContainer><pv:modificationTime>506476</pv:modificationTime><pv:containerContent>object.item.audioItem.musicTrack</pv:containerContent><upnp:class>object.container.playlistContainer</upnp:class></container></DIDL-Lite> from service ContentDirectory
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - UP added to selection list on server TwonkyMedia [NAS01]
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 2 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list [Donnie Darko]
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-04 05:10:14.156 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable

This will never get anything. The browse channel is a command channel, not a state channel. So an item attached to it will never get a state update, therefore will always have the value of the last command you gave for browsing. The idea is, that in the UI, you have a selection list of containers or media, and selecting one immediately updates the selection list. There is no point in keeping a record of one entry in the list.

Play should start playing all of the media (not container) entries in the selection list.

The issue with your search is that the selection list gets updated properly, but because you select on a container, it is not able to play anything. You would need to browse again on that one container to get the media in the container in the selection list. Play would then play that content. But you cannot browse to the specific selection from a script, as you do not have access to the content of the selection list (or do you?).

To prove the point, try a search for media, rather than a playlist. Maybe it is possible to define a search string for content of a container. I am not sure.

If the search returns only one container result, logic would say you would want the content of the container. But what if multiple containers get returned? Without selecting, there is no way to know what to return.

So, at the moment that part it is working as designed. I am open for a better design though.

It does populate the browse selection list. I may have missed the currentid update after search (I did the same as for browse, but that is not the right logic, will adapt).
Edit: it is the right logic. The currentId will be populated with the container the search starts from. A search can return content contained in multiple containers. The only common factor is the higher level container the search started from. Assume I take the parent of the first entry, what about the other entries in that case?

No idea. I have not seen that happening. What status are you specifically refering to? Media control? The renderer should always show the status of the real player (it subscribes to transport status updates). The server sees the status as soon as a renderer is selected. That works for me. A log may help.

Agreed.

@5iver I have updated the readme with the info, but also converted 2 channels to command only channels (playlist select and favorite select). It is more consistent, simplifies the internals, and the values are available for changing in the playlist and favorite channels anyway. So state can be retrieved from there.

I did not do any further changes to search. Suggestions welcome.

Of course I do :grin:, but it wouldn’t be straight forward for people to use. If currentid is populated, then I can just send it to Browse and I should able to search and play containers. In the searches I am doing, I expect only one playlist to be returned. I could just send the ID to currentid, but they change every time I restart my NAS. From a purely automation viewpoint, search is unusable without being able to get at the data returned by the search. If a search returns a single container, I think it would be safe to open it up in browse, rather than requiring it to be selected first. That would save the step of sending the currentid to Browse.

Using a search that only returns tracks always seems to timeout. I have a large library on a slow NAS and it can take 20-30s to return a search result.

from core.log import logging, LOG_PREFIX#, log_traceback
LOG = logging.getLogger("{}.TEST_3".format(LOG_PREFIX))
from time import sleep
events.sendCommand("Twonky_ID", "0")
sleep(1)
LOG.warn("BEFORE SEARCH: Twonky_Search_Criteria: {}, Twonky_Browse: {}, Twonky_ID: {}".format(items["Twonky_Search_Criteria"], items["Twonky_Browse"], items["Twonky_ID"]))

# if items["Twonky_Search_Criteria"].toString() == 'dc:title = "Dance" and upnp:class = "object.container.playlistContainer"':
#     #events.sendCommand("Twonky_Search_Criteria", 'dc:title = "_Wake up!" and upnp:class = "object.container.playlistContainer"')
#     events.sendCommand("Twonky_Search_Criteria", 'dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer"')
# else:
#     events.sendCommand("Twonky_Search_Criteria", 'dc:title = "Dance" and upnp:class = "object.container.playlistContainer"')
#events.sendCommand("Twonky_Search_Criteria", 'upnp:class derivedfrom "object.item.audioItem.musicTrack" and upnp:artist = "Alice in Chains"')
events.sendCommand("Twonky_Search_Criteria", 'upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right"')
sleep(0.5)
LOG.warn("AFTER SEARCH: Twonky_Search_Criteria: {}, Twonky_Browse: {}, Twonky_ID: {}".format(items["Twonky_Search_Criteria"], items["Twonky_Browse"], items["Twonky_ID"]))
2020-09-04 14:43:01.912 [WARN ] [jython.TEST_3] - BEFORE SEARCH: Twonky_Search_Criteria: upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right", Twonky_Browse: .., Twonky_ID: 0
2020-09-04 14:43:02.413 [WARN ] [jython.TEST_3] - AFTER SEARCH: Twonky_Search_Criteria: upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right", Twonky_Browse: .., Twonky_ID: 0
2020-09-04 14:43:00.920 [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-04 14:43:00.920 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Setting currentId to 0
2020-09-04 14:43:03.420 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Exception, previous server query interrupted or timed out, trying new browse anyway
2020-09-04 14:43:03.421 [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-04 14:43:03.433 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Handle command upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right" for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:search on server TwonkyMedia [NAS01]
2020-09-04 14:43:03.433 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Navigating to node 0 on server TwonkyMedia [NAS01]
2020-09-04 14:43:03.433 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Search container 0 for upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right"
2020-09-04 14:43:03.473 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Browse on service ContentDirectory reply {TotalMatches=3, UpdateID=1730, 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-04 14:43:03.473 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable TotalMatches with value 3 from service ContentDirectory
2020-09-04 14:43:03.474 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable UpdateID with value 1730 from service ContentDirectory
2020-09-04 14:43:03.474 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Upnp device TwonkyMedia [NAS01] received variable NumberReturned with value 3 from service ContentDirectory
2020-09-04 14:43:03.474 [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-04 14:43:03.475 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtering content on server TwonkyMedia [NAS01]: false
2020-09-04 14:43:03.475 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - 3 entries added to selection list on server TwonkyMedia [NAS01]
2020-09-04 14:43:03.475 [DEBUG] [org.openhab.binding.upnpcontrol.internal.UpnpDynamicCommandDescriptionProvider] - Adding command description for channel upnpcontrol:upnpserver:55076f6e-6b79-1d65-a4eb-00089bd0e8f2:browse
2020-09-04 14:43:03.475 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Raw result list [Music, Photos, Videos]
2020-09-04 14:43:03.475 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Filtered result list []
2020-09-04 14:43:03.475 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpServerHandler] - Nothing to serve from server TwonkyMedia [NAS01] to renderer Portable
2020-09-04 14:43:03.475 [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, Filter=*, RequestedCount=0, SearchCriteria=upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right", StartingIndex=0}
2020-09-04 14:43:13.476 [INFO ] [org.jupnp.transport.spi.StreamClient] - Timeout of 10 seconds while waiting for HTTP request to complete, aborting: (OutgoingActionRequestMessage) POST http://10.5.5.10:9000/dev0/srv1/control
2020-09-04 14:43:13.477 [DEBUG] [org.openhab.binding.upnpcontrol.internal.handler.UpnpHandler] - Upnp device TwonkyMedia [NAS01] invoke upnp action Search on service ContentDirectory reply {}

I will track it down in the log. Something seems amiss in the subscriptions. This is an Item linked to the control Channel…

openhab> smarthome:status DS_Office_Speaker_Player
UNDEF

I implemented this, and made it configurable. It is on by default. Actually, what it will do is browse down iteratively to the next level when the result of browse or search is a single container entry. It is a thing configuration parameter.
If the result is more than a single container, behaviour will be as before.
I documented this in the readme and put in a specific section to explain the why.

Any success tracking this down? UNDEF for the control would be indeed when there is something wrong with the subscriptions. The refresh command puts it to UNDEF when no state is known.