'Best' way to update the GUI parameters?


  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);


  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!

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);


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?

1 Like

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

Here’s a good article on what to avoid doing in the callback / audio thread.

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

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

1 Like

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.

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.

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())…

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

Mind sharing an example of this? How does one go about pre-allocating and passing the FIFO to the timer constructor and callback? Samples of the timer class and the caller’s instantiation would be great.

nothing really fancy. get your mpsc lockfree fifo ready and big enough to take some parameter change id, then from processBuffer you enqueue the ids of parameters that change from audio thread (and potentially any other thread). then in your timer you poll the fifo and dequeue until empty (or until a certain amount of time elapsed to avoid the audio thread to potentially prevent getting it empty), batch together the same ids if you receive them multiple times and fire off widget updates to those parameter ids. i also poll the fifo in a way that if i don’t get changes i keep the timer lazy, until i get a set of parameter changes then i start polling more frequently using a shorter timer interval.


Thank you. C++ question: I’m having trouble passing to the timer constructor, a reference to the fifo, and storing it correctly, so that it remains valid in the callback. How does one do that? I’m confused by the combination of object allocation, lifetime, scope, multithreading, and refs vs ptrs.

@JuceUser1980 the Timer class is best used as interface, i.e. inherited additionally to the class holding your fifo. That way you have access to all members of your fifo in the callback and the lifetime is bound to the lifetime of the fifo.

class MyClassHoldingFifo : public WhatEverYouInherit, private Timer
        startTimer (10);
    void timerCallback() override
        // ...

Thank you Daniel, very helpful.