1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

AudioProcessorParameter: Break dependency cycle with AudioProcessor

This commit is contained in:
reuk 2025-08-07 17:07:57 +01:00
parent 96ff7a0dcb
commit da8150bb58
No known key found for this signature in database
6 changed files with 91 additions and 40 deletions

View file

@ -40,10 +40,12 @@ JUCE_BEGIN_IGNORE_DEPRECATION_WARNINGS
class LegacyAudioParameter final : public HostedAudioProcessorParameter class LegacyAudioParameter final : public HostedAudioProcessorParameter
{ {
public: public:
LegacyAudioParameter (AudioProcessor& audioProcessorToUse, int audioParameterIndex) LegacyAudioParameter (AudioProcessorParameter::Listener& listener,
AudioProcessor& audioProcessorToUse,
int audioParameterIndex)
: processor (&audioProcessorToUse)
{ {
processor = &audioProcessorToUse; setOwner (&listener);
setParameterIndex (audioParameterIndex); setParameterIndex (audioParameterIndex);
jassert (getParameterIndex() < processor->getNumParameters()); jassert (getParameterIndex() < processor->getNumParameters());
} }
@ -118,6 +120,9 @@ public:
return {}; return {};
} }
private:
AudioProcessor* processor = nullptr;
}; };
//============================================================================== //==============================================================================
@ -135,6 +140,7 @@ public:
{ {
clear(); clear();
forwarder = AudioProcessor::ParameterChangeForwarder { &audioProcessor };
legacyParamIDs = forceLegacyParamIDs; legacyParamIDs = forceLegacyParamIDs;
auto numParameters = audioProcessor.getNumParameters(); auto numParameters = audioProcessor.getNumParameters();
@ -147,7 +153,7 @@ public:
if (usingManagedParameters) if (usingManagedParameters)
return audioProcessor.getParameters()[i]; return audioProcessor.getParameters()[i];
auto newParam = std::make_unique<LegacyAudioParameter> (audioProcessor, i); auto newParam = std::make_unique<LegacyAudioParameter> (forwarder, audioProcessor, i);
auto* result = newParam.get(); auto* result = newParam.get();
ownedGroup.addChild (std::move (newParam)); ownedGroup.addChild (std::move (newParam));
@ -163,6 +169,7 @@ public:
void clear() void clear()
{ {
forwarder = AudioProcessor::ParameterChangeForwarder { nullptr };
ownedGroup = AudioProcessorParameterGroup(); ownedGroup = AudioProcessorParameterGroup();
params.clear(); params.clear();
} }
@ -211,6 +218,7 @@ private:
const AudioProcessorParameterGroup* processorGroup = nullptr; const AudioProcessorParameterGroup* processorGroup = nullptr;
AudioProcessorParameterGroup ownedGroup; AudioProcessorParameterGroup ownedGroup;
Array<AudioProcessorParameter*> params; Array<AudioProcessorParameter*> params;
AudioProcessor::ParameterChangeForwarder forwarder { nullptr };
bool legacyParamIDs = false, usingManagedParameters = false; bool legacyParamIDs = false, usingManagedParameters = false;
}; };

View file

