| @@ -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, | |||
| @@ -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<AudioProcessorParameter> (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<AudioProcessorParameter> (parameter)); | |||
| newParameterTree.addChild (std::unique_ptr<AudioProcessorParameter> (parameter)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| parameterTree.swapWith (parameterGroups); | |||
| getParameterTree() = std::move (newParameterTree); | |||
| UInt32 propertySize = 0; | |||
| Boolean writable = false; | |||
| @@ -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<LADSPAParameter> (*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<LADSPAParameter*> (param)) | |||
| plugin->connect_port (handle, (size_t) ladspaParam->paramID, &(ladspaParam->paramValue.scaled)); | |||
| @@ -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<Vst::UnitID, Vst::UnitInfo> infoMap; | |||
| std::map<Vst::UnitID, AudioProcessorParameterGroup*> groupMap; | |||
| groupMap[Vst::kRootUnitId] = ¶meterGroups; | |||
| groupMap[Vst::kRootUnitId] = &newParameterTree; | |||
| if (unitInfo != nullptr) | |||
| { | |||
| @@ -2598,7 +2594,7 @@ private: | |||
| group->addChild (std::unique_ptr<AudioProcessorParameter> (param)); | |||
| } | |||
| parameterTree.swapWith (parameterGroups); | |||
| getParameterTree() = std::move (newParameterTree); | |||
| } | |||
| void synchroniseStates() | |||
| @@ -721,7 +721,7 @@ void AudioProcessor::addParameterGroup (std::unique_ptr<AudioProcessorParameterG | |||
| parameterTree.addChild (std::move (group)); | |||
| } | |||
| const AudioProcessorParameterGroup& AudioProcessor::getParameterTree() | |||
| AudioProcessorParameterGroup& AudioProcessor::getParameterTree() | |||
| { | |||
| return parameterTree; | |||
| } | |||
| @@ -1222,7 +1222,7 @@ public: | |||
| void addParameterGroup (std::unique_ptr<AudioProcessorParameterGroup>); | |||
| /** Returns the group of parameters managed by this AudioProcessor. */ | |||
| const AudioProcessorParameterGroup& getParameterTree(); | |||
| AudioProcessorParameterGroup& getParameterTree(); | |||
| /** Returns the current list of parameters. */ | |||
| const OwnedArray<AudioProcessorParameter>& getParameters() const noexcept; | |||
| @@ -1669,7 +1669,7 @@ private: | |||
| OwnedArray<AudioProcessorParameter> managedParameters; | |||
| AudioProcessorParameter* getParamChecked (int) const noexcept; | |||
| AudioProcessorParameterGroup parameterTree { {}, {}, {} }; | |||
| AudioProcessorParameterGroup parameterTree; | |||
| #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING | |||
| BigInteger changingParams; | |||
| @@ -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<AudioProcessorParameter> param, | |||
| AudioProcessorParameterGroup* parentGroup) | |||
| : parameter (std::move (param)), parent (parentGroup) | |||
| {} | |||
| AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameterGroup> 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<const AudioProcessorParameterNode**> (children.begin()); } | |||
| const AudioProcessorParameterGroup::AudioProcessorParameterNode** AudioProcessorParameterGroup::end() const noexcept { return const_cast<const AudioProcessorParameterNode**> (children.end()); } | |||
| void AudioProcessorParameterGroup::append (std::unique_ptr<AudioProcessorParameter> newParameter) | |||
| { | |||
| children.add (new AudioProcessorParameterNode (std::move (newParameter), this)); | |||
| } | |||
| void AudioProcessorParameterGroup::append (std::unique_ptr<AudioProcessorParameterGroup> newSubGroup) | |||
| { | |||
| children.add (new AudioProcessorParameterNode (std::move (newSubGroup), this)); | |||
| } | |||
| Array<const AudioProcessorParameterGroup*> AudioProcessorParameterGroup::getSubgroups (bool recursive) const | |||
| { | |||
| Array<const AudioProcessorParameterGroup*> groups; | |||
| getSubgroups (groups, recursive); | |||
| return groups; | |||
| } | |||
| Array<AudioProcessorParameter*> AudioProcessorParameterGroup::getParameters (bool recursive) const | |||
| { | |||
| Array<AudioProcessorParameter*> parameters; | |||
| getParameters (parameters, recursive); | |||
| return parameters; | |||
| } | |||
| Array<const AudioProcessorParameterGroup*> AudioProcessorParameterGroup::getGroupsForParameter (AudioProcessorParameter* parameter) const | |||
| { | |||
| Array<const AudioProcessorParameterGroup*> groups; | |||
| if (auto* group = getGroupForParameter (parameter)) | |||
| { | |||
| while (group != this) | |||
| { | |||
| groups.insert (0, group); | |||
| group = group->getParent(); | |||
| } | |||
| } | |||
| return groups; | |||
| } | |||
| void AudioProcessorParameterGroup::getSubgroups (Array<const AudioProcessorParameterGroup*>& 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<AudioProcessorParameter*>& 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 | |||
| @@ -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<AudioProcessorParameter> param, | |||
| AudioProcessorParameterGroup* parentGroup) | |||
| : parameter (std::move (param)), parent (parentGroup) | |||
| {} | |||
| AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameterGroup> grp, | |||
| AudioProcessorParameterGroup* parentGroup) | |||
| : group (std::move (grp)), parent (parentGroup) | |||
| { | |||
| group->parent = parent; | |||
| } | |||
| AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameter>, AudioProcessorParameterGroup*); | |||
| AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameterGroup>, AudioProcessorParameterGroup*); | |||
| std::unique_ptr<AudioProcessorParameterGroup> group; | |||
| std::unique_ptr<AudioProcessorParameter> 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 <typename ChildType> | |||
| AudioProcessorParameterGroup (const String& groupID, const String& groupName, const String& subgroupSeparator, | |||
| std::unique_ptr<ChildType> child) | |||
| template <typename ParameterOrGroup> | |||
| AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator, | |||
| std::unique_ptr<ParameterOrGroup> 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 <typename ChildType, typename... Args> | |||
| AudioProcessorParameterGroup (const String& groupID, const String& groupName, const String& subgroupSeparator, | |||
| std::unique_ptr<ChildType> firstChild, Args&&... remainingChildren) | |||
| template <typename ParameterOrGroup, typename... Args> | |||
| AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator, | |||
| std::unique_ptr<ParameterOrGroup> firstChild, Args&&... remainingChildren) | |||
| : AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator, std::move (firstChild)) | |||
| { | |||
| addChild (std::forward<Args> (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<const AudioProcessorParameterGroup*> getSubgroups (bool recursive) const | |||
| { | |||
| Array<const AudioProcessorParameterGroup*> groups; | |||
| getSubgroups (groups, recursive); | |||
| return groups; | |||
| } | |||
| Array<const AudioProcessorParameterGroup*> 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<AudioProcessorParameter*> getParameters (bool recursive) const | |||
| { | |||
| Array<AudioProcessorParameter*> parameters; | |||
| getParameters (parameters, recursive); | |||
| return parameters; | |||
| } | |||
| Array<AudioProcessorParameter*> getParameters (bool recursive) const; | |||
| /** Searches this group recursively for a parameter and returns a depth ordered | |||
| list of the groups it belongs to. | |||
| */ | |||
| Array<const AudioProcessorParameterGroup*> getGroupsForParameter (AudioProcessorParameter* parameter) const | |||
| { | |||
| Array<const AudioProcessorParameterGroup*> groups; | |||
| if (auto* group = getGroupForParameter (parameter)) | |||
| { | |||
| while (group != this) | |||
| { | |||
| groups.insert (0, group); | |||
| group = group->getParent(); | |||
| } | |||
| } | |||
| return groups; | |||
| } | |||
| Array<const AudioProcessorParameterGroup*> getGroupsForParameter (AudioProcessorParameter*) const; | |||
| //============================================================================== | |||
| /** Adds a child to the group. */ | |||
| template <typename ChildType> | |||
| void addChild (std::unique_ptr<ChildType> child) | |||
| template <typename ParameterOrGroup> | |||
| void addChild (std::unique_ptr<ParameterOrGroup> 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 <typename ChildType, typename... Args> | |||
| void addChild (std::unique_ptr<ChildType> firstChild, Args&&... remainingChildren) | |||
| /** Adds multiple parameters or sub-groups to this group. */ | |||
| template <typename ParameterOrGroup, typename... Args> | |||
| void addChild (std::unique_ptr<ParameterOrGroup> firstChild, Args&&... remainingChildren) | |||
| { | |||
| addChild (std::move (firstChild)); | |||
| addChild (std::forward<Args> (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<const AudioProcessorParameterGroup*>& 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<AudioProcessorParameter*>& 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<const AudioProcessorParameterGroup*>&, bool recursive) const; | |||
| void getParameters (Array<AudioProcessorParameter*>&, bool recursive) const; | |||
| const AudioProcessorParameterGroup* getGroupForParameter (AudioProcessorParameter*) const; | |||
| void updateChildParentage(); | |||
| void append (std::unique_ptr<AudioProcessorParameter>); | |||
| void append (std::unique_ptr<AudioProcessorParameterGroup>); | |||
| //============================================================================== | |||
| const String identifier, name, separator; | |||
| OwnedArray<const AudioProcessorParameterNode> children; | |||
| String identifier, name, separator; | |||
| OwnedArray<AudioProcessorParameterNode> children; | |||
| AudioProcessorParameterGroup* parent = nullptr; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterGroup) | |||