ButtonAttachment doesn't call AudioProcessorValueTreeState::Listener::parameterChanged

Hi there,
I’m still learning here so I hope that question is not dumb…

So far I’m managing all my Sliders and Comboboxes using the AudioProcessorValueTreeState as explained in this tutorial. Of course I’ve set up my AudioProcessor to inherit from AudioProcessorValueTreeState::Listener and I override the parameterChanged callback in my AudioProcessor too.
So far so good, everything works fine.

Now I’ve added a TextButton and set up a ButtonAttachment (the same way I’ve done it before with the Sliders and ComboBoxes). However, when I press the button the parameterChanged function is not called.

Why is that and how do I make this work?


The advantage of using Attachment classes is that you don’t need to inherit from a Listener class to have your Component control the parameters of the AudioProcessor.

If you still want to inherit from AudioProcessorValueTreeState::Listener and get callbacks through parameterChanged() you need to add yourself as a listener by calling addParameterListener().

Sorry, I don’t see how this answers my question… It actually raises more :wink:

If my AudioProcessor doesn’t inherit from AudioProcessorValueTreeState::Listener so I can override parameterChanged, then where would I call the function to set my parameter (e.g. setCutoff(value))? Shall I use getRawParameterValue each time the processBlock is called? That doesn’t really make sense to me neither…

At the moment my AudioProcessor inherits from AudioProcessorValueTreeState::Listener and also has an AudioProcessorValueTreeState as a class member. It passes the AudioProcessorValueTreeState by reference to the PluginEditor.
In the PluginEditor I’m using Attachments and in the AudioProcessor I’m overriding the parameterChanged function as well as using createAndAddParameter and addParameterListener. Actually I’m just doing like in the tutorial - is there a better way to do this?

Last but not least: How do I get that TextButton to work? I’ve used addParameterListener already, because that’s how it worked with Sliders and Comboboxes as well…

As it stands, the tutorial currently uses the getRawParameterValue() to retrieve a pointer that is later dereferenced in the processBlock().

As far as I know, the tutorial does not inherit from AudioProcessorValueTreeState::Listener nor does it call the addParameterListener() function.

All you need to do is, call createAndAddParameter() in the AudioProcessor and create a ButtonAttachment in the AudioProcessorEditor by passing the TextButton in the constructor.

Does that make sense?

You are right, I think I combined two tutorials somehow… Anyway, it all makes sense, thanks!
Is there any disadvantage in doing it the way I do? I kind of like the parameterChanged function because it keeps my processBlock clean…
Also I still wonder why the parameterChanged is not called when I push the button, it does so for Sliders and ComboBoxes.

Can you provide a minimal working example, maybe as a PIP? It would be much easier for us to work out what’s going on if we can reproduce the problem.

A first thing to check would be for typos when you registered the parameterListener, where you have to pass the paramID. When you use a string literal in the code, try to declare it once as static String, so you can use auto-complete and the compiler can check for typos.

@noahdayan maybe we can add in void AudioProcessorValueTreeState::addParameterListener (StringRef paramID, Listener* listener) something like else jassertfalse;, in case somebody tries to listen to an unattended paramID…

Here it is! The generated PIP wasn’t working and I’m not in the mood at the moment to get my head around that now - but the files are really small anyway. Thanks!
PluginProcessor.cpp (6.6 KB)
PluginEditor.h (1.3 KB)
PluginProcessor.h (2.5 KB)
PluginEditor.cpp (1.5 KB)

That’s a good idea about using static String! However I just checked my project and there is no typo. The example I’ve uploaded doesn’t call parameterChanged either btw
Adding else jassertfalse for detecting unattended paramIDs is still a nice idea :wink:

So the logic is, that the AudioProcessorValueTreeState calls the parameterChanged() of the processor. However you are overriding it as a private method, so the state doesn’t see this method.

Please try if it works if you move the parameterChanged() into the public scope…


(Kind of strange that it compiles though, since from a public point of view the processor is still pure abstract…)

Ok, that makes sense, however even moving the parameterChanged() function to public doesn’t invoke a callback when using a TextButton. It all works fine for Sliders and Comboboxes though, even when the function was private :face_with_raised_eyebrow:
Would you suggest that workflow in general btw? As I said, I’m still learning… I’m thinking about just using a Timer Callback instead, comparing the current value of each parameter to the one used in my AudioProcessor - that will make sure that my AudioProcessor’s parameters are the same as shown in the GUI because parameterChanged() is not comparing values but only gets called when a change happens… Am I right?

Ok, I compiled it an checked…
To get a reaction, the button should change it’s state, so it helps to set

textButton.setClickingTogglesState (true);
addAndMakeVisible (textButton);

and then you should get change messages.



Yes! That did it! Thanks a lot :slight_smile: