Sonos plugin

Hi Lolodomo,

Thanks for your reply.
I didn’t see any lua startup error messages. The device also doesn’t give me any messages, it just shows: “playing:” and then nothing.
I installed yesterday, downloaded yesterday’s zipfile, not sure where to see what version of the plugin it is.

You mean “Playing…” in the Control tab ? Nothing behind ? And no text on the device (dashboard), you see only one icon and 6 buttons ?

What Sonois unit do you own ?

It’s probably time to check the logs looking for errors. Grep “Sonos” messages.

Yep, just playing: without anything behind it. And yes, I see the icon, and the 6 buttons, and the slider. I can move the slider also, no errotr messages.
I tried it with 4 different sonos units, the play:3, play:5, the ZP90 and the ZP120. All run the latest software.
I will try looking at the logs, but not sure which ones should give me a clue.

Let me correct that, no icon.

08 02/23/13 11:04:06.052 JobHandler_LuaUPnP::HandleActionRequest device: 44 service: urn:micasaverde-com:serviceId:MediaNavigation1 action: Play <0xac0d>
08 02/23/13 11:04:06.052 JobHandler_LuaUPnP::HandleActionRequest argument DeviceNum=44 <0xac0d>
08 02/23/13 11:04:06.053 JobHandler_LuaUPnP::HandleActionRequest argument serviceId=urn:micasaverde-com:serviceId:MediaNavigation1 <0xac0d>
08 02/23/13 11:04:06.054 JobHandler_LuaUPnP::HandleActionRequest argument action=Play <0xac0d>
08 02/23/13 11:04:06.054 JobHandler_LuaUPnP::HandleActionRequest argument rand=0.7962358780811654 <0xac0d>
01 02/23/13 11:04:06.056 LuaInterface::CallFunction_Job device 44 function SMediaNavigation1_MediaNavigation1_Play_run failed [string “…”]:917: attempt to index upvalue ‘AVTransport’ (a nil value) <0xac0d>

Same thing for other actions such as stop or set volume

edit
restarting the lua engine gives this in the log:
luup_log:44: Sonos: #44 starting up with id LEAK this:-409600 start:393216 to 0xa50000 <0x402>

What files have you uploaded in the Vera ?

I uploaded the files from trunk 102.zip. as the wiki mentions, all the files except for the …UI4.json. I copied the png files to the correct location as well. I can see all the files on my vera.

Please check that the lua file is really uploaded in the Vera. You should find in particular files named L_Sonos1.lua.lzo and S_SonosAVTransport1.xml.lzo.

You have to look for errors in logs when restarting the plugin (push button reload) because it looks like a variable is not initialized (AVTransport) while this variable is set during plugin startup.

cheers mate, I found an old L_Sonos1.lua from an old version of the plugin, apparently the .lua is called before the .lua.lzo.
Thank you very much for thinking with me, now it works like a charm :slight_smile:

New feature added: Say calls are now managed in a queue. It allows you to call several times the Say actions without waiting for the ending of the previous call. While there are calls in queue, each message is said successively without restoring the context between each message.
Please note that group zones are not correctly managed in case of two successive calls with different group zones.

New version committed (in trunk):

  • Queue management: new callback EnqueueURI + new parameter EnqueueType for callback PlayURI
  • Callbacks SavePlaybackContext and RestorePlaybackContext now respectively saves and restores the Sonos queue

You can enqueue 3 kinds of things:

  • an audio file (x-file-cifs)
  • a playlist file (x-file-cifs) containign audio files
  • a Sonos playlist

New version committed (in trunk):

  • New allowed values as EnqueueType for PlayURI and EnqueueURI: ENQUEUE_AT_FIRST, ENQUEUE_AT_NEXT_PLAY and CLEAR_QUEUE

The parameter EnqueueType for PlayURI and EnqueueURI can take one of these values (string):

  • NO_ENQUEUE: the URI is not enqueued
  • ENQUEUE: the URI is enqueued (at the end)
  • ENQUEUE_AT_FIRST: the URI is inserted at first place in the queue
  • ENQUEUE_AT_NEXT_PLAY: the URI is inserted just after the item in the queue being played; if no item is being played, the URI is enqueued at the end
  • REPLACE_QUEUE: the queue is first erased and then the URI is enqueued
  • CLEAR_QUEUE: the queue is cleared and the URI is not enqueued

