getControlParameterIndex - an elegant implementation

Hi,
I thought this might be helpful simple (imho) way to implement getControlParameterIndex

I’ve made a utility class to simplify linking betwen parameters and components.
It uses JUCEs own powerful ValueTree based elements. It encapsulates attachments from AudioProcessorValueTreeState to add property for each component.

Feel free if you got any feedback. (The nullptr boilerplate was added after initial tests showed it’s possible to get there with no valid pointer).

Interesting! For people, who doesn’t use the AudioProcessorValueTree, here is something more simple, less elegant, but effective:

    int getControlParameterIndex (Component& c) override
    {
        Component* cc= &c;
        while (cc!=nullptr)
        {
            PluginParameterAssociated* pa=dynamic_cast<PluginParameterAssociated*>(cc);
            if (pa!=nullptr)
            {
                return pa->getParameterNumber();
            };
            cc=cc->getParentComponent();
        };
        
        return -1;
    };

And Components which are assigned to a control-index, simply inherit from this class:
(You can also attach this class to parent-components, and all childs will associated with the index)

class PluginParameterAssociated
{
public:
    PluginParameterAssociated(int parameterNumber_)
    : parameterNumber(parameterNumber_)
    {};

    virtual ~PluginParameterAssociated() 
    {};

    int getParameterNumber()
    {
        return parameterNumber;
    };
 private:
    int parameterNumber;
};

@ttg Why not to simply use the setComponentID method?

When you init a component we could do something like this:

void MyClass::setupAttachment(String parameterId) {
  parameterId_ = parameterId;
  slider_.setComponentID(parameterId_);
  attachment_ = std::make_unique<SliderAttachment>(valueTreeState_, parameterId_, slider_);
}

Doing this enable us to implement getControlParameterIndex like this:

int MyEditor::getControlParameterIndex(Component& component) {
  const auto componentId = component.getComponentID();
  const auto parameter =  valueTreeState_.getParameter(componentId);
  if (parameter == nullptr || !componentId.isNotEmpty()) {
    return -1;
  }
  return parameter->getParameterIndex();
}
2 Likes

That looks nice, funny that within 2+ years the code I’ve made looks outdated to modern cpp standards :slight_smile:
(it definitely should be refined, refactored and use template to DRY it…)

still I think getProperties with a custom key for assigned component is more elegant. Might be rare, but imagine:

  • N components are assigned to 1 parameter (N:1)
  • you use findChildWithID()

It will return only one of those IDs.

I’m not sure to understand well, but from you say I think I misspoke. In the setupAttachment(String parameterId) method, the parameterId used is unique for each component. In fact I use a Constant class where I put all my parameterID for the different component.

Does it fix the issue that you stated?

Thanks for sharing this code, @DEADBEEF. There’s a lot implied in this snippet of code that I want to be sure I’m clear in parsing.

The basics
Your class “MyClass” is a Component, right? And you’re using the convention of adding an underscore to all of the MyClass member variables?

Attachments
This is the part that surprised me the most - that the attachment class here for the Component is a member of the Component itself. The APVTS tutorial shows the attachment classes being (private) members of the Editor, and I had assumed that was the necessary scope in which they needed to live.

Related: is the attachment_ member variable of MyClass in the public or private scope?

Thanks!

Hi sorry for the late reply.

Yes as you said a lot of things are implied, my bad.

MyClass is a component and the member variables have an underscore.

attachment_ is a private member variable as well the members valueTreeState_, parameterId_ and slider_

Hope it helps.

1 Like