Issue setting up a ComboboxAttachment with an AudioProcessorValueTreeState

Hello,

I am trying to figure out how to correctly bind a ComboBox component to an AudioProcessorValueTreeState property.

From my understanding, ComboBox items’ indexes cannot start at 0, and it seems to be an issue when connecting it to an APVTS instance, using a ComboboxAttachement.

I put together a very small project demonstrating the issue, which can be seen here:

It is a very simple plugin with a Combobox containing only three options. it is bound to the APVTS with a Combobox attachment. The issues are two fold:

  1. Option 2 can never be selected (it will automatically switch to option 3)
  2. More concerning, it seems that something goes wrong internally with the plugin, because after closing and reopening any DAW (I am able to reproduce this with both Ableton Live 10 and Logic Pro X), trying to open a project containing the plugin, or adding a new instance of the plugin to a new project will cause the DAW to crash

Any help would be greatly appreciated :slight_smile: I am developing on macOs 10.15, using Juce version 6.0.7.

Hello shortwavapp,

Here is one option (off the top of my head - hopefully I won’t make any significant mistakes). There are more ways to do this, of course.

Let’s say you want to make a plug with a filter…

You may have an editor which holds a combobox for the type of filter, which is added like so.

addAndMakeVisible(cType);
cType.addItemList(proc.getFilterTypes(), 1);
cType.setSelectedId(1, juce::dontSendNotification);

Note that the types are added from a list, which in this case comes from a function owned by the processor, which may look like this…

juce::StringArray AudioPluginAudioProcessor::getFilterTypes()
{
return {TRANS(“Lowpass”),
TRANS(“Highpass”)};
}

Now, working backwards, you can see that you need a parameter in your APVT. That may look like what is below. Note that you can use the same function to “fill the range” (not sure how else to say this) this.

auto type = std::make_uniquejuce::AudioParameterChoice(
AudioPluginAudioProcessor::prmParameter1,
TRANS(“Filter Types”),
AudioPluginAudioProcessor::getFilterTypes(),
0,
TRANS(""),
nullptr,
nullptr);

Now you can add your editor listener and attach the control to the parameter just like you would any other.

1 Like

Hi anoesisasudio;

Thanks for the quick reply ! it sounds like what you suggested could work :slight_smile: I can definitely give it a try!

However, i would like to understand why the code example i uploaded to github does not work as expected… this is the same kind of implementation I use for slider attachments, and have no issues with those :thinking:

Please let me know if you have any thoughts on this :slight_smile: I am very new to Juce, so I still have a lot to learn :sweat_smile:

Two remarks:

  • You can use the values from the AudioParameterChoice using the getAllValueStrings() method
    That method is available with all parameters btw.
  • You don’t need to set the selectedID if you added the options before the ComboBoxAttachment
    The attachment will set that (it can’t, if the options are not yet present)

The reason why the zero cannot be used as ID is, because the ComboBox uses the PopupMenu, and there ID==0 is reserved as “cancelled”.

The crash might result from incompatibilities in getStateInformation / setStateInformation. Don’t you get a Stack trace when the crash happens?
And maybe check the result from juce::ValueTree::fromXml(*xmlState) if it is valid.

1 Like

To add to something @daniel brings up here - IDs and indexes are two different numbering systems for ComboBox items, which can be confusing at first. When you call addItem on a ComboBox, you can assign the item any int ID you want (except zero, and it has to be unique), but the index is an automatically generated, zero-base count of the items.

1 Like

@daniel good point about juce::ValueTree::fromXml(*xmlState)

I will test that and get back to you :slight_smile:

Good news : it was a bug in my createParams() method; I updated it like this and now it works fine:

juce::AudioProcessorValueTreeState::ParameterLayout ComboboxBugAudioProcessor::createParams()
{
    juce::AudioProcessorValueTreeState::ParameterLayout layout;
    layout.add(std::make_unique<juce::AudioParameterInt>("LIST", "List", 1, 3, 2));
    return layout;
}

Thanks everyone!