@lolodomo,
I’m not clear on why we need to do this to [tt]PlayURI[/tt]. The functionality being added to it are [generally] available via discrete (and standard) UPnP calls that we also expose.

The one thing that [tt]PlayURI[/tt] offers, that isn’t generally available in the standard calls, is the ability to play a transient message.

It seems to me that we should really:

a) Split out the “Grouping” options from [tt]PlayURI()[/tt] for transient messages.
Something akin to [tt]Say()[/tt], but called something else like [tt]Alert()[/tt], with the same parameter set (but accepting an arbitrary MP3 for the Alert) would be simpler for users to comprehend for the basic functionality

b) Move [tt]PlayURI()[/tt] to it’s simple (non-grouped) model of playback.

c) Move users towards using the standard UPnP functions for all regular Queue management functions, as well as the stuff to “follow” the output of another unit.
They can use a set of them, in sequence, to achieve any compound behavior required. That’s what the UPnP control points do, so it should be possible here also

Overall I think we need to simplify stuff a little, and maybe add a few examples to show people how to perform the compound actions using sequences of UPnP calls.

The current model seems to be heading down a track of the “universal function” which seems like it’ll end up with a very large # of parameter over time, as well as potentially introduce incompatibilities across releases.

Thoughts?

[quote=“guessed, post:833, topic:169644”]Overall I think we need to simplify stuff a little, and maybe add a few examples to show people how to perform the compound actions using sequences of UPnP calls.

The current model seems to be heading down a track of the “universal function” which seems like it’ll end up with a very large # of parameter over time, as well as potentially introduce incompatibilities across releases.

Thoughts?[/quote]

Big YES from a user’s point of view!

Hi guessed.

On one side, we have all the “standard” UPnP calls, everybody can use them if they want. They have often a lot of parameters, not always very clear how to use them, what must be set in each parameter.

On another side, we have defined few functions, more high level: SavePlaybackContext, RestorePlaybackContext, PlayURI, … The aim is to make things easier for a normal user.

Note that there is no constraint to use the few high-level functions provided by the plugin.

In my opinion, a normal user will be able to manage scene through the advanced tab. But as soon as soon as luup code is required including for example XML parsing of return parameters from UPnP calls, I think we have to consider that it is not adapted to a standard user.

That’s why what I have added to manage queue is something that can help most of users, because without that, they will certainly never be able to implement the feature like enqueue+play.

The only point I agree with you is that we have to take care to not have too many parameters in our functions.

So:

1 - We can suppress the Volume parameter as the action SetVolume exists. But I liked it as I always adjust the volume at the same time I start a playback.

2 - We can suppress the “group” parameter as I don’t need it ! But it would be cool to explain to users how to manage group… That’s the perfect example of whar is not clear at all when you look at standard calls.

3 - We could suppress the type “CLEAR_QUEUE” for EnqueueType as it exists a clear call to do that.

4 - But I would like to keep the EnqueueType parameter as it allows things really not obvious to do by a standard user.

By the way, my aim is to make things easier for users, and clearly with only the “standard” actions everything is not clear. So I don’t understand where is the problem to provide low-level actions and more high-level actions if it can hep users.

Done (committed).
RemoveAllTracksFromQueue can easily be used.

I could suppress EnqueueURI action if you want: the only thing that will be difficult for a normal user is EnquieueURI + ENQUEUE_AT_NEXT_PLAY. The other enqueue types can be managed relatively easily with 1 or 2 “standard” calls to RemoveAllTracksFromQueue and AddURIToQueue with the good paramaters.

But I would like to keep EnqueueType paramater to PlayURI as it allows to play what was enqueued, something not really easy to do as the result of AddURIToQueue has to be analysed (XML parsing).

@lolodomo,
I agree on not forcing users into Lua for the simple stuff.

My comments are intended to ensure that the convenience functions that we do provide don’t get “overloaded” with long lists of complex parameters and/or conflicting ones, since that will be just as confusing as having to jump into Lua.

If you look at the core convenience functions we’re providing today, it’s basically PlayURI and Say. There are others, but these are the core of the ones that’ll be used commonly. These need to remain dead-simple.

Given their combined functions, I believe PlayURI is starting to be overloaded in a couple of areas:
a) Play functions are starting to deal with Queue management AND;
b) Potential of Play dealing with both permanent, and transient, content play

I think that something like the following could cover most of the bases:

