1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +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
{
public:
LegacyAudioParameter (AudioProcessor& audioProcessorToUse, int audioParameterIndex)
LegacyAudioParameter (AudioProcessorParameter::Listener& listener,
AudioProcessor& audioProcessorToUse,
int audioParameterIndex)
: processor (&audioProcessorToUse)
{
processor = &audioProcessorToUse;
setOwner (&listener);
setParameterIndex (audioParameterIndex);
jassert (getParameterIndex() < processor->getNumParameters());
}
@ -118,6 +120,9 @@ public:
return {};
}
private:
AudioProcessor* processor = nullptr;
};
//==============================================================================
@ -135,6 +140,7 @@ public:
{
clear();
forwarder = AudioProcessor::ParameterChangeForwarder { &audioProcessor };
legacyParamIDs = forceLegacyParamIDs;
auto numParameters = audioProcessor.getNumParameters();
@ -147,7 +153,7 @@ public:
if (usingManagedParameters)
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();
ownedGroup.addChild (std::move (newParam));
@ -163,6 +169,7 @@ public:
void clear()
{
forwarder = AudioProcessor::ParameterChangeForwarder { nullptr };
ownedGroup = AudioProcessorParameterGroup();
params.clear();
}
@ -211,6 +218,7 @@ private:
const AudioProcessorParameterGroup* processorGroup = nullptr;
AudioProcessorParameterGroup ownedGroup;
Array<AudioProcessorParameter*> params;
AudioProcessor::ParameterChangeForwarder forwarder { nullptr };
bool legacyParamIDs = false, usingManagedParameters = false;
};

View file

@ -521,7 +521,7 @@ void AudioProcessor::addParameter (AudioProcessorParameter* param)
jassert (param != nullptr);
parameterTree.addChild (std::unique_ptr<AudioProcessorParameter> (param));
param->processor = this;
param->setOwner (&parameterListener);
param->setParameterIndex (flatParameterList.size());
flatParameterList.add (param);
@ -539,7 +539,7 @@ void AudioProcessor::addParameterGroup (std::unique_ptr<AudioProcessorParameterG
for (int i = oldSize; i < flatParameterList.size(); ++i)
{
auto p = flatParameterList.getUnchecked (i);
p->processor = this;
p->setOwner (&parameterListener);
p->setParameterIndex (i);
validateParameter (p);
@ -566,7 +566,7 @@ void AudioProcessor::setParameterTree (AudioProcessorParameterGroup&& newTree)
for (int i = 0; i < flatParameterList.size(); ++i)
{
auto p = flatParameterList.getUnchecked (i);
p->processor = this;
p->setOwner (&parameterListener);
p->setParameterIndex (i);
validateParameter (p);
@ -1423,6 +1423,31 @@ AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const
bool AudioProcessor::canAddBus ([[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
} // namespace juce

View file

@ -1516,6 +1516,31 @@ public:
[[deprecated]] virtual bool isOutputChannelStereoPair (int index) const;
/** @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:
//==============================================================================
struct InOutChannelPair
@ -1588,6 +1613,8 @@ private:
AudioProcessorParameterGroup parameterTree;
Array<AudioProcessorParameter*> flatParameterList;
ParameterChangeForwarder parameterListener { this };
AudioProcessorParameter* getParamChecked (int) const;
#if JUCE_DEBUG

View file

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

View file

@ -50,6 +50,12 @@ void AudioProcessorParameter::setParameterIndex (int index) noexcept
parameterIndex = index;
}
void AudioProcessorParameter::setOwner (Listener* listenerIn) noexcept
{
jassert (finalListener == nullptr);
finalListener = listenerIn;
}
void AudioProcessorParameter::setValueNotifyingHost (float newValue)
{
setValue (newValue);
@ -59,7 +65,7 @@ void AudioProcessorParameter::setValueNotifyingHost (float newValue)
void AudioProcessorParameter::beginChangeGesture()
{
// 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
// This means you've called beginChangeGesture twice in succession without
@ -75,20 +81,14 @@ void AudioProcessorParameter::beginChangeGesture()
if (auto* l = listeners[i])
l->parameterGestureChanged (getParameterIndex(), true);
if (processor != nullptr && parameterIndex >= 0)
{
// 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());
}
if (finalListener != nullptr)
finalListener->parameterGestureChanged (getParameterIndex(), true);
}
void AudioProcessorParameter::endChangeGesture()
{
// 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
// This means you've called endChangeGesture without having previously
@ -104,14 +104,8 @@ void AudioProcessorParameter::endChangeGesture()
if (auto* l = listeners[i])
l->parameterGestureChanged (getParameterIndex(), false);
if (processor != nullptr && parameterIndex >= 0)
{
// 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());
}
if (finalListener != nullptr)
finalListener->parameterGestureChanged (getParameterIndex(), false);
}
void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue)
@ -122,14 +116,8 @@ void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue
if (auto* l = listeners [i])
l->parameterValueChanged (getParameterIndex(), newValue);
if (processor != nullptr && parameterIndex >= 0)
{
// 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);
}
if (finalListener != nullptr)
finalListener->parameterValueChanged (getParameterIndex(), newValue);
}
bool AudioProcessorParameter::isOrientationInverted() const { return false; }

View file

@ -35,8 +35,6 @@
namespace juce
{
class AudioProcessor;
//==============================================================================
/** An abstract base class for parameter objects that can be added to an
AudioProcessor.
@ -264,9 +262,9 @@ public:
/** @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 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.
@ -338,6 +336,12 @@ public:
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.
If the listener is already registered, this will not register it again.
@ -355,9 +359,6 @@ public:
/** @internal */
void sendValueChangedMessageToListeners (float newValue);
/** @internal */
AudioProcessor* processor = nullptr;
/** Returns the default number of steps for a parameter.
NOTE! This method is deprecated! It's recommended that you use
@ -373,6 +374,7 @@ private:
int version = 0;
CriticalSection listenerLock;
Array<Listener*> listeners;
Listener* finalListener = nullptr;
mutable StringArray valueStrings;
#if JUCE_DEBUG