Best strategy for painting



Hi, I’m wondering what the best practice is for painting UI components in a plugin. I have tried using a timer to check changes of state attributes which was very responsive but was very CPU intensive (used +30% on idle), and when I remove the timer, the CPU usage is reduced but there is a delay before components are updated. Is it best to use a timer to check for updates and trigger a repaint of that component?

Looking for overview of how VST scheduling of events, repainting etc. works

You should trigger a repaint manually everytime you know something changed. Using a timer to repaint everything is a waste of ressources.


You can use AudioProcessorValueTreeState to keep track of your parameters and register attachments to it like SliderAttachment, ListboxAttachment, ButtonAttachment, etc. You can create your own attachments for custom components too.

Another method if you have your own parameter solution is to use a hashmap, where you use parameter values/ids as a key and a callback function as the value. I believe that’s somewhat similar to what the AudioProcessorValueTreeState does internally. Just be aware that you should wrap your callback like this

auto my_parameter_callback = [capture_list] (double value]  {
    MessageManager::callAsync ([capture_list, value] () { 
        //do stuff ... 

So that your GUI update process is done on the message thread.

Sidenote, that class name is annoyingly long. Were there conflicts with AudioProcessorState ?


If you go the AudioProcessorValueTreeState with Attachments route, is the GUI supposed to update controls automatically when underlying values change? Because that’s not what I’m seeing (perhaps I’m doing something wrong). Manipulating the GUI does indeed seamlessly propagate changes back into the engine, but on the flipside, changing the same parameters within the engine doesn’t seem to do anything to the GUI. In fact, changing things and then painting and/or repainting from a timer callback seems to do nothing – the attached control does not acknowledge that its underlying value has changed.


Could you be a little more specific? Some example code would help people see what’s going wrong.


CallAsync calls the new operator, so it’s better not to use that in the audio thread.