[ul][li]MiOS.Play()[/li]
[li]Sonos1.PlayURI(uri, volume)[/li]
[li]Sonos1.Say(text, language, volume, groupDevices)[/li]
[li]Sonos1.Alert(uri, volume, groupDevices)[/li]
[li]Sonos1.Enqueue(uri, mode)[/li]
[li]Sonos1.SaveContext()[/li]
[li]Sonos1.RestoreContext()[/li][/ul]

This removes any form of queue management from the Play method. It remains simple, and has a pre-defined behavior that [hopefully] most people want.

If folks want to enqueue at a non-standard location, they’d call your Enqueue() convenience first, then the simple MiOS Play() method. Basically, they’d composite a few of these together to get the desired effect, with each “command” being extremely simple, with very few parameters.

If other conveniences are added down the line, then they’d fit this model also - new functions/actions, stuff that likely wouldn’t break existing scenes, but could be composited to achieve an effect.

In the case of transient/one-time play, we would add something like Alert(). We separate out all the functionality for “one-time-play” of something, and make it’s parameters match those of Say(). If we need to add stuff to this, like the context Save/Restore, then it can be readily done without impacting the existing Play() method (which wouldn’t deal with transient content-play)… For the most part, the Alert() function would internally use all the same queue and save/restore mechanisms as Say(), it would just source it’s content from elsewhere. It’s likely that we’d also need a “time” parameter, since we may not be able to work out how long to do it for.

Folks wanting multiple Sonos units to play in unison, for long-term play, would [effectively] do something like the following snippet.

I’ve represented it textually, but I’m intending it to mean the Advanced Scene UI.

x.AVTransport.SetAVTransportURI("x-rincon:RINCON_000E5...Y..01400") y.Sonos1.Play("SQ:Morning playlist")

It won’t be one step, but each component will have recognizable parameters, and parameter values.

For this one, we’d definitely want to expose the relevant information via the UI, so that users can find it easily (eg. the examples tab we’ve talked of before) without having to jump to doc, since the MiOS Advanced Scene pane is primitive and unforgiving.

As a side-note, for Volume, it probably works for a single Sonos unit, but once you have several of them it’s not really as viable.

This is a general issue for any of the group play items (Say, Alert) since the devices might actually need different levels. This happens, for example, when one is a Play Connect, attached to an Amp, and another is a Play 5 - they’ll be different volume levels anyhow.

Happy to leave it in, but it’s never really going to work well for multi-Sonos setups.

If a user wants just to enqueue and play what he has just enqueued, the most standard action (the “Play Now” menu item) of the Sonos control application, your scheme is not sufficient and the user will not be able to achieve this just using the advanced tab. The reason is that with the advanced tab you can only put actions in sequence with no relation between them. To achieve the basic function I describe, you need to get one of the output parameters of the AddUriToQueue action.
By the way, calling Play() after Enqueue() will not start the playback of the queue and even less the good track.
One solution would be to call PlayURI after EnqueueURI using URI “Q:n”, n being the new position in the queue, but one time again it is a data that the user cannot know except using lua code and XML parsing !

That’s why queue management requires to be attached in a same action as the play call. … if we want to give the user an access to queue properly and easily.

That being said, I realize that an enhancement would be to set the return value of EnqueueURI as the first enqueued track number. Using luup code, the user would not be constrained to do XML parsing. It would be easier.

By the way, I think I have found a solution that will be ok for you, I hope… We define PlayURI with no queue management (as before) and I add a new boolean parameter to the EnqueueURI action to let the user decide whether he wants just to enqueue or enqueue and play. Or I can do it with no additional parameter but with additional enqueue modes. Once it’s done, EnqueueURI will become the current PlayURI action.

Ok with that.

Folks wanting multiple Sonos units to play in unison, for long-term play, would [effectively] do something like the following snippet.

I’ve represented it textually, but I’m intending it to mean the Advanced Scene UI.

x.AVTransport.SetAVTransportURI("x-rincon:RINCON_000E5...Y..01400") y.Sonos1.Play("SQ:Morning playlist")

It won’t be one step, but each component will have recognizable parameters, and parameter values.

In my opinion, it is not user friendly, too much difficult,
But we could add a new action:
Sonos1.GroupZones(groupDevices)

In this case, the scene would become more clear:

x.Sonos1.GroupZones("38,45") y.Sonos1.Play("SQ:Morning playlist")