Why can’t you modify your software to allow true shuffle or random play?

Mutualsushi

New member
Joined
Jul 4, 2024
Messages
2
I’d much rather buy an Ultra and use the WiiM App to stream my vast library of CD’s and downloads than continue to use Apple Airplay on my WiiM Plus. I’m not a programmer but I’ve done some back in the day and I just can’t understand why it would be so difficult? Furthermore, if there is a reason, why won’t you explain to us what it is?
 
I think your second sentence answers itself. As for a reason, perhaps WiiM have more pressing development priorities?
 
To be honest the shuffle feature is the only reason I keep Roon.
It’s nice to rediscover something in your collection you may not have listened to for a while
 
WiiM are one of the most reactive companies I know of when it comes to post release software support, I'm sorry something about your WiiM bothers you, but I've rarely seen a product that gets so many firmware updates with new features.
 
I brought this up in another thread a little while ago and apparently it's not as easy to implement as one might think due to the code that's running how the USB media library is created/indexed/accessed, etc. It sounds like most or all of the entire process would have to be either rewritten or ditched all together for a different "app", so to speak, to accomplish it...

Implementation of a true "shuffle" or random playback
 
I brought this up in another thread a little while ago and apparently it's not as easy to implement as one might think due to the code that's running how the USB media library is created/indexed/accessed, etc.
It's not difficult, but it is performed in the app so it's not particularly efficient.

When the WHA browses an index e.g. Album or Songs, the server tells the app how many items are in the index.
The app can either retrieve all the items and sort the list randomly, or request one item at a time from random positions in the list (really inefficient if you want to retrieve a lot of items).

There's been very little development on the UPnP/USB Input side of things for well over a year now. It's just down to priorities.
 
There are many actions available in the UPnP PlayQueue interface. Available for anyone to write their own UI...

http://<your WiiM IP>:49152/upnp/PlayQueueSCPD.xml

XML:
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<actionList>
<action>
<name>CreateQueue</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>ReplaceQueue</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>DeleteQueue</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>BackUpQueue</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>AppendQueue</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>BrowseQueue</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>QueueContext</name>
<direction>out</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetQueueLoopMode</name>
<argumentList>
<argument>
<name>LoopMode</name>
<direction>in</direction>
<relatedStateVariable>LoopMode</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetQueueLoopMode</name>
<argumentList>
<argument>
<name>LoopMode</name>
<direction>out</direction>
<relatedStateVariable>LoopMode</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetQueuePolicy</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>PlayQueueWithIndex</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>Index</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>AppendTracksInQueue</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>RemoveTracksInQueue</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
<argument>
<name>RangStart</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>RangEnd</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>AppendTracksInQueueEx</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
<argument>
<name>Direction</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>StartIndex</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>Play</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetKeyMapping</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetKeyMapping</name>
<argumentList>
<argument>
<name>QueueContext</name>
<direction>out</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetQueueOnline</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>QueueID</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>QueueType</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
<argument>
<name>Queuelimit</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>QueueAutoInsert</name>
<direction>in</direction>
<relatedStateVariable>QueueAutoInsert</relatedStateVariable>
</argument>
<argument>
<name>QueueContext</name>
<direction>out</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SearchQueueOnline</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>SearchKey</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>Queuelimit</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>QueueContext</name>
<direction>out</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetQueueRecord</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>QueueID</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>Action</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetSongsRecord</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>SongID</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>Action</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>UserRegister</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>UserName</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>PassWord</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>UserLogin</name>
<argumentList>
<argument>
<name>AccountSource</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>UserName</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>PassWord</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
<argument>
<name>SavePass</name>
<direction>in</direction>
<relatedStateVariable>QueuePolicy</relatedStateVariable>
</argument>
<argument>
<name>Code</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>Proxy</name>
<direction>in</direction>
<relatedStateVariable>Proxy</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>UserLogout</name>
<argumentList>
<argument>
<name>AccountSource</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetUserInfo</name>
<argumentList>
<argument>
<name>AccountSource</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetUserAccountHistory</name>
<argumentList>
<argument>
<name>AccountSource</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>Number</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetUserFavorites</name>
<argumentList>
<argument>
<name>AccountSource</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>Action</name>
<direction>in</direction>
<relatedStateVariable>Code</relatedStateVariable>
</argument>
<argument>
<name>MediaType</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
<argument>
<name>MediaID</name>
<direction>in</direction>
<relatedStateVariable>QueueID</relatedStateVariable>
</argument>
<argument>
<name>MediaContext</name>
<direction>in</direction>
<relatedStateVariable>QueueContext</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetUserFavorites</name>
<argumentList>
<argument>
<name>AccountSource</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>MediaType</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
<argument>
<name>Filter</name>
<direction>in</direction>
<relatedStateVariable>QueueType</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetQueueIndex</name>
<argumentList>
<argument>
<name>QueueName</name>
<direction>in</direction>
<relatedStateVariable>QueueName</relatedStateVariable>
</argument>
<argument>
<name>CurrentIndex</name>
<direction>out</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>CurrentPage</name>
<direction>out</direction>
<relatedStateVariable>CurrentPage</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>SetSpotifyPreset</name>
<argumentList>
<argument>
<name>KeyIndex</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>DeleteActionQueue</name>
<argumentList>
<argument>
<name>PressType</name>
<direction>in</direction>
<relatedStateVariable>CurrentIndex</relatedStateVariable>
</argument>
</argumentList>
</action>
<action>
<name>GetBasicUserInfo</name>
<argumentList>
<argument>
<name>Result</name>
<direction>out</direction>
<relatedStateVariable>Result</relatedStateVariable>
</argument>
</argumentList>
</action>
</actionList>
<serviceStateTable>
<stateVariable sendEvents="yes">
<name>LastChange</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>QueueName</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>QueueContext</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>CurrentIndex</name>
<dataType>ui4</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>CurrentPage</name>
<dataType>ui4</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>QueuePolicy</name>
<dataType>ui4</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>LoopMode</name>
<dataType>ui4</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>QueueID</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>QueueType</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>QueueAutoInsert</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>Result</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>Code</name>
<dataType>string</dataType>
</stateVariable>
<stateVariable sendEvents="no">
<name>Proxy</name>
<dataType>string</dataType>
</stateVariable>
</serviceStateTable>
</scpd>
 
Back
Top