upgrade to JUCE 5.4.3. Remove (probably) unused JUCE modules. Remove VST2 target (it's been end-of-life'd by Steinberg and by JUCE)
This commit is contained in:
@ -41,7 +41,7 @@ String AudioPluginInstance::getParameterID (int parameterIndex)
|
||||
// Currently there is no corresponding method available in the
|
||||
// AudioProcessorParameter class, and the previous behaviour of JUCE's
|
||||
// plug-in hosting code simply returns a string version of the index; to
|
||||
// maintain backwards compatibilty you should perform the operation below
|
||||
// maintain backwards compatibility you should perform the operation below
|
||||
// this comment. However the caveat is that for plug-ins which change their
|
||||
// number of parameters dynamically at runtime you cannot rely upon the
|
||||
// returned parameter ID mapping to the correct parameter. A comprehensive
|
||||
@ -175,7 +175,7 @@ bool AudioPluginInstance::isMetaParameter (int parameterIndex) const
|
||||
if (auto* param = getParameters()[parameterIndex])
|
||||
return param->isMetaParameter();
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioProcessorParameter::Category AudioPluginInstance::getParameterCategory (int parameterIndex) const
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
Make sure that you delete any UI components that belong to this plugin before
|
||||
deleting the plugin.
|
||||
*/
|
||||
virtual ~AudioPluginInstance() {}
|
||||
~AudioPluginInstance() override = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Fills-in the appropriate parts of this plugin description object. */
|
||||
@ -110,15 +110,15 @@ protected:
|
||||
struct Parameter : public AudioProcessorParameter
|
||||
{
|
||||
Parameter();
|
||||
virtual ~Parameter();
|
||||
~Parameter() override;
|
||||
|
||||
virtual String getText (float value, int maximumStringLength) const override;
|
||||
virtual float getValueForText (const String& text) const override;
|
||||
String getText (float value, int maximumStringLength) const override;
|
||||
float getValueForText (const String& text) const override;
|
||||
|
||||
StringArray onStrings, offStrings;
|
||||
};
|
||||
|
||||
AudioPluginInstance() {}
|
||||
AudioPluginInstance() = default;
|
||||
AudioPluginInstance (const BusesProperties& ioLayouts) : AudioProcessor (ioLayouts) {}
|
||||
template <int numLayouts>
|
||||
AudioPluginInstance (const short channelLayoutList[numLayouts][2]) : AudioProcessor (channelLayoutList) {}
|
||||
|
@ -60,6 +60,11 @@ 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);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@ -691,17 +696,36 @@ AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const noexc
|
||||
return p;
|
||||
}
|
||||
|
||||
void AudioProcessor::addParameter (AudioProcessorParameter* p)
|
||||
void AudioProcessor::addParameterInternal (AudioProcessorParameter* param)
|
||||
{
|
||||
p->processor = this;
|
||||
p->parameterIndex = managedParameters.size();
|
||||
managedParameters.add (p);
|
||||
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<AudioProcessorParameter> (param));
|
||||
}
|
||||
|
||||
void AudioProcessor::addParameterGroup (std::unique_ptr<AudioProcessorParameterGroup> group)
|
||||
{
|
||||
for (auto* param : group->getParameters (true))
|
||||
addParameterInternal (param);
|
||||
|
||||
parameterTree.addChild (std::move (group));
|
||||
}
|
||||
|
||||
const AudioProcessorParameterGroup& AudioProcessor::getParameterTree()
|
||||
{
|
||||
return parameterTree;
|
||||
}
|
||||
|
||||
#ifdef JUCE_DEBUG
|
||||
void AudioProcessor::checkForDupedParamIDs()
|
||||
{
|
||||
@ -1374,6 +1398,24 @@ int32 AudioProcessor::getAAXPluginIDForMainBusConfig (const AudioChannelSet& mai
|
||||
return (idForAudioSuite ? 0x6a796161 /* 'jyaa' */ : 0x6a636161 /* 'jcaa' */) + uniqueFormatId;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const char* AudioProcessor::getWrapperTypeDescription (AudioProcessor::WrapperType type) noexcept
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AudioProcessor::wrapperType_Undefined: return "Undefined";
|
||||
case AudioProcessor::wrapperType_VST: return "VST";
|
||||
case AudioProcessor::wrapperType_VST3: return "VST3";
|
||||
case AudioProcessor::wrapperType_AudioUnit: return "AU";
|
||||
case AudioProcessor::wrapperType_AudioUnitv3: return "AUv3";
|
||||
case AudioProcessor::wrapperType_RTAS: return "RTAS";
|
||||
case AudioProcessor::wrapperType_AAX: return "AAX";
|
||||
case AudioProcessor::wrapperType_Standalone: return "Standalone";
|
||||
case AudioProcessor::wrapperType_Unity: return "Unity";
|
||||
default: jassertfalse; return {};
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) {}
|
||||
void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {}
|
||||
|
@ -412,8 +412,8 @@ public:
|
||||
@param currentLayout If non-null, pretend that the current layout of the AudioProcessor is
|
||||
currentLayout. On exit, currentLayout will be modified to
|
||||
to represent the buses layouts of the AudioProcessor as if the layout
|
||||
of the reciever had been succesfully changed. This is useful as changing
|
||||
the layout of the reciever may change the bus layout of other buses.
|
||||
of the receiver had been successfully changed. This is useful as changing
|
||||
the layout of the receiver may change the bus layout of other buses.
|
||||
|
||||
@see AudioChannelSet
|
||||
*/
|
||||
@ -898,7 +898,7 @@ public:
|
||||
/** Returns the parameter that controls the AudioProcessor's bypass state.
|
||||
|
||||
If this method returns a nullptr then you can still control the bypass by
|
||||
calling processBlockBypassed instaed of processBlock. On the other hand,
|
||||
calling processBlockBypassed instead of processBlock. On the other hand,
|
||||
if this method returns a non-null value, you should never call
|
||||
processBlockBypassed but use the returned parameter to conrol the bypass
|
||||
state instead.
|
||||
@ -1205,12 +1205,25 @@ public:
|
||||
void updateHostDisplay();
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a parameter to the list.
|
||||
The parameter object will be managed and deleted automatically by the list
|
||||
when no longer needed.
|
||||
/** Adds a parameter to the AudioProcessor.
|
||||
|
||||
The parameter object will be managed and deleted automatically by the
|
||||
AudioProcessor when no longer needed.
|
||||
*/
|
||||
void addParameter (AudioProcessorParameter*);
|
||||
|
||||
/** Adds a group of parameters to the AudioProcessor.
|
||||
|
||||
All the parameter objects contained within the group will be managed and
|
||||
deleted automatically by the AudioProcessor when no longer needed.
|
||||
|
||||
@see addParameter
|
||||
*/
|
||||
void addParameterGroup (std::unique_ptr<AudioProcessorParameterGroup>);
|
||||
|
||||
/** Returns the group of parameters managed by this AudioProcessor. */
|
||||
const AudioProcessorParameterGroup& getParameterTree();
|
||||
|
||||
/** Returns the current list of parameters. */
|
||||
const OwnedArray<AudioProcessorParameter>& getParameters() const noexcept;
|
||||
|
||||
@ -1338,6 +1351,34 @@ public:
|
||||
const AudioChannelSet& mainOutputLayout,
|
||||
bool idForAudioSuite) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Some plug-ins support sharing response curve data with the host so that it can
|
||||
display this curve on a console or in the mixer panel. For example, ProTools
|
||||
allows you to see the total EQ curve of a track. It does this by interrogating
|
||||
each plug-in for their internal EQ curve. */
|
||||
struct CurveData
|
||||
{
|
||||
enum class Type : int
|
||||
{
|
||||
EQ, // an EQ curve - input is in Hz, output is in dB
|
||||
Dynamics, // a dynamics curve - input and output is in dB
|
||||
GainReduction, // a gain reduction curve - input and output is in dB
|
||||
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
std::function<float (float)> curve; // a function which represents your curve (such as an eq)
|
||||
Range<float> xRange, yRange; // the data range of your curve
|
||||
|
||||
// For some curve types, your plug-in may already measure the current input and output values.
|
||||
// An host can use to indicate where on the curve the current signal is (for example
|
||||
// by putting a dot on the curve). Simply leave these strings empty if you do not want to
|
||||
// support this.
|
||||
String xMeterID, yMeterID;
|
||||
};
|
||||
|
||||
virtual CurveData getResponseCurve (CurveData::Type /*curveType*/) const { return {}; }
|
||||
|
||||
//==============================================================================
|
||||
/** Not for public use - this is called before deleting an editor component. */
|
||||
void editorBeingDeleted (AudioProcessorEditor*) noexcept;
|
||||
@ -1352,7 +1393,8 @@ public:
|
||||
wrapperType_AudioUnitv3,
|
||||
wrapperType_RTAS,
|
||||
wrapperType_AAX,
|
||||
wrapperType_Standalone
|
||||
wrapperType_Standalone,
|
||||
wrapperType_Unity
|
||||
};
|
||||
|
||||
/** When loaded by a plugin wrapper, this flag will be set to indicate the type
|
||||
@ -1360,6 +1402,10 @@ public:
|
||||
*/
|
||||
WrapperType wrapperType;
|
||||
|
||||
/** Returns a textual description of a WrapperType value */
|
||||
static const char* getWrapperTypeDescription (AudioProcessor::WrapperType) noexcept;
|
||||
|
||||
|
||||
/** A struct containing information about the DAW track inside which your
|
||||
AudioProcessor is loaded. */
|
||||
struct TrackProperties
|
||||
@ -1526,7 +1572,7 @@ protected:
|
||||
|
||||
When adding a bus, isAddingBuses will be true and the plug-in is
|
||||
expected to fill out outNewBusProperties with the properties of the
|
||||
bus which will be created just after the succesful return of this callback.
|
||||
bus which will be created just after the successful return of this callback.
|
||||
|
||||
Implementations of AudioProcessor will rarely need to override this
|
||||
method. Only override this method if your processor supports adding
|
||||
@ -1551,22 +1597,23 @@ protected:
|
||||
void sendParamChangeMessageToListeners (int parameterIndex, float newValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void addParameterInternal (AudioProcessorParameter*);
|
||||
|
||||
//==============================================================================
|
||||
struct InOutChannelPair
|
||||
{
|
||||
int16 inChannels = 0, outChannels = 0;
|
||||
InOutChannelPair() = default;
|
||||
|
||||
InOutChannelPair() noexcept {}
|
||||
InOutChannelPair (const InOutChannelPair& o) noexcept : inChannels (o.inChannels), outChannels (o.outChannels) {}
|
||||
InOutChannelPair (int16 inCh, int16 outCh) noexcept : inChannels (inCh), outChannels (outCh) {}
|
||||
InOutChannelPair (const int16 (&config)[2]) noexcept : inChannels (config[0]), outChannels (config[1]) {}
|
||||
|
||||
InOutChannelPair& operator= (const InOutChannelPair& o) noexcept { inChannels = o.inChannels; outChannels = o.outChannels; return *this; }
|
||||
|
||||
bool operator== (const InOutChannelPair& other) const noexcept
|
||||
{
|
||||
return other.inChannels == inChannels && other.outChannels == outChannels;
|
||||
}
|
||||
|
||||
int16 inChannels = 0, outChannels = 0;
|
||||
};
|
||||
|
||||
template <int numLayouts>
|
||||
@ -1617,6 +1664,8 @@ private:
|
||||
OwnedArray<AudioProcessorParameter> managedParameters;
|
||||
AudioProcessorParameter* getParamChecked (int) const noexcept;
|
||||
|
||||
AudioProcessorParameterGroup parameterTree { {}, {}, {} };
|
||||
|
||||
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING
|
||||
BigInteger changingParams;
|
||||
#endif
|
||||
@ -1640,6 +1689,7 @@ private:
|
||||
|
||||
friend class JuceVST3EditController;
|
||||
friend class JuceVST3Component;
|
||||
friend class VST3PluginInstance;
|
||||
friend class AudioUnitPluginInstance;
|
||||
friend class LADSPAPluginInstance;
|
||||
|
||||
|
@ -88,18 +88,13 @@ void AudioProcessorEditor::setResizable (const bool shouldBeResizable, const boo
|
||||
{
|
||||
resizable = shouldBeResizable;
|
||||
|
||||
if (! resizable)
|
||||
if (! resizable && constrainer == &defaultConstrainer)
|
||||
{
|
||||
setConstrainer (&defaultConstrainer);
|
||||
auto width = getWidth();
|
||||
auto height = getHeight();
|
||||
|
||||
if (auto w = getWidth())
|
||||
{
|
||||
if (auto h = getHeight())
|
||||
{
|
||||
defaultConstrainer.setSizeLimits (w, h, w, h);
|
||||
resized();
|
||||
}
|
||||
}
|
||||
if (width > 0 && height > 0)
|
||||
defaultConstrainer.setSizeLimits (width, height, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +141,10 @@ void AudioProcessorEditor::setConstrainer (ComponentBoundsConstrainer* newConstr
|
||||
{
|
||||
if (constrainer != newConstrainer)
|
||||
{
|
||||
resizable = true;
|
||||
if (newConstrainer != nullptr)
|
||||
resizable = (newConstrainer->getMinimumWidth() != newConstrainer->getMaximumWidth()
|
||||
|| newConstrainer->getMinimumHeight() != newConstrainer->getMaximumHeight());
|
||||
|
||||
attachConstrainer (newConstrainer);
|
||||
}
|
||||
}
|
||||
@ -207,4 +205,23 @@ void AudioProcessorEditor::setScaleFactor (float newScale)
|
||||
editorResized (true);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity
|
||||
typedef ComponentPeer* (*createUnityPeerFunctionType) (Component&);
|
||||
createUnityPeerFunctionType juce_createUnityPeerFn = nullptr;
|
||||
#endif
|
||||
|
||||
ComponentPeer* AudioProcessorEditor::createNewPeer (int styleFlags, void* nativeWindow)
|
||||
{
|
||||
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity
|
||||
if (juce_createUnityPeerFn != nullptr)
|
||||
{
|
||||
ignoreUnused (styleFlags, nativeWindow);
|
||||
return juce_createUnityPeerFn (*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Component::createNewPeer (styleFlags, nativeWindow);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
@ -53,7 +53,7 @@ protected:
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
~AudioProcessorEditor();
|
||||
~AudioProcessorEditor() override;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
@ -193,6 +193,8 @@ private:
|
||||
JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditorListener)
|
||||
};
|
||||
|
||||
ComponentPeer* createNewPeer (int styleFlags, void*) override;
|
||||
|
||||
//==============================================================================
|
||||
void initialise();
|
||||
void editorResized (bool wasResized);
|
||||
|
@ -191,13 +191,13 @@ private:
|
||||
{
|
||||
struct LambdaOp : public RenderingOp
|
||||
{
|
||||
LambdaOp (LambdaType&& f) : function (static_cast<LambdaType&&> (f)) {}
|
||||
LambdaOp (LambdaType&& f) : function (std::move (f)) {}
|
||||
void perform (const Context& c) override { function (c); }
|
||||
|
||||
LambdaType function;
|
||||
};
|
||||
|
||||
renderOps.add (new LambdaOp (static_cast<LambdaType&&> (fn)));
|
||||
renderOps.add (new LambdaOp (std::move (fn)));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@ -359,23 +359,20 @@ struct RenderSequenceBuilder
|
||||
{
|
||||
AudioProcessorGraph::NodeAndChannel channel;
|
||||
|
||||
static AssignedBuffer createReadOnlyEmpty() noexcept { return { { (NodeID) zeroNodeID, 0 } }; }
|
||||
static AssignedBuffer createFree() noexcept { return { { (NodeID) freeNodeID, 0 } }; }
|
||||
static AssignedBuffer createReadOnlyEmpty() noexcept { return { { zeroNodeID(), 0 } }; }
|
||||
static AssignedBuffer createFree() noexcept { return { { freeNodeID(), 0 } }; }
|
||||
|
||||
bool isReadOnlyEmpty() const noexcept { return channel.nodeID == (NodeID) zeroNodeID; }
|
||||
bool isFree() const noexcept { return channel.nodeID == (NodeID) freeNodeID; }
|
||||
bool isReadOnlyEmpty() const noexcept { return channel.nodeID == zeroNodeID(); }
|
||||
bool isFree() const noexcept { return channel.nodeID == freeNodeID(); }
|
||||
bool isAssigned() const noexcept { return ! (isReadOnlyEmpty() || isFree()); }
|
||||
|
||||
void setFree() noexcept { channel = { (NodeID) freeNodeID, 0 }; }
|
||||
void setAssignedToNonExistentNode() noexcept { channel = { (NodeID) anonNodeID, 0 }; }
|
||||
void setFree() noexcept { channel = { freeNodeID(), 0 }; }
|
||||
void setAssignedToNonExistentNode() noexcept { channel = { anonNodeID(), 0 }; }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
anonNodeID = 0x7ffffffd,
|
||||
zeroNodeID = 0x7ffffffe,
|
||||
freeNodeID = 0x7fffffff
|
||||
};
|
||||
static NodeID anonNodeID() { return NodeID (0x7ffffffd); }
|
||||
static NodeID zeroNodeID() { return NodeID (0x7ffffffe); }
|
||||
static NodeID freeNodeID() { return NodeID (0x7fffffff); }
|
||||
};
|
||||
|
||||
Array<AssignedBuffer> audioBuffers, midiBuffers;
|
||||
@ -388,12 +385,12 @@ struct RenderSequenceBuilder
|
||||
int delay;
|
||||
};
|
||||
|
||||
HashMap<NodeID, int> delays;
|
||||
HashMap<uint32, int> delays;
|
||||
int totalLatency = 0;
|
||||
|
||||
int getNodeDelay (NodeID nodeID) const noexcept
|
||||
{
|
||||
return delays[nodeID];
|
||||
return delays[nodeID.uid];
|
||||
}
|
||||
|
||||
int getInputLatencyForNode (NodeID nodeID) const
|
||||
@ -681,12 +678,12 @@ struct RenderSequenceBuilder
|
||||
if (processor.producesMidi())
|
||||
midiBuffers.getReference (midiBufferToUse).channel = { node.nodeID, AudioProcessorGraph::midiChannelIndex };
|
||||
|
||||
delays.set (node.nodeID, maxLatency + processor.getLatencySamples());
|
||||
delays.set (node.nodeID.uid, maxLatency + processor.getLatencySamples());
|
||||
|
||||
if (numOuts == 0)
|
||||
totalLatency = maxLatency;
|
||||
|
||||
sequence.addProcessOp (&node, audioChannelsToUse, totalChans, midiBufferToUse);
|
||||
sequence.addProcessOp (node, audioChannelsToUse, totalChans, midiBufferToUse);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
@ -896,6 +893,8 @@ void AudioProcessorGraph::topologyChanged()
|
||||
|
||||
void AudioProcessorGraph::clear()
|
||||
{
|
||||
const ScopedLock sl (getCallbackLock());
|
||||
|
||||
if (nodes.isEmpty())
|
||||
return;
|
||||
|
||||
@ -920,8 +919,8 @@ AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (AudioProcessor* new
|
||||
return {};
|
||||
}
|
||||
|
||||
if (nodeID == 0)
|
||||
nodeID = ++lastNodeID;
|
||||
if (nodeID == NodeID())
|
||||
nodeID.uid = ++(lastNodeID.uid);
|
||||
|
||||
for (auto* n : nodes)
|
||||
{
|
||||
@ -932,13 +931,13 @@ AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (AudioProcessor* new
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeID > lastNodeID)
|
||||
if (lastNodeID < nodeID)
|
||||
lastNodeID = nodeID;
|
||||
|
||||
newProcessor->setPlayHead (getPlayHead());
|
||||
|
||||
Node::Ptr n (new Node (nodeID, newProcessor));
|
||||
nodes.add (n);
|
||||
nodes.add (n.get());
|
||||
n->setParentGraph (this);
|
||||
topologyChanged();
|
||||
return n;
|
||||
@ -1242,16 +1241,15 @@ void AudioProcessorGraph::handleAsyncUpdate()
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioProcessorGraph::prepareToPlay (double /*sampleRate*/, int estimatedSamplesPerBlock)
|
||||
void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)
|
||||
{
|
||||
if (renderSequenceFloat != nullptr)
|
||||
renderSequenceFloat->prepareBuffers (estimatedSamplesPerBlock);
|
||||
|
||||
if (renderSequenceDouble != nullptr)
|
||||
renderSequenceDouble->prepareBuffers (estimatedSamplesPerBlock);
|
||||
|
||||
setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);
|
||||
clearRenderingSequence();
|
||||
triggerAsyncUpdate();
|
||||
|
||||
if (isNonRealtime() && MessageManager::getInstance()->isThisTheMessageThread())
|
||||
handleAsyncUpdate();
|
||||
else
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
bool AudioProcessorGraph::supportsDoublePrecisionProcessing() const
|
||||
@ -1261,6 +1259,8 @@ bool AudioProcessorGraph::supportsDoublePrecisionProcessing() const
|
||||
|
||||
void AudioProcessorGraph::releaseResources()
|
||||
{
|
||||
const ScopedLock sl (getCallbackLock());
|
||||
|
||||
isPrepared = 0;
|
||||
|
||||
for (auto* n : nodes)
|
||||
|
@ -55,10 +55,20 @@ public:
|
||||
/** Destructor.
|
||||
Any processor objects that have been added to the graph will also be deleted.
|
||||
*/
|
||||
~AudioProcessorGraph();
|
||||
~AudioProcessorGraph() override;
|
||||
|
||||
/** Each node in the graph has a UID of this type. */
|
||||
using NodeID = uint32;
|
||||
struct NodeID
|
||||
{
|
||||
NodeID() {}
|
||||
explicit NodeID (uint32 i) : uid (i) {}
|
||||
|
||||
uint32 uid = 0;
|
||||
|
||||
bool operator== (const NodeID& other) const noexcept { return uid == other.uid; }
|
||||
bool operator!= (const NodeID& other) const noexcept { return uid != other.uid; }
|
||||
bool operator< (const NodeID& other) const noexcept { return uid < other.uid; }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** A special index that represents the midi channel of a node.
|
||||
@ -185,7 +195,7 @@ public:
|
||||
This will return nullptr if the index is out of range.
|
||||
@see getNodeForId
|
||||
*/
|
||||
Node* getNode (int index) const noexcept { return nodes [index]; }
|
||||
Node::Ptr getNode (int index) const noexcept { return nodes[index]; }
|
||||
|
||||
/** Searches the graph for a node with the given ID number and returns it.
|
||||
If no such node was found, this returns nullptr.
|
||||
@ -312,7 +322,7 @@ public:
|
||||
|
||||
//==============================================================================
|
||||
AudioGraphIOProcessor (IODeviceType);
|
||||
~AudioGraphIOProcessor();
|
||||
~AudioGraphIOProcessor() override;
|
||||
|
||||
const String getName() const override;
|
||||
void fillInPluginDescription (PluginDescription&) const override;
|
||||
|
@ -42,12 +42,12 @@ class JUCE_API AudioProcessorListener
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor. */
|
||||
virtual ~AudioProcessorListener() {}
|
||||
virtual ~AudioProcessorListener() = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Receives a callback when a parameter is changed.
|
||||
|
||||
IMPORTANT NOTE: this will be called synchronously when a parameter changes, and
|
||||
IMPORTANT NOTE: This will be called synchronously when a parameter changes, and
|
||||
many audio processors will change their parameter during their audio callback.
|
||||
This means that not only has your handler code got to be completely thread-safe,
|
||||
but it's also got to be VERY fast, and avoid blocking. If you need to handle
|
||||
@ -61,7 +61,7 @@ public:
|
||||
/** Called to indicate that something else in the plugin has changed, like its
|
||||
program, number of parameters, etc.
|
||||
|
||||
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
|
||||
IMPORTANT NOTE: This will be called synchronously, and many audio processors will
|
||||
call it during their audio callback. This means that not only has your handler code
|
||||
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
|
||||
blocking. If you need to handle this event on your message thread, use this callback
|
||||
@ -76,7 +76,7 @@ public:
|
||||
press the mouse button, and audioProcessorParameterChangeGestureEnd would be
|
||||
called when they release it.
|
||||
|
||||
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
|
||||
IMPORTANT NOTE: This will be called synchronously, and many audio processors will
|
||||
call it during their audio callback. This means that not only has your handler code
|
||||
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
|
||||
blocking. If you need to handle this event on your message thread, use this callback
|
||||
@ -93,7 +93,7 @@ public:
|
||||
E.g. if the user is dragging a slider, this would be called when they release
|
||||
the mouse button.
|
||||
|
||||
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
|
||||
IMPORTANT NOTE: This will be called synchronously, and many audio processors will
|
||||
call it during their audio callback. This means that not only has your handler code
|
||||
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
|
||||
blocking. If you need to handle this event on your message thread, use this callback
|
||||
|
@ -147,12 +147,12 @@ public:
|
||||
*/
|
||||
virtual bool isBoolean() const;
|
||||
|
||||
/** Returns a textual version of the supplied parameter value.
|
||||
/** Returns a textual version of the supplied normalised parameter value.
|
||||
The default implementation just returns the floating point value
|
||||
as a string, but this could do anything you need for a custom type
|
||||
of value.
|
||||
*/
|
||||
virtual String getText (float value, int /*maximumStringLength*/) const;
|
||||
virtual String getText (float normalisedValue, int /*maximumStringLength*/) const;
|
||||
|
||||
/** Should parse a string and return the appropriate value for it. */
|
||||
virtual float getValueForText (const String& text) const = 0;
|
||||
@ -216,7 +216,7 @@ public:
|
||||
/** Returns the set of strings which represent the possible states a parameter
|
||||
can be in.
|
||||
|
||||
If you are hosting a plug-in you can use the result of this funtion to
|
||||
If you are hosting a plug-in you can use the result of this function to
|
||||
populate a ComboBox listing the allowed values.
|
||||
|
||||
If you are implementing a plug-in then you do not need to override this.
|
||||
@ -238,11 +238,11 @@ public:
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() {}
|
||||
virtual ~Listener() = default;
|
||||
|
||||
/** Receives a callback when a parameter has been changed.
|
||||
|
||||
IMPORTANT NOTE: this will be called synchronously when a parameter changes, and
|
||||
IMPORTANT NOTE: This will be called synchronously when a parameter changes, and
|
||||
many audio processors will change their parameter during their audio callback.
|
||||
This means that not only has your handler code got to be completely thread-safe,
|
||||
but it's also got to be VERY fast, and avoid blocking. If you need to handle
|
||||
@ -257,7 +257,7 @@ public:
|
||||
being true when they first press the mouse button, and it will be called again with
|
||||
gestureIsStarting being false when they release it.
|
||||
|
||||
IMPORTANT NOTE: this will be called synchronously, and many audio processors will
|
||||
IMPORTANT NOTE: This will be called synchronously, and many audio processors will
|
||||
call it during their audio callback. This means that not only has your handler code
|
||||
got to be completely thread-safe, but it's also got to be VERY fast, and avoid
|
||||
blocking. If you need to handle this event on your message thread, use this callback
|
||||
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
class ParameterGroupTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
ParameterGroupTests() : UnitTest ("ParameterGroups", "Parameters") {}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
beginTest ("ParameterGroups");
|
||||
|
||||
auto g1 = std::make_unique<AudioProcessorParameterGroup> ("g1", "g1", " - ");
|
||||
|
||||
auto* p1 = new AudioParameterFloat ("p1", "p1", { 0.0f, 2.0f }, 0.5f);
|
||||
auto* p2 = new AudioParameterFloat ("p2", "p2", { 0.0f, 2.0f }, 0.5f);
|
||||
auto* p3 = new AudioParameterFloat ("p3", "p3", { 0.0f, 2.0f }, 0.5f);
|
||||
|
||||
g1->addChild (std::unique_ptr<AudioParameterFloat> (p1));
|
||||
g1->addChild (std::unique_ptr<AudioParameterFloat> (p2),
|
||||
std::unique_ptr<AudioParameterFloat> (p3));
|
||||
|
||||
auto p4 = std::make_unique<AudioParameterFloat> ("p4", "p4", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
|
||||
auto p5 = std::make_unique<AudioParameterFloat> ("p5", "p5", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
|
||||
auto p6 = std::make_unique<AudioParameterFloat> ("p6", "p6", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
|
||||
|
||||
g1->addChild (std::move (p4));
|
||||
g1->addChild (std::move (p5),
|
||||
std::move (p6));
|
||||
|
||||
{
|
||||
auto topLevelParams = g1->getParameters (false);
|
||||
auto params = g1->getParameters (true);
|
||||
expect (topLevelParams == params);
|
||||
expectEquals (params.size(), 6);
|
||||
|
||||
expect (params[0] == (AudioProcessorParameter*) p1);
|
||||
expect (params[1] == (AudioProcessorParameter*) p2);
|
||||
expect (params[2] == (AudioProcessorParameter*) p3);
|
||||
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[3])->name == "p4");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[4])->name == "p5");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[5])->name == "p6");
|
||||
}
|
||||
|
||||
auto* p7 = new AudioParameterFloat ("p7", "p7", { 0.0f, 2.0f }, 0.5f);
|
||||
auto* p8 = new AudioParameterFloat ("p8", "p8", { 0.0f, 2.0f }, 0.5f);
|
||||
auto* p9 = new AudioParameterFloat ("p9", "p9", { 0.0f, 2.0f }, 0.5f);
|
||||
|
||||
auto p10 = std::make_unique<AudioParameterFloat> ("p10", "p10", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
|
||||
auto p11 = std::make_unique<AudioParameterFloat> ("p11", "p11", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
|
||||
auto p12 = std::make_unique<AudioParameterFloat> ("p12", "p12", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
|
||||
|
||||
auto g2 = std::make_unique<AudioProcessorParameterGroup> ("g2", "g2", " | ", std::unique_ptr<AudioParameterFloat> (p7));
|
||||
auto g3 = std::make_unique<AudioProcessorParameterGroup> ("g3", "g3", " | ", std::unique_ptr<AudioParameterFloat> (p8), std::unique_ptr<AudioParameterFloat> (p9));
|
||||
auto g4 = std::make_unique<AudioProcessorParameterGroup> ("g4", "g4", " | ", std::move (p10));
|
||||
auto g5 = std::make_unique<AudioProcessorParameterGroup> ("g5", "g5", " | ", std::move (p11), std::move (p12));
|
||||
|
||||
g1->addChild (std::move (g2));
|
||||
g4->addChild (std::move (g5));
|
||||
g1->addChild (std::move (g3), std::move (g4));
|
||||
|
||||
{
|
||||
auto topLevelParams = g1->getParameters (false);
|
||||
auto params = g1->getParameters (true);
|
||||
expectEquals (topLevelParams.size(), 6);
|
||||
expectEquals (params.size(), 12);
|
||||
|
||||
expect (params[0] == (AudioProcessorParameter*) p1);
|
||||
expect (params[1] == (AudioProcessorParameter*) p2);
|
||||
expect (params[2] == (AudioProcessorParameter*) p3);
|
||||
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[3])->name == "p4");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[4])->name == "p5");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[5])->name == "p6");
|
||||
|
||||
expect (params[6] == (AudioProcessorParameter*) p7);
|
||||
expect (params[7] == (AudioProcessorParameter*) p8);
|
||||
expect (params[8] == (AudioProcessorParameter*) p9);
|
||||
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[9]) ->name == "p10");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[10])->name == "p11");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (params[11])->name == "p12");
|
||||
}
|
||||
|
||||
g1->addChild (std::make_unique<AudioProcessorParameterGroup> ("g6", "g6", " | ",
|
||||
std::make_unique<AudioParameterFloat> ("p11", "p11", NormalisableRange<float> (0.0f, 2.0f), 0.5f),
|
||||
std::make_unique<AudioProcessorParameterGroup> ("g7", "g7", " | ",
|
||||
std::make_unique<AudioParameterFloat> ("p12", "p12", NormalisableRange<float> (0.0f, 2.0f), 0.5f)),
|
||||
std::make_unique<AudioParameterFloat> ("p13", "p13", NormalisableRange<float> (0.0f, 2.0f), 0.5f)));
|
||||
|
||||
TestAudioProcessor processor;
|
||||
|
||||
processor.addParameter (new AudioParameterFloat ("pstart", "pstart", NormalisableRange<float> (0.0f, 2.0f), 0.5f));
|
||||
auto groupParams = g1->getParameters (true);
|
||||
processor.addParameterGroup (std::move (g1));
|
||||
processor.addParameter (new AudioParameterFloat ("pend", "pend", NormalisableRange<float> (0.0f, 2.0f), 0.5f));
|
||||
|
||||
auto& processorParams = processor.getParameters();
|
||||
expect (dynamic_cast<AudioParameterFloat*> (processorParams.getFirst())->name == "pstart");
|
||||
expect (dynamic_cast<AudioParameterFloat*> (processorParams.getLast()) ->name == "pend");
|
||||
|
||||
auto numParams = processorParams.size();
|
||||
|
||||
for (int i = 1; i < numParams - 1; ++i)
|
||||
expect (processorParams[i] == groupParams[i - 1]);
|
||||
|
||||
}
|
||||
private:
|
||||
struct TestAudioProcessor : public AudioProcessor
|
||||
{
|
||||
const String getName() const override { return "ap"; }
|
||||
void prepareToPlay (double, int) override {}
|
||||
void releaseResources() override {}
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}
|
||||
double getTailLengthSeconds() const override { return 0.0; }
|
||||
bool acceptsMidi() const override { return false; }
|
||||
bool producesMidi() const override { return false; }
|
||||
AudioProcessorEditor* createEditor() override { return nullptr; }
|
||||
bool hasEditor() const override { return false; }
|
||||
int getNumPrograms() override { return 0; }
|
||||
int getCurrentProgram() override { return 0; }
|
||||
void setCurrentProgram (int) override {}
|
||||
const String getProgramName (int) override { return {}; }
|
||||
void changeProgramName (int, const String&) override {}
|
||||
void getStateInformation (MemoryBlock&) override {}
|
||||
void setStateInformation (const void*, int) override {}
|
||||
};
|
||||
};
|
||||
|
||||
static ParameterGroupTests parameterGroupTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
@ -0,0 +1,299 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** A class encapsulating a group of AudioProcessorParameters and nested
|
||||
AudioProcessorParameterGroups.
|
||||
|
||||
This class is predominantly write-only; there are methods for adding group
|
||||
members but none for removing them. Ultimately you will probably want to
|
||||
add a fully constructed group to an AudioProcessor.
|
||||
|
||||
@see AudioProcessor::addParameterGroup
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class AudioProcessorParameterGroup
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** A child of an AudioProcessorParameterGroup.
|
||||
|
||||
This can contain either an AudioProcessorParameter or an
|
||||
AudioProcessorParameterGroup. You can query which using the
|
||||
getParameter and getGroup methods.
|
||||
|
||||
@code
|
||||
for (auto* child : group)
|
||||
if (auto* parameter = node.getParameter())
|
||||
parameter->setValueNotifyingHost (0.5f);
|
||||
else
|
||||
node.getGroup()->AddChild (new Parameter());
|
||||
@endcode
|
||||
*/
|
||||
class AudioProcessorParameterNode
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Returns the parent group or nullptr if this is a top-level group. */
|
||||
AudioProcessorParameterGroup* getParent() const { return parent; }
|
||||
|
||||
/** Returns a pointer to a parameter if this node contains a parameter, nullptr otherwise. */
|
||||
AudioProcessorParameter* getParameter() const { return parameter.get(); }
|
||||
|
||||
/** Returns a pointer to a group if this node contains a group, nullptr otherwise. */
|
||||
AudioProcessorParameterGroup* getGroup() const { return group.get(); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioProcessorParameterGroup> group;
|
||||
std::unique_ptr<AudioProcessorParameter> parameter;
|
||||
AudioProcessorParameterGroup* parent = nullptr;
|
||||
|
||||
friend class AudioProcessorParameterGroup;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterNode)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Creates an empty AudioProcessorParameterGroup.
|
||||
|
||||
@param groupID A unique identifier for the group. Keep it basic; don't use any special
|
||||
characters like "." and avoid pure integer strings which could collide with
|
||||
legacy parameter IDs.
|
||||
@param groupName The group's name, which will be displayed in the host.
|
||||
@param subgroupSeparator A separator string to use between the name of this group and the name of any
|
||||
subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates an AudioProcessorParameterGroup with a single child.
|
||||
|
||||
@param groupID A unique identifier for the group. Keep it basic; don't use any special
|
||||
characters like "." and avoid pure integer strings which could collide with
|
||||
legacy parameter IDs.
|
||||
@param groupName The group's name, which will be displayed in the host.
|
||||
@param subgroupSeparator A separator string to use between the name of this group and the name of any
|
||||
subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
|
||||
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)
|
||||
: AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator)
|
||||
{
|
||||
addChild (std::move (child));
|
||||
}
|
||||
|
||||
/** Creates an AudioProcessorParameterGroup with multiple children.
|
||||
|
||||
@param groupID A unique identifier for the group. Keep it basic; don't use any special
|
||||
characters like "." and avoid pure integer strings which could collide with
|
||||
legacy parameter IDs.
|
||||
@param groupName The group's name, which will be displayed in the host.
|
||||
@param subgroupSeparator A separator string to use between the name of this group and the name of any
|
||||
subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
|
||||
layers of nested subgroups, but AU plug-ins cannot have any subgroups.
|
||||
@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)
|
||||
: AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator, std::move (firstChild))
|
||||
{
|
||||
addChild (std::forward<Args> (remainingChildren)...);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the group's ID. */
|
||||
String getID() const { return identifier; }
|
||||
|
||||
/** Returns the group's name. */
|
||||
String getName() const { return name; }
|
||||
|
||||
/** Returns the group's separator string. */
|
||||
String getSeparator() const { return separator; }
|
||||
|
||||
/** Returns the parent of the group, or nullptr if this is a top-levle group. */
|
||||
const AudioProcessorParameterGroup* getParent() const noexcept { return parent; }
|
||||
|
||||
//==============================================================================
|
||||
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);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns all subgroups of this group.
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a child to the group. */
|
||||
template <typename ChildType>
|
||||
void addChild (std::unique_ptr<ChildType> 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));
|
||||
}
|
||||
|
||||
/** Adds multiple children to the group. */
|
||||
template <typename ChildType, typename... Args>
|
||||
void addChild (std::unique_ptr<ChildType> firstChild, Args&&... remainingChildren)
|
||||
{
|
||||
addChild (std::move (firstChild));
|
||||
addChild (std::forward<Args> (remainingChildren)...);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const String identifier, name, separator;
|
||||
OwnedArray<const AudioProcessorParameterNode> children;
|
||||
AudioProcessorParameterGroup* parent = nullptr;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterGroup)
|
||||
};
|
||||
|
||||
} // namespace juce
|
@ -32,8 +32,8 @@ class ParameterListener : private AudioProcessorParameter::Listener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
ParameterListener (AudioProcessor& p, AudioProcessorParameter& param)
|
||||
: processor (p), parameter (param)
|
||||
ParameterListener (AudioProcessor& proc, AudioProcessorParameter& param)
|
||||
: processor (proc), parameter (param)
|
||||
{
|
||||
if (LegacyAudioParameter::isLegacy (¶meter))
|
||||
processor.addListener (this);
|
||||
@ -43,7 +43,7 @@ public:
|
||||
startTimer (100);
|
||||
}
|
||||
|
||||
virtual ~ParameterListener()
|
||||
~ParameterListener() override
|
||||
{
|
||||
if (LegacyAudioParameter::isLegacy (¶meter))
|
||||
processor.removeListener (this);
|
||||
@ -101,8 +101,8 @@ class BooleanParameterComponent final : public Component,
|
||||
private ParameterListener
|
||||
{
|
||||
public:
|
||||
BooleanParameterComponent (AudioProcessor& processor, AudioProcessorParameter& param)
|
||||
: ParameterListener (processor, param)
|
||||
BooleanParameterComponent (AudioProcessor& proc, AudioProcessorParameter& param)
|
||||
: ParameterListener (proc, param)
|
||||
{
|
||||
// Set the initial value.
|
||||
handleNewParameterValue();
|
||||
@ -154,8 +154,8 @@ class SwitchParameterComponent final : public Component,
|
||||
private ParameterListener
|
||||
{
|
||||
public:
|
||||
SwitchParameterComponent (AudioProcessor& processor, AudioProcessorParameter& param)
|
||||
: ParameterListener (processor, param)
|
||||
SwitchParameterComponent (AudioProcessor& proc, AudioProcessorParameter& param)
|
||||
: ParameterListener (proc, param)
|
||||
{
|
||||
auto* leftButton = buttons.add (new TextButton());
|
||||
auto* rightButton = buttons.add (new TextButton());
|
||||
@ -259,8 +259,8 @@ class ChoiceParameterComponent final : public Component,
|
||||
private ParameterListener
|
||||
{
|
||||
public:
|
||||
ChoiceParameterComponent (AudioProcessor& processor, AudioProcessorParameter& param)
|
||||
: ParameterListener (processor, param),
|
||||
ChoiceParameterComponent (AudioProcessor& proc, AudioProcessorParameter& param)
|
||||
: ParameterListener (proc, param),
|
||||
parameterValues (getParameter().getAllValueStrings())
|
||||
{
|
||||
box.addItemList (parameterValues, 1);
|
||||
@ -321,8 +321,8 @@ class SliderParameterComponent final : public Component,
|
||||
private ParameterListener
|
||||
{
|
||||
public:
|
||||
SliderParameterComponent (AudioProcessor& processor, AudioProcessorParameter& param)
|
||||
: ParameterListener (processor, param)
|
||||
SliderParameterComponent (AudioProcessor& proc, AudioProcessorParameter& param)
|
||||
: ParameterListener (proc, param)
|
||||
{
|
||||
if (getParameter().getNumSteps() != AudioProcessor::getDefaultNumParameterSteps())
|
||||
slider.setRange (0.0, 1.0, 1.0 / (getParameter().getNumSteps() - 1.0));
|
||||
@ -506,7 +506,7 @@ private:
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct GenericAudioProcessorEditor::Pimpl
|
||||
struct GenericAudioProcessorEditor::Pimpl
|
||||
{
|
||||
Pimpl (GenericAudioProcessorEditor& parent)
|
||||
: owner (parent)
|
||||
|
@ -44,7 +44,7 @@ class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor
|
||||
public:
|
||||
//==============================================================================
|
||||
GenericAudioProcessorEditor (AudioProcessor* owner);
|
||||
~GenericAudioProcessorEditor();
|
||||
~GenericAudioProcessorEditor() override;
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics&) override;
|
||||
|
Reference in New Issue
Block a user