@ -521,7 +521,7 @@ void AudioProcessor::addParameter (AudioProcessorParameter* param)
jassert (param != nullptr); jassert (param != nullptr);
parameterTree.addChild (std::unique_ptr<AudioProcessorParameter> (param)); parameterTree.addChild (std::unique_ptr<AudioProcessorParameter> (param));
param->processor = this; param->setOwner (&parameterListener);
param->setParameterIndex (flatParameterList.size()); param->setParameterIndex (flatParameterList.size());
flatParameterList.add (param); flatParameterList.add (param);
@ -539,7 +539,7 @@ void AudioProcessor::addParameterGroup (std::unique_ptr<AudioProcessorParameterG
for (int i = oldSize; i < flatParameterList.size(); ++i) for (int i = oldSize; i < flatParameterList.size(); ++i)
{ {
auto p = flatParameterList.getUnchecked (i); auto p = flatParameterList.getUnchecked (i);
p->processor = this; p->setOwner (&parameterListener);
p->setParameterIndex (i); p->setParameterIndex (i);
validateParameter (p); validateParameter (p);
@ -566,7 +566,7 @@ void AudioProcessor::setParameterTree (AudioProcessorParameterGroup&& newTree)
for (int i = 0; i < flatParameterList.size(); ++i) for (int i = 0; i < flatParameterList.size(); ++i)
{ {
auto p = flatParameterList.getUnchecked (i); auto p = flatParameterList.getUnchecked (i);
p->processor = this; p->setOwner (&parameterListener);
p->setParameterIndex (i); p->setParameterIndex (i);
validateParameter (p); validateParameter (p);
@ -1423,6 +1423,31 @@ AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const
bool AudioProcessor::canAddBus ([[maybe_unused]] bool isInput) const { return false; } bool AudioProcessor::canAddBus ([[maybe_unused]] bool isInput) const { return false; }
bool AudioProcessor::canRemoveBus ([[maybe_unused]] bool isInput) const { return false; } bool AudioProcessor::canRemoveBus ([[maybe_unused]] bool isInput) const { return false; }
//==============================================================================
void AudioProcessor::ParameterChangeForwarder::parameterValueChanged (int index, float value)
{
if (owner == nullptr)
return;
for (int i = owner->listeners.size(); --i >= 0;)
if (auto* l = owner->listeners[i])
l->audioProcessorParameterChanged (owner, index, value);
}
void AudioProcessor::ParameterChangeForwarder::parameterGestureChanged (int index, bool begin)
{
if (owner == nullptr)
return;
const auto callback = begin
? &AudioProcessorListener::audioProcessorParameterChangeGestureBegin
: &AudioProcessorListener::audioProcessorParameterChangeGestureEnd;
for (int i = owner->listeners.size(); --i >= 0;)
if (auto* l = owner->listeners[i])
(l->*callback) (owner, index);
}
JUCE_END_IGNORE_DEPRECATION_WARNINGS JUCE_END_IGNORE_DEPRECATION_WARNINGS
} // namespace juce } // namespace juce

View file

@ -1516,6 +1516,31 @@ public:
[[deprecated]] virtual bool isOutputChannelStereoPair (int index) const; [[deprecated]] virtual bool isOutputChannelStereoPair (int index) const;
/** @endcond */ /** @endcond */
/** @internal
Used to convert new-style per-parameter callbacks into old-style processor-change
callbacks.
This type will be removed in the future!
*/
class ParameterChangeForwarder : public AudioProcessorParameter::Listener
{
public:
explicit ParameterChangeForwarder (AudioProcessor* o) : owner (o) {}
ParameterChangeForwarder (const ParameterChangeForwarder& other) : owner (other.owner) {}
ParameterChangeForwarder& operator= (const ParameterChangeForwarder& other)
{
owner = other.owner;
return *this;
}
void parameterValueChanged (int, float) override;
void parameterGestureChanged (int, bool) override;
private:
AudioProcessor* owner = nullptr;
};
private: private:
//============================================================================== //==============================================================================
struct InOutChannelPair struct InOutChannelPair
@ -1588,6 +1613,8 @@ private:
AudioProcessorParameterGroup parameterTree; AudioProcessorParameterGroup parameterTree;
Array<AudioProcessorParameter*> flatParameterList; Array<AudioProcessorParameter*> flatParameterList;
ParameterChangeForwarder parameterListener { this };
AudioProcessorParameter* getParamChecked (int) const; AudioProcessorParameter* getParamChecked (int) const;
#if JUCE_DEBUG #if JUCE_DEBUG

View file

@ -36,6 +36,7 @@ namespace juce
{ {
class AudioProcessorEditorListener; class AudioProcessorEditorListener;
class AudioProcessor;
//============================================================================== //==============================================================================
/** /**

View file

@ -50,6 +50,12 @@ void AudioProcessorParameter::setParameterIndex (int index) noexcept
parameterIndex = index; parameterIndex = index;
} }
void AudioProcessorParameter::setOwner (Listener* listenerIn) noexcept
{
jassert (finalListener == nullptr);
finalListener = listenerIn;
}
void AudioProcessorParameter::setValueNotifyingHost (float newValue) void AudioProcessorParameter::setValueNotifyingHost (float newValue)
{ {
setValue (newValue); setValue (newValue);
@ -59,7 +65,7 @@ void AudioProcessorParameter::setValueNotifyingHost (float newValue)
void AudioProcessorParameter::beginChangeGesture() void AudioProcessorParameter::beginChangeGesture()
{ {
// This method can't be used until the parameter has been attached to a processor! // This method can't be used until the parameter has been attached to a processor!
jassert (processor != nullptr && parameterIndex >= 0); jassert (parameterIndex >= 0);
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING
// This means you've called beginChangeGesture twice in succession without // This means you've called beginChangeGesture twice in succession without
@ -75,20 +81,14 @@ void AudioProcessorParameter::beginChangeGesture()
if (auto* l = listeners[i]) if (auto* l = listeners[i])
l->parameterGestureChanged (getParameterIndex(), true); l->parameterGestureChanged (getParameterIndex(), true);
if (processor != nullptr && parameterIndex >= 0) if (finalListener != nullptr)
{ finalListener->parameterGestureChanged (getParameterIndex(), true);
// audioProcessorParameterChangeGestureBegin callbacks will shortly be deprecated and
// this code will be removed.
for (int i = processor->listeners.size(); --i >= 0;)
if (auto* l = processor->listeners[i])
l->audioProcessorParameterChangeGestureBegin (processor, getParameterIndex());
}
} }
void AudioProcessorParameter::endChangeGesture() void AudioProcessorParameter::endChangeGesture()
{ {
// This method can't be used until the parameter has been attached to a processor! // This method can't be used until the parameter has been attached to a processor!
jassert (processor != nullptr && parameterIndex >= 0); jassert (parameterIndex >= 0);
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING
// This means you've called endChangeGesture without having previously // This means you've called endChangeGesture without having previously
@ -104,14 +104,8 @@ void AudioProcessorParameter::endChangeGesture()
if (auto* l = listeners[i]) if (auto* l = listeners[i])
l->parameterGestureChanged (getParameterIndex(), false); l->parameterGestureChanged (getParameterIndex(), false);
if (processor != nullptr && parameterIndex >= 0) if (finalListener != nullptr)
{ finalListener->parameterGestureChanged (getParameterIndex(), false);
// audioProcessorParameterChangeGestureEnd callbacks will shortly be deprecated and
// this code will be removed.
for (int i = processor->listeners.size(); --i >= 0;)
if (auto* l = processor->listeners[i])
l->audioProcessorParameterChangeGestureEnd (processor, getParameterIndex());
}
} }
void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue) void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue)
@ -122,14 +116,8 @@ void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue
if (auto* l = listeners [i]) if (auto* l = listeners [i])
l->parameterValueChanged (getParameterIndex(), newValue); l->parameterValueChanged (getParameterIndex(), newValue);
if (processor != nullptr && parameterIndex >= 0) if (finalListener != nullptr)
{ finalListener->parameterValueChanged (getParameterIndex(), newValue);
// audioProcessorParameterChanged callbacks will shortly be deprecated and
// this code will be removed.
for (int i = processor->listeners.size(); --i >= 0;)
if (auto* l = processor->listeners[i])
l->audioProcessorParameterChanged (processor, getParameterIndex(), newValue);
}
} }
bool AudioProcessorParameter::isOrientationInverted() const { return false; } bool AudioProcessorParameter::isOrientationInverted() const { return false; }

View file

@ -35,8 +35,6 @@
namespace juce namespace juce
{ {
class AudioProcessor;
//============================================================================== //==============================================================================
/** An abstract base class for parameter objects that can be added to an /** An abstract base class for parameter objects that can be added to an
AudioProcessor. AudioProcessor.
@ -264,9 +262,9 @@ public:
/** @internal /** @internal
This should only be called by the owner of the parameter after it has been added to This should only be called by the owner of the parameter after it has been added to
a processor. Do not call this function; changing parameter indices *will* break things! a processor. Do not call this function; changing the parameter index *will* break things!
*/ */
void setParameterIndex (int index) noexcept; void setParameterIndex (int) noexcept;
//============================================================================== //==============================================================================
/** Returns the current value of the parameter as a String. /** Returns the current value of the parameter as a String.
@ -338,6 +336,12 @@ public:
virtual void parameterGestureChanged (int parameterIndex, bool gestureIsStarting) = 0; virtual void parameterGestureChanged (int parameterIndex, bool gestureIsStarting) = 0;
}; };
/** @internal
This should only be called by the owner of the parameter after it has been added to
a processor. Do not call this function; changing the owner *will* break things!
*/
void setOwner (Listener* listener) noexcept;
/** Registers a listener to receive events when the parameter's state changes. /** Registers a listener to receive events when the parameter's state changes.
If the listener is already registered, this will not register it again. If the listener is already registered, this will not register it again.
@ -355,9 +359,6 @@ public:
/** @internal */ /** @internal */
void sendValueChangedMessageToListeners (float newValue); void sendValueChangedMessageToListeners (float newValue);
/** @internal */
AudioProcessor* processor = nullptr;
/** Returns the default number of steps for a parameter. /** Returns the default number of steps for a parameter.
NOTE! This method is deprecated! It's recommended that you use NOTE! This method is deprecated! It's recommended that you use
@ -373,6 +374,7 @@ private:
int version = 0; int version = 0;
CriticalSection listenerLock; CriticalSection listenerLock;
Array<Listener*> listeners; Array<Listener*> listeners;
Listener* finalListener = nullptr;
mutable StringArray valueStrings; mutable StringArray valueStrings;
#if JUCE_DEBUG #if JUCE_DEBUG