diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index f9c9c1caa0..5584361cb6 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -958,7 +958,7 @@ private: { auto vstParamID = audioProcessor->getVSTParamIDForIndex (i); auto* juceParam = audioProcessor->getParamForVSTParamID (vstParamID); - auto* parameterGroup = pluginInstance->parameterTree.getGroupsForParameter (juceParam).getLast(); + auto* parameterGroup = pluginInstance->getParameterTree().getGroupsForParameter (juceParam).getLast(); auto unitID = JuceAudioProcessor::getUnitID (parameterGroup); parameters.addParameter (new Param (*this, *juceParam, vstParamID, unitID, diff --git a/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm b/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm index 4571b1ed50..64a55f56f4 100644 --- a/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm +++ b/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm @@ -1353,7 +1353,7 @@ public: { managedParameters.clear (false); paramIDToIndex.clear(); - AudioProcessorParameterGroup parameterGroups ({}, {}, {}); + AudioProcessorParameterGroup newParameterTree; if (audioUnit != nullptr) { @@ -1471,7 +1471,7 @@ public: getClumpName(), String()); group->addChild (std::unique_ptr (parameter)); groupIDMap[info.clumpID] = group.get(); - parameterGroups.addChild (std::move (group)); + newParameterTree.addChild (std::move (group)); } else { @@ -1480,14 +1480,14 @@ public: } else { - parameterGroups.addChild (std::unique_ptr (parameter)); + newParameterTree.addChild (std::unique_ptr (parameter)); } } } } } - parameterTree.swapWith (parameterGroups); + getParameterTree() = 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 930269c646..8a10030f63 100644 --- a/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp @@ -181,15 +181,16 @@ public: inputs.clear(); outputs.clear(); managedParameters.clear (false); - AudioProcessorParameterGroup group ({}, {}, {}); - parameterTree.swapWith (group); + AudioProcessorParameterGroup parameterGroups; for (unsigned int i = 0; i < plugin->PortCount; ++i) { const auto portDesc = plugin->PortDescriptors[i]; if ((portDesc & LADSPA_PORT_CONTROL) != 0) - addParameter (new LADSPAParameter (*this, (int) i, String (plugin->PortNames[i]).trim(), (portDesc & LADSPA_PORT_INPUT) != 0)); + parameterGroups.addChild (std::make_unique (*this, (int) i, + String (plugin->PortNames[i]).trim(), + (portDesc & LADSPA_PORT_INPUT) != 0)); if ((portDesc & LADSPA_PORT_AUDIO) != 0) { @@ -198,6 +199,8 @@ public: } } + getParameterTree() = std::move (parameterGroups); + for (auto* param : getParameters()) if (auto* ladspaParam = dynamic_cast (param)) plugin->connect_port (handle, (size_t) ladspaParam->paramID, &(ladspaParam->paramValue.scaled)); diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index e6a3a736c6..f0db0188e2 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -1752,11 +1752,8 @@ public: if (! holder->initialise()) return false; - if (! isControllerInitialised) - { - if (! holder->fetchController (editController)) - return false; - } + if (! (isControllerInitialised || holder->fetchController (editController))) + return false; // (May return an error if the plugin combines the IComponent and IEditController implementations) editController->initialize (holder->host->getFUnknown()); @@ -1768,12 +1765,12 @@ public: auto configureParameters = [this] { - addParameters(); + refreshParameterList(); synchroniseStates(); syncProgramNames(); }; - configureParameters(); + configureParameters(); setupIO(); // Some plug-ins don't present their parameters until after the IO has been @@ -1785,12 +1782,11 @@ public: } void* getPlatformSpecificData() override { return holder->component; } - void refreshParameterList() override {} //============================================================================== const String getName() const override { - VST3ModuleHandle::Ptr& module = holder->module; + auto& module = holder->module; return module != nullptr ? module->name : String(); } @@ -2536,15 +2532,15 @@ private: } } - void addParameters() + void refreshParameterList() override { - AudioProcessorParameterGroup parameterGroups ({}, {}, {}); + AudioProcessorParameterGroup newParameterTree; // We're going to add parameter groups to the tree recursively in the same order as the // first parameters contained within them. std::map infoMap; std::map groupMap; - groupMap[Vst::kRootUnitId] = ¶meterGroups; + groupMap[Vst::kRootUnitId] = &newParameterTree; if (unitInfo != nullptr) { @@ -2598,7 +2594,7 @@ private: group->addChild (std::unique_ptr (param)); } - parameterTree.swapWith (parameterGroups); + getParameterTree() = std::move (newParameterTree); } void synchroniseStates() diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp index 81460cfeb8..2f5bf2a490 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp @@ -721,7 +721,7 @@ void AudioProcessor::addParameterGroup (std::unique_ptr); /** Returns the group of parameters managed by this AudioProcessor. */ - const AudioProcessorParameterGroup& getParameterTree(); + AudioProcessorParameterGroup& getParameterTree(); /** Returns the current list of parameters. */ const OwnedArray& getParameters() const noexcept; @@ -1669,7 +1669,7 @@ private: OwnedArray managedParameters; AudioProcessorParameter* getParamChecked (int) const noexcept; - AudioProcessorParameterGroup parameterTree { {}, {}, {} }; + AudioProcessorParameterGroup parameterTree; #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING BigInteger changingParams; diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp index 5468216605..692cc53759 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp @@ -27,6 +27,160 @@ namespace juce { +AudioProcessorParameterGroup::AudioProcessorParameterNode::~AudioProcessorParameterNode() = default; + +AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (AudioProcessorParameterNode&& other) + : group (std::move (other.group)), parameter (std::move (other.parameter)) +{ + if (group != nullptr) + group->parent = parent; +} + +AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (std::unique_ptr param, + AudioProcessorParameterGroup* parentGroup) + : parameter (std::move (param)), parent (parentGroup) +{} + +AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (std::unique_ptr grp, + AudioProcessorParameterGroup* parentGroup) + : group (std::move (grp)), parent (parentGroup) +{ + group->parent = parent; +} + +AudioProcessorParameterGroup* AudioProcessorParameterGroup::AudioProcessorParameterNode::getParent() const { return parent; } +AudioProcessorParameter* AudioProcessorParameterGroup::AudioProcessorParameterNode::getParameter() const { return parameter.get(); } +AudioProcessorParameterGroup* AudioProcessorParameterGroup::AudioProcessorParameterNode::getGroup() const { return group.get(); } + +//============================================================================== +AudioProcessorParameterGroup::AudioProcessorParameterGroup() = default; + +AudioProcessorParameterGroup::AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator) + : identifier (std::move (groupID)), name (std::move (groupName)), separator (std::move (subgroupSeparator)) +{ +} + +AudioProcessorParameterGroup::~AudioProcessorParameterGroup() = default; + +AudioProcessorParameterGroup::AudioProcessorParameterGroup (AudioProcessorParameterGroup&& other) + : identifier (std::move (other.identifier)), + name (std::move (other.name)), + separator (std::move (other.separator)), + children (std::move (other.children)) +{ + updateChildParentage(); +} + +AudioProcessorParameterGroup& AudioProcessorParameterGroup::operator= (AudioProcessorParameterGroup&& other) +{ + identifier = std::move (other.identifier); + name = std::move (other.name); + separator = std::move (other.separator); + children = std::move (other.children); + updateChildParentage(); + return *this; +} + +void AudioProcessorParameterGroup::updateChildParentage() +{ + for (auto* child : children) + { + child->parent = this; + + if (auto* group = child->getGroup()) + group->parent = this; + } +} + +String AudioProcessorParameterGroup::getID() const { return identifier; } +String AudioProcessorParameterGroup::getName() const { return name; } +String AudioProcessorParameterGroup::getSeparator() const { return separator; } +const AudioProcessorParameterGroup* AudioProcessorParameterGroup::getParent() const noexcept { return parent; } + +const AudioProcessorParameterGroup::AudioProcessorParameterNode** AudioProcessorParameterGroup::begin() const noexcept { return const_cast (children.begin()); } +const AudioProcessorParameterGroup::AudioProcessorParameterNode** AudioProcessorParameterGroup::end() const noexcept { return const_cast (children.end()); } + +void AudioProcessorParameterGroup::append (std::unique_ptr newParameter) +{ + children.add (new AudioProcessorParameterNode (std::move (newParameter), this)); +} + +void AudioProcessorParameterGroup::append (std::unique_ptr newSubGroup) +{ + children.add (new AudioProcessorParameterNode (std::move (newSubGroup), this)); +} + +Array AudioProcessorParameterGroup::getSubgroups (bool recursive) const +{ + Array groups; + getSubgroups (groups, recursive); + return groups; +} + +Array AudioProcessorParameterGroup::getParameters (bool recursive) const +{ + Array parameters; + getParameters (parameters, recursive); + return parameters; +} + +Array AudioProcessorParameterGroup::getGroupsForParameter (AudioProcessorParameter* parameter) const +{ + Array groups; + + if (auto* group = getGroupForParameter (parameter)) + { + while (group != this) + { + groups.insert (0, group); + group = group->getParent(); + } + } + + return groups; +} + +void AudioProcessorParameterGroup::getSubgroups (Array& previousGroups, bool recursive) const +{ + for (auto* child : children) + { + if (auto* group = child->getGroup()) + { + previousGroups.add (group); + + if (recursive) + group->getSubgroups (previousGroups, true); + } + } +} + +void AudioProcessorParameterGroup::getParameters (Array& previousParameters, bool recursive) const +{ + for (auto* child : children) + { + if (auto* parameter = child->getParameter()) + previousParameters.add (parameter); + else if (recursive) + child->getGroup()->getParameters (previousParameters, true); + } +} + +const AudioProcessorParameterGroup* AudioProcessorParameterGroup::getGroupForParameter (AudioProcessorParameter* parameter) const +{ + for (auto* child : children) + { + if (child->getParameter() == parameter) + return this; + + if (auto* group = child->getGroup()) + if (auto* foundGroup = group->getGroupForParameter (parameter)) + return foundGroup; + } + + return nullptr; +} + +//============================================================================== #if JUCE_UNIT_TESTS class ParameterGroupTests : public UnitTest diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.h b/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.h index 5258089460..082e2c6d56 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.h @@ -61,28 +61,22 @@ public: { public: //============================================================================== + AudioProcessorParameterNode (AudioProcessorParameterNode&&); + ~AudioProcessorParameterNode(); + /** Returns the parent group or nullptr if this is a top-level group. */ - AudioProcessorParameterGroup* getParent() const { return parent; } + AudioProcessorParameterGroup* getParent() const; /** Returns a pointer to a parameter if this node contains a parameter, nullptr otherwise. */ - AudioProcessorParameter* getParameter() const { return parameter.get(); } + AudioProcessorParameter* getParameter() const; /** Returns a pointer to a group if this node contains a group, nullptr otherwise. */ - AudioProcessorParameterGroup* getGroup() const { return group.get(); } + AudioProcessorParameterGroup* getGroup() const; private: //============================================================================== - AudioProcessorParameterNode (std::unique_ptr param, - AudioProcessorParameterGroup* parentGroup) - : parameter (std::move (param)), parent (parentGroup) - {} - - AudioProcessorParameterNode (std::unique_ptr grp, - AudioProcessorParameterGroup* parentGroup) - : group (std::move (grp)), parent (parentGroup) - { - group->parent = parent; - } + AudioProcessorParameterNode (std::unique_ptr, AudioProcessorParameterGroup*); + AudioProcessorParameterNode (std::unique_ptr, AudioProcessorParameterGroup*); std::unique_ptr group; std::unique_ptr parameter; @@ -94,6 +88,9 @@ public: }; //============================================================================== + /** Creates an empty AudioProcessorParameterGroup with no name or ID. */ + AudioProcessorParameterGroup(); + /** Creates an empty AudioProcessorParameterGroup. @param groupID A unique identifier for the group. Keep it basic; don't use any special @@ -105,10 +102,7 @@ public: layers of nested subgroups, but AU plug-ins cannot have any subgroups. */ - AudioProcessorParameterGroup (const String& groupID, const String& groupName, const String& subgroupSeparator) - : identifier (groupID), name (groupName), separator (subgroupSeparator) - { - } + AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator); /** Creates an AudioProcessorParameterGroup with a single child. @@ -121,9 +115,9 @@ public: layers of nested subgroups, but AU plug-ins cannot have any subgroups. @param child An AudioProcessorParameter or an AudioProcessorParameterGroup to add to the group. */ - template - AudioProcessorParameterGroup (const String& groupID, const String& groupName, const String& subgroupSeparator, - std::unique_ptr child) + template + AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator, + std::unique_ptr child) : AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator) { addChild (std::move (child)); @@ -141,47 +135,35 @@ public: @param firstChild An AudioProcessorParameter or an AudioProcessorParameterGroup to add to the group. @param remainingChildren A list of more AudioProcessorParameters or AudioProcessorParameterGroups to add to the group. */ - template - AudioProcessorParameterGroup (const String& groupID, const String& groupName, const String& subgroupSeparator, - std::unique_ptr firstChild, Args&&... remainingChildren) + template + AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator, + std::unique_ptr firstChild, Args&&... remainingChildren) : AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator, std::move (firstChild)) { addChild (std::forward (remainingChildren)...); } + AudioProcessorParameterGroup (AudioProcessorParameterGroup&&); + AudioProcessorParameterGroup& operator= (AudioProcessorParameterGroup&&); + + ~AudioProcessorParameterGroup(); + //============================================================================== /** Returns the group's ID. */ - String getID() const { return identifier; } + String getID() const; /** Returns the group's name. */ - String getName() const { return name; } + String getName() const; /** Returns the group's separator string. */ - String getSeparator() const { return separator; } + String getSeparator() const; /** Returns the parent of the group, or nullptr if this is a top-levle group. */ - const AudioProcessorParameterGroup* getParent() const noexcept { return parent; } + const AudioProcessorParameterGroup* getParent() const noexcept; //============================================================================== - const AudioProcessorParameterNode** begin() const noexcept { return children.begin(); } - const AudioProcessorParameterNode** end() const noexcept { return children.end(); } - - //============================================================================== - /** Swaps the content of this group with another. */ - void swapWith (AudioProcessorParameterGroup& other) noexcept - { - children.swapWith (other.children); - - auto refreshParentPtr = [] (AudioProcessorParameterGroup& parentGroup) - { - for (auto* child : parentGroup) - if (auto* group = child->getGroup()) - group->parent = &parentGroup; - }; - - refreshParentPtr (*this); - refreshParentPtr (other); - } + const AudioProcessorParameterNode** begin() const noexcept; + const AudioProcessorParameterNode** end() const noexcept; //============================================================================== /** Returns all subgroups of this group. @@ -189,108 +171,57 @@ public: @param recursive If this is true then this method will fetch all nested subgroups using a depth first search. */ - Array getSubgroups (bool recursive) const - { - Array groups; - getSubgroups (groups, recursive); - return groups; - } + Array getSubgroups (bool recursive) const; /** Returns all the parameters in this group. @param recursive If this is true then this method will fetch all nested parameters using a depth first search. */ - Array getParameters (bool recursive) const - { - Array parameters; - getParameters (parameters, recursive); - return parameters; - } + Array getParameters (bool recursive) const; /** Searches this group recursively for a parameter and returns a depth ordered list of the groups it belongs to. */ - Array getGroupsForParameter (AudioProcessorParameter* parameter) const - { - Array groups; - - if (auto* group = getGroupForParameter (parameter)) - { - while (group != this) - { - groups.insert (0, group); - group = group->getParent(); - } - } - - return groups; - } + Array getGroupsForParameter (AudioProcessorParameter*) const; //============================================================================== /** Adds a child to the group. */ - template - void addChild (std::unique_ptr child) + template + void addChild (std::unique_ptr child) { // If you hit a compiler error here then you are attempting to add a // child that is neither a pointer to an AudioProcessorParameterGroup // nor a pointer to an AudioProcessorParameter. - children.add (new AudioProcessorParameterNode (std::move (child), this)); + append (std::move (child)); } - /** Adds multiple children to the group. */ - template - void addChild (std::unique_ptr firstChild, Args&&... remainingChildren) + /** Adds multiple parameters or sub-groups to this group. */ + template + void addChild (std::unique_ptr firstChild, Args&&... remainingChildren) { addChild (std::move (firstChild)); addChild (std::forward (remainingChildren)...); } + #ifndef DOXYGEN + // This class now has a move operator, so if you're try to move them around, you should + // use that, or if you really need to swap two groups, just call std::swap + JUCE_DEPRECATED_WITH_BODY (void swapWith (AudioProcessorParameterGroup& other), { std::swap (*this, other); }) + #endif + private: //============================================================================== - void getSubgroups (Array& previousGroups, bool recursive) const - { - for (auto* child : children) - { - if (auto* group = child->getGroup()) - { - previousGroups.add (group); - - if (recursive) - group->getSubgroups (previousGroups, true); - } - } - } - - void getParameters (Array& previousParameters, bool recursive) const - { - for (auto* child : children) - { - if (auto* parameter = child->getParameter()) - previousParameters.add (parameter); - else if (recursive) - child->getGroup()->getParameters (previousParameters, true); - } - } - - const AudioProcessorParameterGroup* getGroupForParameter (AudioProcessorParameter* parameter) const - { - for (auto* child : children) - { - if (child->getParameter() == parameter) - return this; - - if (auto* group = child->getGroup()) - if (auto* foundGroup = group->getGroupForParameter (parameter)) - return foundGroup; - } - - return nullptr; - } + void getSubgroups (Array&, bool recursive) const; + void getParameters (Array&, bool recursive) const; + const AudioProcessorParameterGroup* getGroupForParameter (AudioProcessorParameter*) const; + void updateChildParentage(); + void append (std::unique_ptr); + void append (std::unique_ptr); //============================================================================== - const String identifier, name, separator; - OwnedArray children; + String identifier, name, separator; + OwnedArray children; AudioProcessorParameterGroup* parent = nullptr; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterGroup)