New Parameter API: potential big problems arising


#1

Hi,

i use several wrapper types for AudioProcessor, which wrap one AudioProcessor into another. With the old API-Level this was easy and no problem because of the structure of the API, like:

   float getParameter (int parameterIndex) override
   {
        	return wrappedProcessor->getParameter(parameterIndex);
   }

I guess a lot of people doing similar things, because of the “virtualness” of the methods which is some kind of “insurance” of the structure.

If new versions of plugin-wrappers use AudioProcessorParameter directly, how to deal with this situation? Removing virtual functions is fundamental breaking change.


#2

The old way of doing things will still work (albeit it will hit you with an assertion). The new way of doing this would be something like this:

class WrapperProcessor
     : public AudioProcessor
{
public:
    WrapperProcessor (AudioPluginInstance* processorToUse)
        : AudioProcessor (getBusesPropertiesFromProcessor (processorToUse)),
          plugin (processorToUse)
    {
        updateParameter();
    }
    
    //==============================================================================
    .
    .
    .
    //==============================================================================
    class AudioParameterWrapper : public AudioProcessorParameter
    {
    public:
        AudioParameterWrapper (AudioProcessorParameter& paramToWrap)
            : wrap (paramToWrap)
        {}
        
        float getValue() const override                          { return wrap.getValue();        }
        void setValue (float newValue) override                  { wrap.setValue (newValue);      }
        float getDefaultValue() const override                   { return wrap.getDefaultValue(); }
        String getName (int maxLen) const override               { return wrap.getName (maxLen);  }
        String getLabel() const override                         { return wrap.getLabel();        }
        int getNumSteps() const override                         { return wrap.getNumSteps();     }
        bool isDiscrete() const override                         { return wrap.isDiscrete();      }
        
        String getText (float v, int len) const override         { return wrap.getText (v, len);        }
        float getValueForText (const String& t) const override   { return wrap.getValueForText (t);     }
        String getCurrentValueAsText() const override            { return wrap.getCurrentValueAsText(); }
        bool isOrientationInverted() const override              { return wrap.isOrientationInverted(); }
        bool isAutomatable() const override                      { return wrap.isAutomatable(); }
        bool isMetaParameter() const override                    { return wrap.isMetaParameter(); }
        Category getCategory() const override                    { return wrap.getCategory(); }
    private:
        AudioProcessorParameter& wrap;
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioParameterWrapper)
    };
    
    void updateParameter()
    {
        auto& params = plugin->getParameters();

        for (auto* param : params)
            addParameter (new AudioParameterWrapper(*param));
    }
    
    ScopedPointer<AudioProcessor> plugin;
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WrapperProcessor)
};

Breaking Change: Hosted AudioProcessorParameter improvements
#3

That’s an awful lot of boilerplate just to forward a method… is it possible for you guys to not deprecate getParameter/setParameter so we don’t have to use the Parameter class all the time?


#4

It’s not forwarding a method.

It’s forwarding about 15 methods, and is a totally reasonable amount of boilerplate for that job.

And it’s pretty much the same amount of code you’d write if you were using the old methods to do the forwarding. I remember writing a similar wrapper class a couple of years ago for NOISE and it was much bigger than this.