From ceff63fad7645475064fc088b2909473182fc626 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 22 May 2019 15:49:27 +0100 Subject: [PATCH] Moved AudioPluginInstance::refreshParameterList() into AudioProcessor. Did some refactoring of the way AudioProcessor maintains its internal flat list of parameters --- .../juce_AudioUnitPluginFormat.mm | 4 +- .../format_types/juce_LADSPAPluginFormat.cpp | 11 +- .../format_types/juce_VST3PluginFormat.cpp | 3 +- .../format_types/juce_VSTPluginFormat.cpp | 27 +- .../processors/juce_AudioPluginInstance.cpp | 2 + .../processors/juce_AudioPluginInstance.h | 9 +- .../processors/juce_AudioProcessor.cpp | 607 +++++++++--------- .../processors/juce_AudioProcessor.h | 320 ++------- .../juce_AudioProcessorParameterGroup.cpp | 6 +- 9 files changed, 386 insertions(+), 603 deletions(-) diff --git a/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm b/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm index 64a55f56f4..38fcf5cb49 100644 --- a/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm +++ b/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm @@ -1351,7 +1351,6 @@ public: void refreshParameterList() override { - managedParameters.clear (false); paramIDToIndex.clear(); AudioProcessorParameterGroup newParameterTree; @@ -1440,7 +1439,6 @@ public: isBoolean, label, (info.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0); - addParameterInternal (parameter); if (info.flags & kAudioUnitParameterFlag_HasClump) { @@ -1487,7 +1485,7 @@ public: } } - getParameterTree() = std::move (newParameterTree); + setParameterTree (std::move (newParameterTree)); UInt32 propertySize = 0; Boolean writable = false; diff --git a/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp index 8a10030f63..f96a38790a 100644 --- a/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp @@ -180,17 +180,16 @@ public: inputs.clear(); outputs.clear(); - managedParameters.clear (false); - AudioProcessorParameterGroup parameterGroups; + AudioProcessorParameterGroup newTree; for (unsigned int i = 0; i < plugin->PortCount; ++i) { const auto portDesc = plugin->PortDescriptors[i]; if ((portDesc & LADSPA_PORT_CONTROL) != 0) - parameterGroups.addChild (std::make_unique (*this, (int) i, - String (plugin->PortNames[i]).trim(), - (portDesc & LADSPA_PORT_INPUT) != 0)); + newTree.addChild (std::make_unique (*this, (int) i, + String (plugin->PortNames[i]).trim(), + (portDesc & LADSPA_PORT_INPUT) != 0)); if ((portDesc & LADSPA_PORT_AUDIO) != 0) { @@ -199,7 +198,7 @@ public: } } - getParameterTree() = std::move (parameterGroups); + setParameterTree (std::move (newTree)); for (auto* param : getParameters()) if (auto* ladspaParam = dynamic_cast (param)) diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index f0db0188e2..2ff41f85c9 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -2560,7 +2560,6 @@ private: auto* param = new VST3Parameter (*this, paramInfo.id, (paramInfo.flags & Vst::ParameterInfo::kCanAutomate) != 0); - addParameterInternal (param); if ((paramInfo.flags & Vst::ParameterInfo::kIsBypass) != 0) bypassParam = param; @@ -2594,7 +2593,7 @@ private: group->addChild (std::unique_ptr (param)); } - getParameterTree() = std::move (newParameterTree); + setParameterTree (std::move (newParameterTree)); } void synchroniseStates() diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 2b5ca8c442..81a0a9b37b 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -1006,6 +1006,16 @@ struct VSTPluginInstance : public AudioPluginInstance, if (auto* xml = vstModule->vstXml.get()) xmlInfo.reset (VSTXMLInfo::createFor (*xml)); + refreshParameterList(); + + vstSupportsBypass = (pluginCanDo ("bypass") > 0); + setRateAndBufferSizeDetails (sampleRateToUse, blockSizeToUse); + } + + void refreshParameterList() override + { + AudioProcessorParameterGroup newParameterTree; + for (int i = 0; i < vstEffect->numParams; ++i) { String paramName; @@ -1070,21 +1080,12 @@ struct VSTPluginInstance : public AudioPluginInstance, } } - addParameter (new VSTParameter (*this, - paramName, - shortParamNames, - defaultValue, - label, - isAutomatable, - isDiscrete, - numSteps, - isBoolSwitch, - parameterValueStrings, - valueType)); + newParameterTree.addChild (std::make_unique (*this, paramName, shortParamNames, defaultValue, + label, isAutomatable, isDiscrete, numSteps, + isBoolSwitch, parameterValueStrings, valueType)); } - vstSupportsBypass = (pluginCanDo ("bypass") > 0); - setRateAndBufferSizeDetails (sampleRateToUse, blockSizeToUse); + setParameterTree (std::move (newParameterTree)); } ~VSTPluginInstance() override diff --git a/modules/juce_audio_processors/processors/juce_AudioPluginInstance.cpp b/modules/juce_audio_processors/processors/juce_AudioPluginInstance.cpp index ca03292eb8..da90159e22 100644 --- a/modules/juce_audio_processors/processors/juce_AudioPluginInstance.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioPluginInstance.cpp @@ -34,6 +34,8 @@ PluginDescription AudioPluginInstance::getPluginDescription() const return desc; } +void* AudioPluginInstance::getPlatformSpecificData() { return nullptr; } + String AudioPluginInstance::getParameterID (int parameterIndex) { assertOnceOnDeprecatedMethodUse(); diff --git a/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h b/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h index 20f7466bd0..9eb8112803 100644 --- a/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h +++ b/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h @@ -63,7 +63,7 @@ public: //============================================================================== /** Fills-in the appropriate parts of this plugin description object. */ - virtual void fillInPluginDescription (PluginDescription& description) const = 0; + virtual void fillInPluginDescription (PluginDescription&) const = 0; /** Returns a PluginDescription for this plugin. This is just a convenience method to avoid calling fillInPluginDescription. @@ -74,12 +74,7 @@ public: E.g. For a VST, this value can be cast to an AEffect*. For an AudioUnit, it can be cast to an AudioUnit handle. */ - virtual void* getPlatformSpecificData() { return nullptr; } - - /** For some formats (currently AudioUnit), this forces a reload of the list of - available parameters. - */ - virtual void refreshParameterList() {} + virtual void* getPlatformSpecificData(); // Rather than using these methods you should call the corresponding methods // on the AudioProcessorParameter objects returned from getParameters(). diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp index 2f5bf2a490..4a4ab1cb77 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp @@ -60,11 +60,6 @@ AudioProcessor::~AudioProcessor() // or more parameters without having made a corresponding call to endParameterChangeGesture... jassert (changingParams.countNumberOfSetBits() == 0); #endif - - // The parameters are owned by an AudioProcessorParameterGroup, but we need - // to keep the managedParameters array populated to maintain backwards - // compatibility. - managedParameters.clearQuick (false); } //============================================================================== @@ -371,10 +366,6 @@ void AudioProcessor::setRateAndBufferSizeDetails (double newSampleRate, int newB { currentSampleRate = newSampleRate; blockSize = newBlockSize; - - #ifdef JUCE_DEBUG - checkForDupedParamIDs(); - #endif } //============================================================================== @@ -405,12 +396,12 @@ int AudioProcessor::getOffsetInBusBufferForAbsoluteChannelIndex (bool isInput, i } //============================================================================== -void AudioProcessor::setNonRealtime (const bool newNonRealtime) noexcept +void AudioProcessor::setNonRealtime (bool newNonRealtime) noexcept { nonRealtime = newNonRealtime; } -void AudioProcessor::setLatencySamples (const int newLatency) +void AudioProcessor::setLatencySamples (int newLatency) { if (latencySamples != newLatency) { @@ -419,148 +410,6 @@ void AudioProcessor::setLatencySamples (const int newLatency) } } -//============================================================================== -#if JUCE_GCC - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#elif JUCE_CLANG - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" -#elif JUCE_MSVC - #pragma warning (push, 0) - #pragma warning (disable: 4996) -#endif - -void AudioProcessor::setParameterNotifyingHost (int parameterIndex, float newValue) -{ - if (auto* param = getParameters()[parameterIndex]) - { - param->setValueNotifyingHost (newValue); - } - else if (isPositiveAndBelow (parameterIndex, getNumParameters())) - { - setParameter (parameterIndex, newValue); - sendParamChangeMessageToListeners (parameterIndex, newValue); - } -} - -void AudioProcessor::sendParamChangeMessageToListeners (int parameterIndex, float newValue) -{ - if (auto* param = getParameters()[parameterIndex]) - { - param->sendValueChangedMessageToListeners (newValue); - } - else - { - if (isPositiveAndBelow (parameterIndex, getNumParameters())) - { - for (int i = listeners.size(); --i >= 0;) - if (auto* l = getListenerLocked (i)) - l->audioProcessorParameterChanged (this, parameterIndex, newValue); - } - else - { - jassertfalse; // called with an out-of-range parameter index! - } - } -} - -void AudioProcessor::beginParameterChangeGesture (int parameterIndex) -{ - if (auto* param = getParameters()[parameterIndex]) - { - param->beginChangeGesture(); - } - else - { - if (isPositiveAndBelow (parameterIndex, getNumParameters())) - { - #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING - // This means you've called beginParameterChangeGesture twice in succession without a matching - // call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it. - jassert (! changingParams[parameterIndex]); - changingParams.setBit (parameterIndex); - #endif - - for (int i = listeners.size(); --i >= 0;) - if (auto* l = getListenerLocked (i)) - l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); - } - else - { - jassertfalse; // called with an out-of-range parameter index! - } - } -} - -void AudioProcessor::endParameterChangeGesture (int parameterIndex) -{ - if (auto* param = getParameters()[parameterIndex]) - { - param->endChangeGesture(); - } - else - { - if (isPositiveAndBelow (parameterIndex, getNumParameters())) - { - #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING - // This means you've called endParameterChangeGesture without having previously called - // beginParameterChangeGesture. That might be fine in most hosts, but better to keep the - // calls matched correctly. - jassert (changingParams[parameterIndex]); - changingParams.clearBit (parameterIndex); - #endif - - for (int i = listeners.size(); --i >= 0;) - if (auto* l = getListenerLocked (i)) - l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); - } - else - { - jassertfalse; // called with an out-of-range parameter index! - } - } -} - -String AudioProcessor::getParameterName (int index, int maximumStringLength) -{ - if (auto* p = managedParameters[index]) - return p->getName (maximumStringLength); - - return isPositiveAndBelow (index, getNumParameters()) ? getParameterName (index).substring (0, maximumStringLength) - : String(); -} - -const String AudioProcessor::getParameterText (int index) -{ - #if JUCE_DEBUG - // if you hit this, then you're probably using the old parameter control methods, - // but have forgotten to implement either of the getParameterText() methods. - jassert (! textRecursionCheck); - ScopedValueSetter sv (textRecursionCheck, true, false); - #endif - - return isPositiveAndBelow (index, getNumParameters()) ? getParameterText (index, 1024) - : String(); -} - -String AudioProcessor::getParameterText (int index, int maximumStringLength) -{ - if (auto* p = managedParameters[index]) - return p->getText (p->getValue(), maximumStringLength); - - return isPositiveAndBelow (index, getNumParameters()) ? getParameterText (index).substring (0, maximumStringLength) - : String(); -} - -#if JUCE_GCC - #pragma GCC diagnostic pop -#elif JUCE_CLANG - #pragma clang diagnostic pop -#elif JUCE_MSVC - #pragma warning (pop) -#endif - //============================================================================== AudioProcessorListener* AudioProcessor::getListenerLocked (int index) const noexcept { @@ -575,180 +424,73 @@ void AudioProcessor::updateHostDisplay() l->audioProcessorChanged (this); } -const OwnedArray& AudioProcessor::getParameters() const noexcept +const Array& AudioProcessor::getParameters() const { - return managedParameters; + if (flatParamListNeedsRebuilding) + { + flatParamListNeedsRebuilding = false; + flatParameterList = parameterTree.getParameters (true); + + #ifdef JUCE_DEBUG + StringArray usedIDs; + usedIDs.ensureStorageAllocated (flatParameterList.size()); + #endif + + int index = 0; + + for (auto& p : flatParameterList) + { + p->processor = const_cast (this); + p->parameterIndex = index++; + + #ifdef JUCE_DEBUG + if (auto* withID = dynamic_cast (p)) + usedIDs.add (withID->paramID); + #endif + } + + #ifdef JUCE_DEBUG + usedIDs.sort (false); + + // This assertion checks whether you attempted to add two or more parameters with the same ID + for (int i = 1; i < usedIDs.size(); ++i) + jassert (usedIDs[i - 1] != usedIDs[i]); + #endif + } + + return flatParameterList; } -int AudioProcessor::getNumParameters() +void AudioProcessor::addParameter (AudioProcessorParameter* param) { - return managedParameters.size(); + parameterTree.addChild (std::unique_ptr (param)); + flatParamListNeedsRebuilding = true; } -float AudioProcessor::getParameter (int index) +void AudioProcessor::addParameterGroup (std::unique_ptr group) { - if (auto* p = getParamChecked (index)) - return p->getValue(); - - return 0; + parameterTree.addChild (std::move (group)); + flatParamListNeedsRebuilding = true; } -void AudioProcessor::setParameter (int index, float newValue) +const AudioProcessorParameterGroup& AudioProcessor::getParameterTree() const { - if (auto* p = getParamChecked (index)) - p->setValue (newValue); + return parameterTree; } -float AudioProcessor::getParameterDefaultValue (int index) +void AudioProcessor::setParameterTree (AudioProcessorParameterGroup&& newTree) { - if (auto* p = managedParameters[index]) - return p->getDefaultValue(); - - return 0; + parameterTree = std::move (newTree); + flatParamListNeedsRebuilding = true; } -const String AudioProcessor::getParameterName (int index) -{ - if (auto* p = getParamChecked (index)) - return p->getName (512); - - return {}; -} - -String AudioProcessor::getParameterID (int index) -{ - // Don't use getParamChecked here, as this must also work for legacy plug-ins - if (auto* p = dynamic_cast (managedParameters[index])) - return p->paramID; - - return String (index); -} - -int AudioProcessor::getParameterNumSteps (int index) -{ - if (auto* p = managedParameters[index]) - return p->getNumSteps(); - - return AudioProcessor::getDefaultNumParameterSteps(); -} +void AudioProcessor::refreshParameterList() {} int AudioProcessor::getDefaultNumParameterSteps() noexcept { return 0x7fffffff; } -bool AudioProcessor::isParameterDiscrete (int index) const -{ - if (auto* p = managedParameters[index]) - return p->isDiscrete(); - - return false; -} - -String AudioProcessor::getParameterLabel (int index) const -{ - if (auto* p = managedParameters[index]) - return p->getLabel(); - - return {}; -} - -bool AudioProcessor::isParameterAutomatable (int index) const -{ - if (auto* p = managedParameters[index]) - return p->isAutomatable(); - - return true; -} - -bool AudioProcessor::isParameterOrientationInverted (int index) const -{ - if (auto* p = managedParameters[index]) - return p->isOrientationInverted(); - - return false; -} - -bool AudioProcessor::isMetaParameter (int index) const -{ - if (auto* p = managedParameters[index]) - return p->isMetaParameter(); - - return false; -} - -AudioProcessorParameter::Category AudioProcessor::getParameterCategory (int index) const -{ - if (auto* p = managedParameters[index]) - return p->getCategory(); - - return AudioProcessorParameter::genericParameter; -} - -AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const noexcept -{ - AudioProcessorParameter* p = managedParameters[index]; - - // If you hit this, then you're either trying to access parameters that are out-of-range, - // or you're not using addParameter and the managed parameter list, but have failed - // to override some essential virtual methods and implement them appropriately. - jassert (p != nullptr); - return p; -} - -void AudioProcessor::addParameterInternal (AudioProcessorParameter* param) -{ - param->processor = this; - param->parameterIndex = managedParameters.size(); - managedParameters.add (param); - - #ifdef JUCE_DEBUG - shouldCheckParamsForDupeIDs = true; - #endif -} - -void AudioProcessor::addParameter (AudioProcessorParameter* param) -{ - addParameterInternal (param); - parameterTree.addChild (std::unique_ptr (param)); -} - -void AudioProcessor::addParameterGroup (std::unique_ptr group) -{ - for (auto* param : group->getParameters (true)) - addParameterInternal (param); - - parameterTree.addChild (std::move (group)); -} - -AudioProcessorParameterGroup& AudioProcessor::getParameterTree() -{ - return parameterTree; -} - -#ifdef JUCE_DEBUG -void AudioProcessor::checkForDupedParamIDs() -{ - if (shouldCheckParamsForDupeIDs) - { - shouldCheckParamsForDupeIDs = false; - StringArray ids; - - for (auto p : managedParameters) - if (auto* withID = dynamic_cast (p)) - ids.add (withID->paramID); - - ids.sort (false); - - for (int i = 1; i < ids.size(); ++i) - { - // This is triggered if you have two or more parameters with the same ID! - jassert (ids[i - 1] != ids[i]); - } - } -} -#endif - void AudioProcessor::suspendProcessing (const bool shouldBeSuspended) { const ScopedLock sl (callbackLock); @@ -1422,6 +1164,259 @@ const char* AudioProcessor::getWrapperTypeDescription (AudioProcessor::WrapperTy } } +//============================================================================== +#if JUCE_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif JUCE_CLANG + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif JUCE_MSVC + #pragma warning (push, 0) + #pragma warning (disable: 4996) +#endif + +void AudioProcessor::setParameterNotifyingHost (int parameterIndex, float newValue) +{ + if (auto* param = getParameters()[parameterIndex]) + { + param->setValueNotifyingHost (newValue); + } + else if (isPositiveAndBelow (parameterIndex, getNumParameters())) + { + setParameter (parameterIndex, newValue); + sendParamChangeMessageToListeners (parameterIndex, newValue); + } +} + +void AudioProcessor::sendParamChangeMessageToListeners (int parameterIndex, float newValue) +{ + if (auto* param = getParameters()[parameterIndex]) + { + param->sendValueChangedMessageToListeners (newValue); + } + else + { + if (isPositiveAndBelow (parameterIndex, getNumParameters())) + { + for (int i = listeners.size(); --i >= 0;) + if (auto* l = getListenerLocked (i)) + l->audioProcessorParameterChanged (this, parameterIndex, newValue); + } + else + { + jassertfalse; // called with an out-of-range parameter index! + } + } +} + +void AudioProcessor::beginParameterChangeGesture (int parameterIndex) +{ + if (auto* param = getParameters()[parameterIndex]) + { + param->beginChangeGesture(); + } + else + { + if (isPositiveAndBelow (parameterIndex, getNumParameters())) + { + #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING + // This means you've called beginParameterChangeGesture twice in succession without a matching + // call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it. + jassert (! changingParams[parameterIndex]); + changingParams.setBit (parameterIndex); + #endif + + for (int i = listeners.size(); --i >= 0;) + if (auto* l = getListenerLocked (i)) + l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); + } + else + { + jassertfalse; // called with an out-of-range parameter index! + } + } +} + +void AudioProcessor::endParameterChangeGesture (int parameterIndex) +{ + if (auto* param = getParameters()[parameterIndex]) + { + param->endChangeGesture(); + } + else + { + if (isPositiveAndBelow (parameterIndex, getNumParameters())) + { + #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING + // This means you've called endParameterChangeGesture without having previously called + // beginParameterChangeGesture. That might be fine in most hosts, but better to keep the + // calls matched correctly. + jassert (changingParams[parameterIndex]); + changingParams.clearBit (parameterIndex); + #endif + + for (int i = listeners.size(); --i >= 0;) + if (auto* l = getListenerLocked (i)) + l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); + } + else + { + jassertfalse; // called with an out-of-range parameter index! + } + } +} + +String AudioProcessor::getParameterName (int index, int maximumStringLength) +{ + if (auto* p = getParameters()[index]) + return p->getName (maximumStringLength); + + return isPositiveAndBelow (index, getNumParameters()) ? getParameterName (index).substring (0, maximumStringLength) + : String(); +} + +const String AudioProcessor::getParameterText (int index) +{ + #if JUCE_DEBUG + // if you hit this, then you're probably using the old parameter control methods, + // but have forgotten to implement either of the getParameterText() methods. + jassert (! textRecursionCheck); + ScopedValueSetter sv (textRecursionCheck, true, false); + #endif + + return isPositiveAndBelow (index, getNumParameters()) ? getParameterText (index, 1024) + : String(); +} + +String AudioProcessor::getParameterText (int index, int maximumStringLength) +{ + if (auto* p = getParameters()[index]) + return p->getText (p->getValue(), maximumStringLength); + + return isPositiveAndBelow (index, getNumParameters()) ? getParameterText (index).substring (0, maximumStringLength) + : String(); +} + +int AudioProcessor::getNumParameters() +{ + return getParameters().size(); +} + +float AudioProcessor::getParameter (int index) +{ + if (auto* p = getParamChecked (index)) + return p->getValue(); + + return 0; +} + +void AudioProcessor::setParameter (int index, float newValue) +{ + if (auto* p = getParamChecked (index)) + p->setValue (newValue); +} + +float AudioProcessor::getParameterDefaultValue (int index) +{ + if (auto* p = getParameters()[index]) + return p->getDefaultValue(); + + return 0; +} + +const String AudioProcessor::getParameterName (int index) +{ + if (auto* p = getParamChecked (index)) + return p->getName (512); + + return {}; +} + +String AudioProcessor::getParameterID (int index) +{ + // Don't use getParamChecked here, as this must also work for legacy plug-ins + if (auto* p = dynamic_cast (getParameters()[index])) + return p->paramID; + + return String (index); +} + +int AudioProcessor::getParameterNumSteps (int index) +{ + if (auto* p = getParameters()[index]) + return p->getNumSteps(); + + return AudioProcessor::getDefaultNumParameterSteps(); +} + +bool AudioProcessor::isParameterDiscrete (int index) const +{ + if (auto* p = getParameters()[index]) + return p->isDiscrete(); + + return false; +} + +String AudioProcessor::getParameterLabel (int index) const +{ + if (auto* p = getParameters()[index]) + return p->getLabel(); + + return {}; +} + +bool AudioProcessor::isParameterAutomatable (int index) const +{ + if (auto* p = getParameters()[index]) + return p->isAutomatable(); + + return true; +} + +bool AudioProcessor::isParameterOrientationInverted (int index) const +{ + if (auto* p = getParameters()[index]) + return p->isOrientationInverted(); + + return false; +} + +bool AudioProcessor::isMetaParameter (int index) const +{ + if (auto* p = getParameters()[index]) + return p->isMetaParameter(); + + return false; +} + +AudioProcessorParameter::Category AudioProcessor::getParameterCategory (int index) const +{ + if (auto* p = getParameters()[index]) + return p->getCategory(); + + return AudioProcessorParameter::genericParameter; +} + +AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const +{ + auto p = getParameters()[index]; + + // If you hit this, then you're either trying to access parameters that are out-of-range, + // or you're not using addParameter and the managed parameter list, but have failed + // to override some essential virtual methods and implement them appropriately. + jassert (p != nullptr); + return p; +} + +#if JUCE_GCC + #pragma GCC diagnostic pop +#elif JUCE_CLANG + #pragma clang diagnostic pop +#elif JUCE_MSVC + #pragma warning (pop) +#endif + //============================================================================== void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) {} void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {} diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessor.h b/modules/juce_audio_processors/processors/juce_AudioProcessor.h index b8bcb8d5d7..868c0d5986 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessor.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessor.h @@ -975,95 +975,6 @@ public: AudioProcessorEditor* createEditorIfNeeded(); //============================================================================== - /** This must return the correct value immediately after the object has been - created, and mustn't change the number of parameters later. - - NOTE! This method is deprecated! It's recommended that you use the - AudioProcessorParameter class instead to manage your parameters. - */ - JUCE_DEPRECATED (virtual int getNumParameters()); - - /** Returns the name of a particular parameter. - - NOTE! This method is deprecated! It's recommended that you use the - AudioProcessorParameter class instead to manage your parameters. - */ - JUCE_DEPRECATED (virtual const String getParameterName (int parameterIndex)); - - /** Returns the ID of a particular parameter. - - The ID is used to communicate the value or mapping of a particular parameter with - the host. By default this method will simply return a string representation of - index. - - NOTE! This method is deprecated! It's recommended that you use the - AudioProcessorParameterWithID class instead to manage your parameters. - */ - JUCE_DEPRECATED (virtual String getParameterID (int index)); - - /** Called by the host to find out the value of one of the processor's parameters. - - The host will expect the value returned to be between 0 and 1.0. - - This could be called quite frequently, so try to make your code efficient. - It's also likely to be called by non-UI threads, so the code in here should - be thread-aware. - - NOTE! This method is deprecated! It's recommended that you use the - AudioProcessorParameter class instead to manage your parameters. - */ - JUCE_DEPRECATED (virtual float getParameter (int parameterIndex)); - - /** Returns the name of a parameter as a text string with a preferred maximum length. - If you want to provide customised short versions of your parameter names that - will look better in constrained spaces (e.g. the displays on hardware controller - devices or mixing desks) then you should implement this method. - If you don't override it, the default implementation will call getParameterName(int), - and truncate the result. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getName() instead. - */ - JUCE_DEPRECATED (virtual String getParameterName (int parameterIndex, int maximumStringLength)); - - /** Returns the value of a parameter as a text string. - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getText() instead. - */ - JUCE_DEPRECATED (virtual const String getParameterText (int parameterIndex)); - - /** Returns the value of a parameter as a text string with a preferred maximum length. - If you want to provide customised short versions of your parameter values that - will look better in constrained spaces (e.g. the displays on hardware controller - devices or mixing desks) then you should implement this method. - If you don't override it, the default implementation will call getParameterText(int), - and truncate the result. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getText() instead. - */ - JUCE_DEPRECATED (virtual String getParameterText (int parameterIndex, int maximumStringLength)); - - /** Returns the number of discrete steps that this parameter can represent. - - The default return value if you don't implement this method is - AudioProcessor::getDefaultNumParameterSteps(). - - If your parameter is boolean, then you may want to make this return 2. - - If you want the host to display stepped automation values, rather than a - continuous interpolation between successive values, you should ensure that - isParameterDiscrete returns true. - - The value that is returned may or may not be used, depending on the host. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getNumSteps() instead. - - @see isParameterDiscrete - */ - JUCE_DEPRECATED (virtual int getParameterNumSteps (int parameterIndex)); - /** Returns the default number of steps for a parameter. NOTE! This method is deprecated! It's recommended that you use @@ -1073,130 +984,6 @@ public: */ static int getDefaultNumParameterSteps() noexcept; - /** Returns true if the parameter should take discrete, rather than continuous - values. - - If the parameter is boolean, this should return true (with getParameterNumSteps - returning 2). - - The value that is returned may or may not be used, depending on the host. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::isDiscrete() instead. - - @see getParameterNumSteps - */ - JUCE_DEPRECATED (virtual bool isParameterDiscrete (int parameterIndex) const); - - /** Returns the default value for the parameter. - By default, this just returns 0. - The value that is returned may or may not be used, depending on the host. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getDefaultValue() instead. - */ - JUCE_DEPRECATED (virtual float getParameterDefaultValue (int parameterIndex)); - - /** Some plugin types may be able to return a label string for a - parameter's units. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getLabel() instead. - */ - JUCE_DEPRECATED (virtual String getParameterLabel (int index) const); - - /** This can be overridden to tell the host that particular parameters operate in the - reverse direction. (Not all plugin formats or hosts will actually use this information). - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::isOrientationInverted() instead. - */ - JUCE_DEPRECATED (virtual bool isParameterOrientationInverted (int index) const); - - /** The host will call this method to change the value of one of the processor's parameters. - - The host may call this at any time, including during the audio processing - callback, so the processor has to process this very fast and avoid blocking. - - If you want to set the value of a parameter internally, e.g. from your - editor component, then don't call this directly - instead, use the - setParameterNotifyingHost() method, which will also send a message to - the host telling it about the change. If the message isn't sent, the host - won't be able to automate your parameters properly. - - The value passed will be between 0 and 1.0. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::setValue() instead. - */ - JUCE_DEPRECATED (virtual void setParameter (int parameterIndex, float newValue)); - - /** Your processor can call this when it needs to change one of its parameters. - - This could happen when the editor or some other internal operation changes - a parameter. This method will call the setParameter() method to change the - value, and will then send a message to the host telling it about the change. - - Note that to make sure the host correctly handles automation, you should call - the beginParameterChangeGesture() and endParameterChangeGesture() methods to - tell the host when the user has started and stopped changing the parameter. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::setValueNotifyingHost() instead. - */ - void setParameterNotifyingHost (int parameterIndex, float newValue); - - /** Returns true if the host can automate this parameter. - By default, this returns true for all parameters. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::isAutomatable() instead. - */ - JUCE_DEPRECATED (virtual bool isParameterAutomatable (int parameterIndex) const); - - /** Should return true if this parameter is a "meta" parameter. - A meta-parameter is a parameter that changes other params. It is used - by some hosts (e.g. AudioUnit hosts). - By default this returns false. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::isMetaParameter() instead. - */ - JUCE_DEPRECATED (virtual bool isMetaParameter (int parameterIndex) const); - - /** Should return the parameter's category. - By default, this returns the "generic" category. - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::getCategory() instead. - */ - JUCE_DEPRECATED (virtual AudioProcessorParameter::Category getParameterCategory (int parameterIndex) const); - - /** Sends a signal to the host to tell it that the user is about to start changing this - parameter. - - This allows the host to know when a parameter is actively being held by the user, and - it may use this information to help it record automation. - - If you call this, it must be matched by a later call to endParameterChangeGesture(). - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::beginChangeGesture() instead. - */ - JUCE_DEPRECATED (void beginParameterChangeGesture (int parameterIndex)); - - /** Tells the host that the user has finished changing this parameter. - - This allows the host to know when a parameter is actively being held by the user, and - it may use this information to help it record automation. - - A call to this method must follow a call to beginParameterChangeGesture(). - - NOTE! This method is deprecated! It's recommended that you use - AudioProcessorParameter::endChangeGesture() instead. - */ - JUCE_DEPRECATED (void endParameterChangeGesture (int parameterIndex)); - /** The processor can call this when something (apart from a parameter value) has changed. It sends a hint to the host that something like the program, number of parameters, @@ -1222,10 +1009,21 @@ public: void addParameterGroup (std::unique_ptr); /** Returns the group of parameters managed by this AudioProcessor. */ - AudioProcessorParameterGroup& getParameterTree(); + const AudioProcessorParameterGroup& getParameterTree() const; - /** Returns the current list of parameters. */ - const OwnedArray& getParameters() const noexcept; + /** Returns the group of parameters managed by this AudioProcessor. */ + void setParameterTree (AudioProcessorParameterGroup&& newTree); + + /** A processor should implement this method so that the host can ask it to + rebuild its parameter tree. + If a plugin never changes its parameters, it's enough to create its + parameters in its constructor and do nothing in this method, but some + may want to + */ + virtual void refreshParameterList(); + + /** Returns a flat list of the parameters in the current tree. */ + const Array& getParameters() const; //============================================================================== /** Returns the number of preset programs the processor supports. @@ -1432,38 +1230,6 @@ public: */ virtual void updateTrackProperties (const TrackProperties& properties); - //============================================================================== - #ifndef DOXYGEN - /** Deprecated: use getTotalNumInputChannels instead. */ - JUCE_DEPRECATED_WITH_BODY (int getNumInputChannels() const noexcept, { return getTotalNumInputChannels(); }) - JUCE_DEPRECATED_WITH_BODY (int getNumOutputChannels() const noexcept, { return getTotalNumOutputChannels(); }) - - /** Returns a string containing a whitespace-separated list of speaker types - These functions are deprecated: use the methods provided in the AudioChannelSet - class. - */ - JUCE_DEPRECATED_WITH_BODY (const String getInputSpeakerArrangement() const noexcept, { return cachedInputSpeakerArrString; }) - JUCE_DEPRECATED_WITH_BODY (const String getOutputSpeakerArrangement() const noexcept, { return cachedOutputSpeakerArrString; }) - - /** Returns the name of one of the processor's input channels. - - These functions are deprecated: your audio processor can inform the host - on channel layouts and names via the methods in the AudioChannelSet class. - - @see getBus, Bus::getCurrentLayout, AudioChannelSet - */ - JUCE_DEPRECATED (virtual const String getInputChannelName (int channelIndex) const); - JUCE_DEPRECATED (virtual const String getOutputChannelName (int channelIndex) const); - - /** Returns true if the specified channel is part of a stereo pair with its neighbour. - - These functions are deprecated: your audio processor should specify the audio - channel pairing information by modifying the busLayout member variable in - the constructor. */ - JUCE_DEPRECATED (virtual bool isInputChannelStereoPair (int index) const); - JUCE_DEPRECATED (virtual bool isOutputChannelStereoPair (int index) const); - #endif - //============================================================================== /** Helper function that just converts an xml element into a binary blob. @@ -1601,10 +1367,44 @@ protected: /** @internal */ void sendParamChangeMessageToListeners (int parameterIndex, float newValue); -private: //============================================================================== - void addParameterInternal (AudioProcessorParameter*); + #ifndef DOXYGEN +public: + // These methods are all deprecated in favour of using AudioProcessorParameter + // and AudioProcessorParameterGroup + JUCE_DEPRECATED (virtual int getNumParameters()); + JUCE_DEPRECATED (virtual const String getParameterName (int parameterIndex)); + JUCE_DEPRECATED (virtual String getParameterID (int index)); + JUCE_DEPRECATED (virtual float getParameter (int parameterIndex)); + JUCE_DEPRECATED (virtual String getParameterName (int parameterIndex, int maximumStringLength)); + JUCE_DEPRECATED (virtual const String getParameterText (int parameterIndex)); + JUCE_DEPRECATED (virtual String getParameterText (int parameterIndex, int maximumStringLength)); + JUCE_DEPRECATED (virtual int getParameterNumSteps (int parameterIndex)); + JUCE_DEPRECATED (virtual bool isParameterDiscrete (int parameterIndex) const); + JUCE_DEPRECATED (virtual float getParameterDefaultValue (int parameterIndex)); + JUCE_DEPRECATED (virtual String getParameterLabel (int index) const); + JUCE_DEPRECATED (virtual bool isParameterOrientationInverted (int index) const); + JUCE_DEPRECATED (virtual void setParameter (int parameterIndex, float newValue)); + JUCE_DEPRECATED (virtual bool isParameterAutomatable (int parameterIndex) const); + JUCE_DEPRECATED (virtual bool isMetaParameter (int parameterIndex) const); + JUCE_DEPRECATED (virtual AudioProcessorParameter::Category getParameterCategory (int parameterIndex) const); + JUCE_DEPRECATED (void beginParameterChangeGesture (int parameterIndex)); + JUCE_DEPRECATED (void endParameterChangeGesture (int parameterIndex)); + JUCE_DEPRECATED (void setParameterNotifyingHost (int parameterIndex, float newValue)); + // These functions are deprecated: your audio processor can inform the host + // on its bus and channel layouts and names using the AudioChannelSet and various bus classes. + JUCE_DEPRECATED_WITH_BODY (int getNumInputChannels() const noexcept, { return getTotalNumInputChannels(); }) + JUCE_DEPRECATED_WITH_BODY (int getNumOutputChannels() const noexcept, { return getTotalNumOutputChannels(); }) + JUCE_DEPRECATED_WITH_BODY (const String getInputSpeakerArrangement() const noexcept, { return cachedInputSpeakerArrString; }) + JUCE_DEPRECATED_WITH_BODY (const String getOutputSpeakerArrangement() const noexcept, { return cachedOutputSpeakerArrString; }) + JUCE_DEPRECATED (virtual const String getInputChannelName (int channelIndex) const); + JUCE_DEPRECATED (virtual const String getOutputChannelName (int channelIndex) const); + JUCE_DEPRECATED (virtual bool isInputChannelStereoPair (int index) const); + JUCE_DEPRECATED (virtual bool isOutputChannelStereoPair (int index) const); + #endif + +private: //============================================================================== struct InOutChannelPair { @@ -1666,19 +1466,18 @@ private: String cachedInputSpeakerArrString, cachedOutputSpeakerArrString; int cachedTotalIns = 0, cachedTotalOuts = 0; - OwnedArray managedParameters; - AudioProcessorParameter* getParamChecked (int) const noexcept; - AudioProcessorParameterGroup parameterTree; + mutable Array flatParameterList; + mutable bool flatParamListNeedsRebuilding = true; - #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING - BigInteger changingParams; - #endif + AudioProcessorParameter* getParamChecked (int) const; #if JUCE_DEBUG + #if ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING + BigInteger changingParams; + #endif + bool textRecursionCheck = false; - bool shouldCheckParamsForDupeIDs = false; - void checkForDupedParamIDs(); #endif AudioProcessorListener* getListenerLocked (int) const noexcept; @@ -1690,11 +1489,6 @@ private: void processBypassed (AudioBuffer&, MidiBuffer&); friend class AudioProcessorParameter; - - friend class JuceVST3EditController; - friend class JuceVST3Component; - friend class VST3PluginInstance; - friend class AudioUnitPluginInstance; friend class LADSPAPluginInstance; // This method is no longer used - you can delete it from your AudioProcessor classes. diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp index 692cc53759..01c1238b61 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp @@ -268,10 +268,10 @@ public: } g1->addChild (std::make_unique ("g6", "g6", " | ", - std::make_unique ("p11", "p11", NormalisableRange (0.0f, 2.0f), 0.5f), + std::make_unique ("p13", "p13", NormalisableRange (0.0f, 2.0f), 0.5f), std::make_unique ("g7", "g7", " | ", - std::make_unique ("p12", "p12", NormalisableRange (0.0f, 2.0f), 0.5f)), - std::make_unique ("p13", "p13", NormalisableRange (0.0f, 2.0f), 0.5f))); + std::make_unique ("p14", "p14", NormalisableRange (0.0f, 2.0f), 0.5f)), + std::make_unique ("p15", "p15", NormalisableRange (0.0f, 2.0f), 0.5f))); TestAudioProcessor processor;