'Best' way to update the GUI parameters?


#1

Hi,

  1. The current Plugin Demo uses a timerCallback() which regularly checks the processor variables and updates the GUI:

[code]void JuceDemoPluginAudioProcessorEditor::timerCallback()
{
JuceDemoPluginAudioProcessor* ourProcessor = getProcessor();

AudioPlayHead::CurrentPositionInfo newPos (ourProcessor->lastPosInfo);

if (lastDisplayedPosition != newPos)
    displayPositionInfo (newPos);

gainSlider->setValue (ourProcessor->gain, false);
delaySlider->setValue (ourProcessor->delay, false);

}
[/code]

  1. The previous Plugin Demo used a changeListenerCallback:

void JuceDemoPluginAudioProcessorEditor::changeListenerCallback (void* source) { // this is the filter telling us that it's changed, so we'll update our // display of the time, midi message, etc. updateParametersFromFilter(); }

notified from the processor’s setParameter function:

[code]void JuceDemoPluginAudioProcessor::setParameter (int index, float newValue)
{
//All parameters should have values in the [0,1] range! This is a standard!
jassert(newValue<=1);
jassert(newValue>=0);

if (index == 0)
{
    if (gain != newValue)
    {
        gain = newValue;

        // if this is changing the gain, broadcast a change message which
        // our editor will pick up.
        sendChangeMessage (this);
    }
}

}[/code]

My conclusions:

I understand that 1) would be the most appropriate way to update the graphical representation of variables which are written during the processor’s processBlock (e.g. VU meter) (you don’t want to update the GUI with the frame rate)

I understand that 2) should be more efficient for a parameter which is only used as an input to the processor’s processBlock (since it will probably be updated less often than the timercallback). However for an automated parameter I guess the host is probably calling setParameter at the frame rate too right?

Am I missing anything else under the hood? Do you know other interesting and safe ways to do this?


#2

both:
use a timer call-back for the vu-meter/automated updates, listeners for irregular updates.


#3

Here’s a good article on what to avoid doing in the callback / audio thread.
http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing

As long as you avoid those pitfalls, anything else should be fine.


#4

Are these still the best way to update GUIs from parameters?


#5

Yep. It’s not magic; these are still in use because they’re simple and they work.

The only real changes are to how the underlying data model works, i.e. we now have useful structures like AudioProcessorValueTreeState which can manage parameters and such for us but under the hood it’s still updated via listeners.


#6

I saw the tree state class indeed. It makes things better in terms of design, the last really ugly part is the bunch of tests in the processBlock method.
I suppose this may also be a way to do A/B comparison. The question I have would be to know if getting a child from the value tree state return a reference to it or a new tree.


#7

My current favourite way:
Summary, as Jules wrote regarding Tracktion somewhere on the forum (this was in context of project load/save in Traktion and real time values such as region fades/gain/automation etc…).
Best would be to have dupes of vars used for the read part or pointers.

AudioProcessorValueTreeState there is float*

AudioProcessorValueTreeState::getRawParameterValue	(	StringRef 	parameterID	)	const

so once linked Editor element (slider/button) updates you’re good to go since you’re reading the pointer.

For sub-components where you set parameters by setMyParameter(float newVal) I’ve simply set a juce::Value reffered to my UI Value. and a listener on changes.
so each time Value changed if call the proper setMyParameter(mValue.getValueObject())…


#8

i currently use preallocated non blocking fifo queues, and dequeue them in a ui timer callback, eventually packing multiple updates to the same “elements” together. this works pretty nicely, and avoid that you refresh all your components every callback