Updating editor controls from setParameter()


#1

I’m confused about something. setParameter() is called by the host when automation occurs. In response, I want to update the controls on my editor panel.

However, when my editor controls change, I have to call setParameterNotifyingHost(), to tell the host about the change. Unfortunately, this calls setParameter(), which then updates the editor controls.

This seems inefficient: every time I move an editor control, it will be moved to where it just moved.

Is there a better way to handle this?


#2

Why? The host presumably already knows, since you are reacting to a change that it sent.

In this case, updating your interface controlds should not be triggering an event.

Ideally, since setParameter() can be called during processing, you don’t want to do much of anything there.

One possible approach is to have a buffer inside your editor class that stores the values of your parameters. When setParameter is called, it is this buffer that is updated. An asynch message is then sent to a UI updater, but no actual UI components are updated at this time.

When the UI updater is woken, it will check each of the parameters in the buffer, and if they differ from the current values for the UI components, it’ll update them. This update should not trigger a change event!

Change events should only be triggered by user interaction.

Obviously you’ll need to make the buffer a critical section, but since the filter can only write to the buffer, and the editor can only read from it, you can optimize this, and protect against deadlocks pretty easily.

The important thing is not to have your UI updating happening as a direct result of calls to setParameter() - also you should not be creating event loops as the example you describe above seems to be doing.


#3

[quote=“valley”][quote=“data”]
However, when my editor controls change, I have to call setParameterNotifyingHost(), to tell the host about the change. Unfortunately, this calls setParameter(), which then updates the editor controls.
[/quote]

Why? The host presumably already knows, since you are reacting to a change that it sent.

In this case, updating your interface controlds should not be triggering an event.
[/quote]

Hmm … actually, that’s not what’s happening though. I meant that I have to call setParameterNotifyingHost() when the user moves a slider or presses a button. But since setParameterNotifyingHost() always calls setParameter(), it updates the control again.

It’s not exactly a show-stopper; it can even serve as a sort of clamping mechanism. And the control probably isn’t getting drawn twice, since the updates come fairly close together. But it vexes me to think of the wasted cycles :wink:

I almost wish I had control classes which didn’t change their appearance at all in response to a user action. (This would separate View and Control from each other actually.) Then the second update wouldn’t be redundant.

[quote=“valley”]Ideally, since setParameter() can be called during processing, you don’t want to do much of anything there.

One possible approach is to have a buffer inside your editor class that stores the values of your parameters. When setParameter is called, it is this buffer that is updated. An asynch message is then sent to a UI updater, but no actual UI components are updated at this time.
[/quote]

Yes, that’s what I do.

I don’t do that – my change messages say which parameter was changed.


#4

I’m not sure I get the question, but two points:
You don’t need to send a change message in setParameter as far as I know. I think JAP does that for you. I havent tested automation extensivly though.

Secondly, when you update a widget because you got a change message from the filter use something like:

Slider->setValue(filter->getParameter(i), false);

That second parameter means that the slider will not send a change message.


#5

Well, i think basically the original poster is correct.

[Changing an EDITOR control widget directly MUST result in a call to setParameterNotifyingHost]

[setParameter’s value change MUST be reflected on the GUI somehow]

I’m perfectly happy to have a change message sent to the connected control in the GUI. It’s updated asynchronously so it’s not going to be a massive drain on the processing with EVERY change, and it’s only ‘one thing’ from the computer’s side of things. By that i mean, for processing, it’s not got this extended track of changes being done. Only when the user interacts with the controls directly does it do this [GUI change]->[host, setParameter!]->[change GUI]. I think that’s acceptable.

Of course, a point (i believe kraken) made previously in another thread suggests it may be a good idea to implement some kind of locking system so that setParameter is ignored when the user is currently manipulating a control anyway [this would be beneficial for when tweaking whilst automation is present]


#6

[quote=“haydxn”]Well, i think basically the original poster is correct.

[Changing an EDITOR control widget directly MUST result in a call to setParameterNotifyingHost]

[setParameter’s value change MUST be reflected on the GUI somehow]
[/quote]

Ah, vindication! :slight_smile: (But thanks to the other guys for taking an interest!) Yes, you’ve got it.

[quote=“haydxn”]I’m perfectly happy to have a change message sent to the connected
control in the GUI …[/quote]

I’ve got there almost myself, but it bugs me even so. But because of the asynchronous GUI updating, I suppose I can’t reasonably object too much.

At this point, it’s only my inner perfectionist that’s mewling, and he’s not always right anyway.

I saw that thread too.

It occurs to me that it might be worth having a look at the pickup modes used in recording systems that have fader automation (which is basically all the big ones). I don’t use those much myself, but I know Logic has an extensive set of options for handling this sort of thing, and probably others as well.

For the plugin I’m doing at the moment, though, I don’t think automation will be very popular. But that’s another story … :slight_smile:


#7

[quote=“haydxn”]Well, i think basically the original poster is correct.

[Changing an EDITOR control widget directly MUST result in a call to setParameterNotifyingHost]

[setParameter’s value change MUST be reflected on the GUI somehow]

[/quote]

To me though, what data is describing is circular:

the first point is that the host has informed the editor that a parameter has been automated.

the next point is that this requires a UI update.

the third point is (unless I’m totally misreading that post) that the UI update needs to be passed to setParameterNotifyingHost(), which it doesn’t because the update is only happening as a result of a host sent message.

In my mind, and automation message from the host should be handled like:

(in pseudo code)

if (uiComponent.value != valueFromHost) uiComponent.setValue(valueFromHost, dontTriggerAnEvent);

If the sequence is being generated by the UI itself, which seems to be how you are reading the post, then yeah, the editor calls setParameterNotifyingHost(), which in turns calls setParameter(). I don’t see that as wasteful though, because as I said originally, personally I like to have a buffer between the UI controls and setParameter() as it makes it a little easier to be thread safe.


#8

That’s the issue, for sure.

Given that your editor can be receiving calls to setParam even while the effect is busy in process(), and at the same time your user can be generating automation events on the UI surface, you’re going to end up with a little redundancy here and there to make sure that memory accesses don’t start colliding here there and everywhere.


#9

[quote=“valley”][quote=“data”]
I’ve got there almost myself, but it bugs me even so. But because of the asynchronous GUI updating, I suppose I can’t reasonably object too much.
[/quote]

That’s the issue, for sure.

Given that your editor can be receiving calls to setParam even while the effect is busy in process(), and at the same time your user can be generating automation events on the UI surface, you’re going to end up with a little redundancy here and there to make sure that memory accesses don’t start colliding here there and everywhere.[/quote]

Excellent point!

My inner perfectionist seems to have fallen silent. :slight_smile: Thanks!


#10