- clean working copy for leaving SVN
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPLAYHEAD_H_INCLUDED
|
||||
#define JUCE_AUDIOPLAYHEAD_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A subclass of AudioPlayHead can supply information about the position and
|
||||
status of a moving play head during audio playback.
|
||||
|
||||
One of these can be supplied to an AudioProcessor object so that it can find
|
||||
out about the position of the audio that it is rendering.
|
||||
|
||||
@see AudioProcessor::setPlayHead, AudioProcessor::getPlayHead
|
||||
*/
|
||||
class JUCE_API AudioPlayHead
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
AudioPlayHead() {}
|
||||
|
||||
public:
|
||||
virtual ~AudioPlayHead() {}
|
||||
|
||||
//==============================================================================
|
||||
/** Frame rate types. */
|
||||
enum FrameRateType
|
||||
{
|
||||
fps24 = 0,
|
||||
fps25 = 1,
|
||||
fps2997 = 2,
|
||||
fps30 = 3,
|
||||
fps2997drop = 4,
|
||||
fps30drop = 5,
|
||||
fpsUnknown = 99
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** This structure is filled-in by the AudioPlayHead::getCurrentPosition() method.
|
||||
*/
|
||||
struct JUCE_API CurrentPositionInfo
|
||||
{
|
||||
/** The tempo in BPM */
|
||||
double bpm;
|
||||
|
||||
/** Time signature numerator, e.g. the 3 of a 3/4 time sig */
|
||||
int timeSigNumerator;
|
||||
/** Time signature denominator, e.g. the 4 of a 3/4 time sig */
|
||||
int timeSigDenominator;
|
||||
|
||||
/** The current play position, in samples from the start of the edit. */
|
||||
int64 timeInSamples;
|
||||
/** The current play position, in seconds from the start of the edit. */
|
||||
double timeInSeconds;
|
||||
|
||||
/** For timecode, the position of the start of the edit, in seconds from 00:00:00:00. */
|
||||
double editOriginTime;
|
||||
|
||||
/** The current play position, in pulses-per-quarter-note. */
|
||||
double ppqPosition;
|
||||
|
||||
/** The position of the start of the last bar, in pulses-per-quarter-note.
|
||||
|
||||
This is the time from the start of the edit to the start of the current
|
||||
bar, in ppq units.
|
||||
|
||||
Note - this value may be unavailable on some hosts, e.g. Pro-Tools. If
|
||||
it's not available, the value will be 0.
|
||||
*/
|
||||
double ppqPositionOfLastBarStart;
|
||||
|
||||
/** The video frame rate, if applicable. */
|
||||
FrameRateType frameRate;
|
||||
|
||||
/** True if the transport is currently playing. */
|
||||
bool isPlaying;
|
||||
|
||||
/** True if the transport is currently recording.
|
||||
|
||||
(When isRecording is true, then isPlaying will also be true).
|
||||
*/
|
||||
bool isRecording;
|
||||
|
||||
/** The current cycle start position in pulses-per-quarter-note.
|
||||
Note that not all hosts or plugin formats may provide this value.
|
||||
@see isLooping
|
||||
*/
|
||||
double ppqLoopStart;
|
||||
|
||||
/** The current cycle end position in pulses-per-quarter-note.
|
||||
Note that not all hosts or plugin formats may provide this value.
|
||||
@see isLooping
|
||||
*/
|
||||
double ppqLoopEnd;
|
||||
|
||||
/** True if the transport is currently looping. */
|
||||
bool isLooping;
|
||||
|
||||
//==============================================================================
|
||||
bool operator== (const CurrentPositionInfo& other) const noexcept;
|
||||
bool operator!= (const CurrentPositionInfo& other) const noexcept;
|
||||
|
||||
void resetToDefault();
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Fills-in the given structure with details about the transport's
|
||||
position at the start of the current processing block.
|
||||
|
||||
This method must ONLY be called from within your AudioProcessor::processBlock()
|
||||
method. Calling it at any other time will probably cause a nasty crash.
|
||||
*/
|
||||
virtual bool getCurrentPosition (CurrentPositionInfo& result) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_AUDIOPLAYHEAD_H_INCLUDED
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPLUGININSTANCE_H_INCLUDED
|
||||
#define JUCE_AUDIOPLUGININSTANCE_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for an active instance of a plugin.
|
||||
|
||||
This derives from the AudioProcessor class, and adds some extra functionality
|
||||
that helps when wrapping dynamically loaded plugins.
|
||||
|
||||
This class is not needed when writing plugins, and you should never need to derive
|
||||
your own sub-classes from it. The plugin hosting classes use it internally and will
|
||||
return AudioPluginInstance objects which wrap external plugins.
|
||||
|
||||
@see AudioProcessor, AudioPluginFormat
|
||||
*/
|
||||
class JUCE_API AudioPluginInstance : public AudioProcessor
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor.
|
||||
|
||||
Make sure that you delete any UI components that belong to this plugin before
|
||||
deleting the plugin.
|
||||
*/
|
||||
virtual ~AudioPluginInstance() {}
|
||||
|
||||
//==============================================================================
|
||||
/** Fills-in the appropriate parts of this plugin description object. */
|
||||
virtual void fillInPluginDescription (PluginDescription& description) const = 0;
|
||||
|
||||
/** Returns a PluginDescription for this plugin.
|
||||
This is just a convenience method to avoid calling fillInPluginDescription.
|
||||
*/
|
||||
PluginDescription getPluginDescription() const
|
||||
{
|
||||
PluginDescription desc;
|
||||
fillInPluginDescription (desc);
|
||||
return desc;
|
||||
}
|
||||
|
||||
/** Returns a pointer to some kind of platform-specific data about the plugin.
|
||||
E.g. For a VST, this value can be cast to an AEffect*. For an AudioUnit, it can be
|
||||
cast to an AudioUnit handle.
|
||||
*/
|
||||
virtual void* getPlatformSpecificData() { return nullptr; }
|
||||
|
||||
/** For some formats (currently AudioUnit), this forces a reload of the list of
|
||||
available parameters.
|
||||
*/
|
||||
virtual void refreshParameterList() {}
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
AudioPluginInstance() {}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginInstance)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_AUDIOPLUGININSTANCE_H_INCLUDED
|
||||
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
static ThreadLocalValue<AudioProcessor::WrapperType> wrapperTypeBeingCreated;
|
||||
|
||||
void JUCE_CALLTYPE AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::WrapperType type)
|
||||
{
|
||||
wrapperTypeBeingCreated = type;
|
||||
}
|
||||
|
||||
AudioProcessor::AudioProcessor()
|
||||
: wrapperType (wrapperTypeBeingCreated.get()),
|
||||
playHead (nullptr),
|
||||
sampleRate (0),
|
||||
blockSize (0),
|
||||
numInputChannels (0),
|
||||
numOutputChannels (0),
|
||||
latencySamples (0),
|
||||
suspended (false),
|
||||
nonRealtime (false)
|
||||
{
|
||||
}
|
||||
|
||||
AudioProcessor::~AudioProcessor()
|
||||
{
|
||||
// ooh, nasty - the editor should have been deleted before the filter
|
||||
// that it refers to is deleted..
|
||||
jassert (activeEditor == nullptr);
|
||||
|
||||
#if JUCE_DEBUG
|
||||
// This will fail if you've called beginParameterChangeGesture() for one
|
||||
// or more parameters without having made a corresponding call to endParameterChangeGesture...
|
||||
jassert (changingParams.countNumberOfSetBits() == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioProcessor::setPlayHead (AudioPlayHead* const newPlayHead)
|
||||
{
|
||||
playHead = newPlayHead;
|
||||
}
|
||||
|
||||
void AudioProcessor::addListener (AudioProcessorListener* const newListener)
|
||||
{
|
||||
const ScopedLock sl (listenerLock);
|
||||
listeners.addIfNotAlreadyThere (newListener);
|
||||
}
|
||||
|
||||
void AudioProcessor::removeListener (AudioProcessorListener* const listenerToRemove)
|
||||
{
|
||||
const ScopedLock sl (listenerLock);
|
||||
listeners.removeFirstMatchingValue (listenerToRemove);
|
||||
}
|
||||
|
||||
void AudioProcessor::setPlayConfigDetails (const int newNumIns,
|
||||
const int newNumOuts,
|
||||
const double newSampleRate,
|
||||
const int newBlockSize) noexcept
|
||||
{
|
||||
sampleRate = newSampleRate;
|
||||
blockSize = newBlockSize;
|
||||
|
||||
if (numInputChannels != newNumIns || numOutputChannels != newNumOuts)
|
||||
{
|
||||
numInputChannels = newNumIns;
|
||||
numOutputChannels = newNumOuts;
|
||||
|
||||
numChannelsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessor::numChannelsChanged() {}
|
||||
|
||||
void AudioProcessor::setSpeakerArrangement (const String& inputs, const String& outputs)
|
||||
{
|
||||
inputSpeakerArrangement = inputs;
|
||||
outputSpeakerArrangement = outputs;
|
||||
}
|
||||
|
||||
void AudioProcessor::setNonRealtime (const bool newNonRealtime) noexcept
|
||||
{
|
||||
nonRealtime = newNonRealtime;
|
||||
}
|
||||
|
||||
void AudioProcessor::setLatencySamples (const int newLatency)
|
||||
{
|
||||
if (latencySamples != newLatency)
|
||||
{
|
||||
latencySamples = newLatency;
|
||||
updateHostDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessor::setParameterNotifyingHost (const int parameterIndex,
|
||||
const float newValue)
|
||||
{
|
||||
setParameter (parameterIndex, newValue);
|
||||
sendParamChangeMessageToListeners (parameterIndex, newValue);
|
||||
}
|
||||
|
||||
AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) const noexcept
|
||||
{
|
||||
const ScopedLock sl (listenerLock);
|
||||
return listeners [index];
|
||||
}
|
||||
|
||||
void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex, const float newValue)
|
||||
{
|
||||
if (isPositiveAndBelow (parameterIndex, getNumParameters()))
|
||||
{
|
||||
for (int i = listeners.size(); --i >= 0;)
|
||||
if (AudioProcessorListener* l = getListenerLocked (i))
|
||||
l->audioProcessorParameterChanged (this, parameterIndex, newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // called with an out-of-range parameter index!
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessor::beginParameterChangeGesture (int parameterIndex)
|
||||
{
|
||||
if (isPositiveAndBelow (parameterIndex, getNumParameters()))
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
// This means you've called beginParameterChangeGesture twice in succession without a matching
|
||||
// call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it.
|
||||
jassert (! changingParams [parameterIndex]);
|
||||
changingParams.setBit (parameterIndex);
|
||||
#endif
|
||||
|
||||
for (int i = listeners.size(); --i >= 0;)
|
||||
if (AudioProcessorListener* l = getListenerLocked (i))
|
||||
l->audioProcessorParameterChangeGestureBegin (this, parameterIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // called with an out-of-range parameter index!
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessor::endParameterChangeGesture (int parameterIndex)
|
||||
{
|
||||
if (isPositiveAndBelow (parameterIndex, getNumParameters()))
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
// This means you've called endParameterChangeGesture without having previously called
|
||||
// endParameterChangeGesture. That might be fine in most hosts, but better to keep the
|
||||
// calls matched correctly.
|
||||
jassert (changingParams [parameterIndex]);
|
||||
changingParams.clearBit (parameterIndex);
|
||||
#endif
|
||||
|
||||
for (int i = listeners.size(); --i >= 0;)
|
||||
if (AudioProcessorListener* l = getListenerLocked (i))
|
||||
l->audioProcessorParameterChangeGestureEnd (this, parameterIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // called with an out-of-range parameter index!
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessor::updateHostDisplay()
|
||||
{
|
||||
for (int i = listeners.size(); --i >= 0;)
|
||||
if (AudioProcessorListener* l = getListenerLocked (i))
|
||||
l->audioProcessorChanged (this);
|
||||
}
|
||||
|
||||
const OwnedArray<AudioProcessorParameter>& AudioProcessor::getParameters() const noexcept
|
||||
{
|
||||
return managedParameters;
|
||||
}
|
||||
|
||||
int AudioProcessor::getNumParameters()
|
||||
{
|
||||
return managedParameters.size();
|
||||
}
|
||||
|
||||
float AudioProcessor::getParameter (int index)
|
||||
{
|
||||
if (AudioProcessorParameter* p = getParamChecked (index))
|
||||
return p->getValue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioProcessor::setParameter (int index, float newValue)
|
||||
{
|
||||
if (AudioProcessorParameter* p = getParamChecked (index))
|
||||
p->setValue (newValue);
|
||||
}
|
||||
|
||||
float AudioProcessor::getParameterDefaultValue (int index)
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->getDefaultValue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const String AudioProcessor::getParameterName (int index)
|
||||
{
|
||||
if (AudioProcessorParameter* p = getParamChecked (index))
|
||||
return p->getName (512);
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterName (int index, int maximumStringLength)
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->getName (maximumStringLength);
|
||||
|
||||
return getParameterName (index).substring (0, maximumStringLength);
|
||||
}
|
||||
|
||||
const String AudioProcessor::getParameterText (int index)
|
||||
{
|
||||
return getParameterText (index, 1024);
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterText (int index, int maximumStringLength)
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->getText (p->getValue(), maximumStringLength);
|
||||
|
||||
return getParameterText (index).substring (0, maximumStringLength);
|
||||
}
|
||||
|
||||
int AudioProcessor::getParameterNumSteps (int index)
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->getNumSteps();
|
||||
|
||||
return AudioProcessor::getDefaultNumParameterSteps();
|
||||
}
|
||||
|
||||
int AudioProcessor::getDefaultNumParameterSteps() noexcept
|
||||
{
|
||||
return 0x7fffffff;
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterLabel (int index) const
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->getLabel();
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
bool AudioProcessor::isParameterAutomatable (int index) const
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->isAutomatable();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioProcessor::isParameterOrientationInverted (int index) const
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->isOrientationInverted();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioProcessor::isMetaParameter (int index) const
|
||||
{
|
||||
if (AudioProcessorParameter* p = managedParameters[index])
|
||||
return p->isMetaParameter();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const noexcept
|
||||
{
|
||||
AudioProcessorParameter* p = managedParameters[index];
|
||||
|
||||
// If you hit this, then you're either trying to access parameters that are out-of-range,
|
||||
// or you're not using addParameter and the managed parameter list, but have failed
|
||||
// to override some essential virtual methods and implement them appropriately.
|
||||
jassert (p != nullptr);
|
||||
return p;
|
||||
}
|
||||
|
||||
void AudioProcessor::addParameter (AudioProcessorParameter* p)
|
||||
{
|
||||
p->processor = this;
|
||||
p->parameterIndex = managedParameters.size();
|
||||
managedParameters.add (p);
|
||||
}
|
||||
|
||||
void AudioProcessor::suspendProcessing (const bool shouldBeSuspended)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
suspended = shouldBeSuspended;
|
||||
}
|
||||
|
||||
void AudioProcessor::reset() {}
|
||||
void AudioProcessor::processBlockBypassed (AudioSampleBuffer&, MidiBuffer&) {}
|
||||
|
||||
//==============================================================================
|
||||
void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) noexcept
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
||||
if (activeEditor == editor)
|
||||
activeEditor = nullptr;
|
||||
}
|
||||
|
||||
AudioProcessorEditor* AudioProcessor::createEditorIfNeeded()
|
||||
{
|
||||
if (activeEditor != nullptr)
|
||||
return activeEditor;
|
||||
|
||||
AudioProcessorEditor* const ed = createEditor();
|
||||
|
||||
if (ed != nullptr)
|
||||
{
|
||||
// you must give your editor comp a size before returning it..
|
||||
jassert (ed->getWidth() > 0 && ed->getHeight() > 0);
|
||||
|
||||
const ScopedLock sl (callbackLock);
|
||||
activeEditor = ed;
|
||||
}
|
||||
|
||||
// You must make your hasEditor() method return a consistent result!
|
||||
jassert (hasEditor() == (ed != nullptr));
|
||||
|
||||
return ed;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioProcessor::getCurrentProgramStateInformation (juce::MemoryBlock& destData)
|
||||
{
|
||||
getStateInformation (destData);
|
||||
}
|
||||
|
||||
void AudioProcessor::setCurrentProgramStateInformation (const void* data, int sizeInBytes)
|
||||
{
|
||||
setStateInformation (data, sizeInBytes);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// magic number to identify memory blocks that we've stored as XML
|
||||
const uint32 magicXmlNumber = 0x21324356;
|
||||
|
||||
void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& destData)
|
||||
{
|
||||
{
|
||||
MemoryOutputStream out (destData, false);
|
||||
out.writeInt (magicXmlNumber);
|
||||
out.writeInt (0);
|
||||
xml.writeToStream (out, String(), true, false);
|
||||
out.writeByte (0);
|
||||
}
|
||||
|
||||
// go back and write the string length..
|
||||
static_cast<uint32*> (destData.getData())[1]
|
||||
= ByteOrder::swapIfBigEndian ((uint32) destData.getSize() - 9);
|
||||
}
|
||||
|
||||
XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeInBytes)
|
||||
{
|
||||
if (sizeInBytes > 8
|
||||
&& ByteOrder::littleEndianInt (data) == magicXmlNumber)
|
||||
{
|
||||
const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4));
|
||||
|
||||
if (stringLength > 0)
|
||||
return XmlDocument::parse (String::fromUTF8 (static_cast<const char*> (data) + 8,
|
||||
jmin ((sizeInBytes - 8), stringLength)));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) {}
|
||||
void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {}
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessorParameter::AudioProcessorParameter() noexcept
|
||||
: processor (nullptr), parameterIndex (-1)
|
||||
{}
|
||||
|
||||
AudioProcessorParameter::~AudioProcessorParameter() {}
|
||||
|
||||
void AudioProcessorParameter::setValueNotifyingHost (float newValue)
|
||||
{
|
||||
// This method can't be used until the parameter has been attached to a processor!
|
||||
jassert (processor != nullptr && parameterIndex >= 0);
|
||||
|
||||
return processor->setParameterNotifyingHost (parameterIndex, newValue);
|
||||
}
|
||||
|
||||
void AudioProcessorParameter::beginChangeGesture()
|
||||
{
|
||||
// This method can't be used until the parameter has been attached to a processor!
|
||||
jassert (processor != nullptr && parameterIndex >= 0);
|
||||
|
||||
processor->beginParameterChangeGesture (parameterIndex);
|
||||
}
|
||||
|
||||
void AudioProcessorParameter::endChangeGesture()
|
||||
{
|
||||
// This method can't be used until the parameter has been attached to a processor!
|
||||
jassert (processor != nullptr && parameterIndex >= 0);
|
||||
|
||||
processor->endParameterChangeGesture (parameterIndex);
|
||||
}
|
||||
|
||||
bool AudioProcessorParameter::isOrientationInverted() const { return false; }
|
||||
bool AudioProcessorParameter::isAutomatable() const { return true; }
|
||||
bool AudioProcessorParameter::isMetaParameter() const { return false; }
|
||||
int AudioProcessorParameter::getNumSteps() const { return AudioProcessor::getDefaultNumParameterSteps(); }
|
||||
|
||||
String AudioProcessorParameter::getText (float value, int /*maximumStringLength*/) const
|
||||
{
|
||||
return String (value, 2);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool AudioPlayHead::CurrentPositionInfo::operator== (const CurrentPositionInfo& other) const noexcept
|
||||
{
|
||||
return timeInSamples == other.timeInSamples
|
||||
&& ppqPosition == other.ppqPosition
|
||||
&& editOriginTime == other.editOriginTime
|
||||
&& ppqPositionOfLastBarStart == other.ppqPositionOfLastBarStart
|
||||
&& frameRate == other.frameRate
|
||||
&& isPlaying == other.isPlaying
|
||||
&& isRecording == other.isRecording
|
||||
&& bpm == other.bpm
|
||||
&& timeSigNumerator == other.timeSigNumerator
|
||||
&& timeSigDenominator == other.timeSigDenominator
|
||||
&& ppqLoopStart == other.ppqLoopStart
|
||||
&& ppqLoopEnd == other.ppqLoopEnd
|
||||
&& isLooping == other.isLooping;
|
||||
}
|
||||
|
||||
bool AudioPlayHead::CurrentPositionInfo::operator!= (const CurrentPositionInfo& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
void AudioPlayHead::CurrentPositionInfo::resetToDefault()
|
||||
{
|
||||
zerostruct (*this);
|
||||
timeSigNumerator = 4;
|
||||
timeSigDenominator = 4;
|
||||
bpm = 120;
|
||||
}
|
||||
@@ -0,0 +1,689 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPROCESSOR_H_INCLUDED
|
||||
#define JUCE_AUDIOPROCESSOR_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for audio processing filters or plugins.
|
||||
|
||||
This is intended to act as a base class of audio filter that is general enough to
|
||||
be wrapped as a VST, AU, RTAS, etc, or used internally.
|
||||
|
||||
It is also used by the plugin hosting code as the wrapper around an instance
|
||||
of a loaded plugin.
|
||||
|
||||
Derive your filter class from this base class, and if you're building a plugin,
|
||||
you should implement a global function called createPluginFilter() which creates
|
||||
and returns a new instance of your subclass.
|
||||
*/
|
||||
class JUCE_API AudioProcessor
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Constructor. */
|
||||
AudioProcessor();
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~AudioProcessor();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the name of this processor. */
|
||||
virtual const String getName() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Called before playback starts, to let the filter prepare itself.
|
||||
|
||||
The sample rate is the target sample rate, and will remain constant until
|
||||
playback stops.
|
||||
|
||||
The estimatedSamplesPerBlock value is a HINT about the typical number of
|
||||
samples that will be processed for each callback, but isn't any kind
|
||||
of guarantee. The actual block sizes that the host uses may be different
|
||||
each time the callback happens, and may be more or less than this value.
|
||||
*/
|
||||
virtual void prepareToPlay (double sampleRate,
|
||||
int estimatedSamplesPerBlock) = 0;
|
||||
|
||||
/** Called after playback has stopped, to let the filter free up any resources it
|
||||
no longer needs.
|
||||
*/
|
||||
virtual void releaseResources() = 0;
|
||||
|
||||
/** Renders the next block.
|
||||
|
||||
When this method is called, the buffer contains a number of channels which is
|
||||
at least as great as the maximum number of input and output channels that
|
||||
this filter is using. It will be filled with the filter's input data and
|
||||
should be replaced with the filter's output.
|
||||
|
||||
So for example if your filter has 2 input channels and 4 output channels, then
|
||||
the buffer will contain 4 channels, the first two being filled with the
|
||||
input data. Your filter should read these, do its processing, and replace
|
||||
the contents of all 4 channels with its output.
|
||||
|
||||
Or if your filter has 5 inputs and 2 outputs, the buffer will have 5 channels,
|
||||
all filled with data, and your filter should overwrite the first 2 of these
|
||||
with its output. But be VERY careful not to write anything to the last 3
|
||||
channels, as these might be mapped to memory that the host assumes is read-only!
|
||||
|
||||
Note that if you have more outputs than inputs, then only those channels that
|
||||
correspond to an input channel are guaranteed to contain sensible data - e.g.
|
||||
in the case of 2 inputs and 4 outputs, the first two channels contain the input,
|
||||
but the last two channels may contain garbage, so you should be careful not to
|
||||
let this pass through without being overwritten or cleared.
|
||||
|
||||
Also note that the buffer may have more channels than are strictly necessary,
|
||||
but you should only read/write from the ones that your filter is supposed to
|
||||
be using.
|
||||
|
||||
The number of samples in these buffers is NOT guaranteed to be the same for every
|
||||
callback, and may be more or less than the estimated value given to prepareToPlay().
|
||||
Your code must be able to cope with variable-sized blocks, or you're going to get
|
||||
clicks and crashes!
|
||||
|
||||
If the filter is receiving a midi input, then the midiMessages array will be filled
|
||||
with the midi messages for this block. Each message's timestamp will indicate the
|
||||
message's time, as a number of samples from the start of the block.
|
||||
|
||||
Any messages left in the midi buffer when this method has finished are assumed to
|
||||
be the filter's midi output. This means that your filter should be careful to
|
||||
clear any incoming messages from the array if it doesn't want them to be passed-on.
|
||||
|
||||
Be very careful about what you do in this callback - it's going to be called by
|
||||
the audio thread, so any kind of interaction with the UI is absolutely
|
||||
out of the question. If you change a parameter in here and need to tell your UI to
|
||||
update itself, the best way is probably to inherit from a ChangeBroadcaster, let
|
||||
the UI components register as listeners, and then call sendChangeMessage() inside the
|
||||
processBlock() method to send out an asynchronous message. You could also use
|
||||
the AsyncUpdater class in a similar way.
|
||||
*/
|
||||
virtual void processBlock (AudioSampleBuffer& buffer,
|
||||
MidiBuffer& midiMessages) = 0;
|
||||
|
||||
/** Renders the next block when the processor is being bypassed.
|
||||
The default implementation of this method will pass-through any incoming audio, but
|
||||
you may override this method e.g. to add latency compensation to the data to match
|
||||
the processor's latency characteristics. This will avoid situations where bypassing
|
||||
will shift the signal forward in time, possibly creating pre-echo effects and odd timings.
|
||||
Another use for this method would be to cross-fade or morph between the wet (not bypassed)
|
||||
and dry (bypassed) signals.
|
||||
*/
|
||||
virtual void processBlockBypassed (AudioSampleBuffer& buffer,
|
||||
MidiBuffer& midiMessages);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the current AudioPlayHead object that should be used to find
|
||||
out the state and position of the playhead.
|
||||
|
||||
You can call this from your processBlock() method, and use the AudioPlayHead
|
||||
object to get the details about the time of the start of the block currently
|
||||
being processed.
|
||||
|
||||
If the host hasn't supplied a playhead object, this will return nullptr.
|
||||
*/
|
||||
AudioPlayHead* getPlayHead() const noexcept { return playHead; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the current sample rate.
|
||||
|
||||
This can be called from your processBlock() method - it's not guaranteed
|
||||
to be valid at any other time, and may return 0 if it's unknown.
|
||||
*/
|
||||
double getSampleRate() const noexcept { return sampleRate; }
|
||||
|
||||
/** Returns the current typical block size that is being used.
|
||||
|
||||
This can be called from your processBlock() method - it's not guaranteed
|
||||
to be valid at any other time.
|
||||
|
||||
Remember it's not the ONLY block size that may be used when calling
|
||||
processBlock, it's just the normal one. The actual block sizes used may be
|
||||
larger or smaller than this, and will vary between successive calls.
|
||||
*/
|
||||
int getBlockSize() const noexcept { return blockSize; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of input channels that the host will be sending the filter.
|
||||
|
||||
If writing a plugin, your configuration macros should specify the number of
|
||||
channels that your filter would prefer to have, and this method lets
|
||||
you know how many the host is actually using.
|
||||
|
||||
Note that this method is only valid during or after the prepareToPlay()
|
||||
method call. Until that point, the number of channels will be unknown.
|
||||
*/
|
||||
int getNumInputChannels() const noexcept { return numInputChannels; }
|
||||
|
||||
/** Returns the number of output channels that the host will be sending the filter.
|
||||
|
||||
If writing a plugin, your configuration macros should specify the number of
|
||||
channels that your filter would prefer to have, and this method lets
|
||||
you know how many the host is actually using.
|
||||
|
||||
Note that this method is only valid during or after the prepareToPlay()
|
||||
method call. Until that point, the number of channels will be unknown.
|
||||
*/
|
||||
int getNumOutputChannels() const noexcept { return numOutputChannels; }
|
||||
|
||||
/** Returns a string containing a whitespace-separated list of speaker types
|
||||
corresponding to each input channel.
|
||||
For example in a 5.1 arrangement, the string may be "L R C Lfe Ls Rs"
|
||||
If the speaker arrangement is unknown, the returned string will be empty.
|
||||
*/
|
||||
const String& getInputSpeakerArrangement() const noexcept { return inputSpeakerArrangement; }
|
||||
|
||||
/** Returns a string containing a whitespace-separated list of speaker types
|
||||
corresponding to each output channel.
|
||||
For example in a 5.1 arrangement, the string may be "L R C Lfe Ls Rs"
|
||||
If the speaker arrangement is unknown, the returned string will be empty.
|
||||
*/
|
||||
const String& getOutputSpeakerArrangement() const noexcept { return outputSpeakerArrangement; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the name of one of the processor's input channels.
|
||||
|
||||
The processor might not supply very useful names for channels, and this might be
|
||||
something like "1", "2", "left", "right", etc.
|
||||
*/
|
||||
virtual const String getInputChannelName (int channelIndex) const = 0;
|
||||
|
||||
/** Returns the name of one of the processor's output channels.
|
||||
|
||||
The processor might not supply very useful names for channels, and this might be
|
||||
something like "1", "2", "left", "right", etc.
|
||||
*/
|
||||
virtual const String getOutputChannelName (int channelIndex) const = 0;
|
||||
|
||||
/** Returns true if the specified channel is part of a stereo pair with its neighbour. */
|
||||
virtual bool isInputChannelStereoPair (int index) const = 0;
|
||||
|
||||
/** Returns true if the specified channel is part of a stereo pair with its neighbour. */
|
||||
virtual bool isOutputChannelStereoPair (int index) const = 0;
|
||||
|
||||
/** This returns the number of samples delay that the filter imposes on the audio
|
||||
passing through it.
|
||||
|
||||
The host will call this to find the latency - the filter itself should set this value
|
||||
by calling setLatencySamples() as soon as it can during its initialisation.
|
||||
*/
|
||||
int getLatencySamples() const noexcept { return latencySamples; }
|
||||
|
||||
/** The filter should call this to set the number of samples delay that it introduces.
|
||||
|
||||
The filter should call this as soon as it can during initialisation, and can call it
|
||||
later if the value changes.
|
||||
*/
|
||||
void setLatencySamples (int newLatency);
|
||||
|
||||
/** Returns true if a silent input always produces a silent output. */
|
||||
virtual bool silenceInProducesSilenceOut() const = 0;
|
||||
|
||||
/** Returns the length of the filter's tail, in seconds. */
|
||||
virtual double getTailLengthSeconds() const = 0;
|
||||
|
||||
/** Returns true if the processor wants midi messages. */
|
||||
virtual bool acceptsMidi() const = 0;
|
||||
|
||||
/** Returns true if the processor produces midi messages. */
|
||||
virtual bool producesMidi() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** This returns a critical section that will automatically be locked while the host
|
||||
is calling the processBlock() method.
|
||||
|
||||
Use it from your UI or other threads to lock access to variables that are used
|
||||
by the process callback, but obviously be careful not to keep it locked for
|
||||
too long, because that could cause stuttering playback. If you need to do something
|
||||
that'll take a long time and need the processing to stop while it happens, use the
|
||||
suspendProcessing() method instead.
|
||||
|
||||
@see suspendProcessing
|
||||
*/
|
||||
const CriticalSection& getCallbackLock() const noexcept { return callbackLock; }
|
||||
|
||||
/** Enables and disables the processing callback.
|
||||
|
||||
If you need to do something time-consuming on a thread and would like to make sure
|
||||
the audio processing callback doesn't happen until you've finished, use this
|
||||
to disable the callback and re-enable it again afterwards.
|
||||
|
||||
E.g.
|
||||
@code
|
||||
void loadNewPatch()
|
||||
{
|
||||
suspendProcessing (true);
|
||||
|
||||
..do something that takes ages..
|
||||
|
||||
suspendProcessing (false);
|
||||
}
|
||||
@endcode
|
||||
|
||||
If the host tries to make an audio callback while processing is suspended, the
|
||||
filter will return an empty buffer, but won't block the audio thread like it would
|
||||
do if you use the getCallbackLock() critical section to synchronise access.
|
||||
|
||||
Any code that calls processBlock() should call isSuspended() before doing so, and
|
||||
if the processor is suspended, it should avoid the call and emit silence or
|
||||
whatever is appropriate.
|
||||
|
||||
@see getCallbackLock
|
||||
*/
|
||||
void suspendProcessing (bool shouldBeSuspended);
|
||||
|
||||
/** Returns true if processing is currently suspended.
|
||||
@see suspendProcessing
|
||||
*/
|
||||
bool isSuspended() const noexcept { return suspended; }
|
||||
|
||||
/** A plugin can override this to be told when it should reset any playing voices.
|
||||
|
||||
The default implementation does nothing, but a host may call this to tell the
|
||||
plugin that it should stop any tails or sounds that have been left running.
|
||||
*/
|
||||
virtual void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the processor is being run in an offline mode for rendering.
|
||||
|
||||
If the processor is being run live on realtime signals, this returns false.
|
||||
If the mode is unknown, this will assume it's realtime and return false.
|
||||
|
||||
This value may be unreliable until the prepareToPlay() method has been called,
|
||||
and could change each time prepareToPlay() is called.
|
||||
|
||||
@see setNonRealtime()
|
||||
*/
|
||||
bool isNonRealtime() const noexcept { return nonRealtime; }
|
||||
|
||||
/** Called by the host to tell this processor whether it's being used in a non-realtime
|
||||
capacity for offline rendering or bouncing.
|
||||
*/
|
||||
virtual void setNonRealtime (bool isNonRealtime) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates the filter's UI.
|
||||
|
||||
This can return nullptr if you want a UI-less filter, in which case the host may create
|
||||
a generic UI that lets the user twiddle the parameters directly.
|
||||
|
||||
If you do want to pass back a component, the component should be created and set to
|
||||
the correct size before returning it. If you implement this method, you must
|
||||
also implement the hasEditor() method and make it return true.
|
||||
|
||||
Remember not to do anything silly like allowing your filter to keep a pointer to
|
||||
the component that gets created - it could be deleted later without any warning, which
|
||||
would make your pointer into a dangler. Use the getActiveEditor() method instead.
|
||||
|
||||
The correct way to handle the connection between an editor component and its
|
||||
filter is to use something like a ChangeBroadcaster so that the editor can
|
||||
register itself as a listener, and be told when a change occurs. This lets them
|
||||
safely unregister themselves when they are deleted.
|
||||
|
||||
Here are a few things to bear in mind when writing an editor:
|
||||
|
||||
- Initially there won't be an editor, until the user opens one, or they might
|
||||
not open one at all. Your filter mustn't rely on it being there.
|
||||
- An editor object may be deleted and a replacement one created again at any time.
|
||||
- It's safe to assume that an editor will be deleted before its filter.
|
||||
|
||||
@see hasEditor
|
||||
*/
|
||||
virtual AudioProcessorEditor* createEditor() = 0;
|
||||
|
||||
/** Your filter must override this and return true if it can create an editor component.
|
||||
@see createEditor
|
||||
*/
|
||||
virtual bool hasEditor() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the active editor, if there is one.
|
||||
Bear in mind this can return nullptr, even if an editor has previously been opened.
|
||||
*/
|
||||
AudioProcessorEditor* getActiveEditor() const noexcept { return activeEditor; }
|
||||
|
||||
/** Returns the active editor, or if there isn't one, it will create one.
|
||||
This may call createEditor() internally to create the component.
|
||||
*/
|
||||
AudioProcessorEditor* createEditorIfNeeded();
|
||||
|
||||
//==============================================================================
|
||||
/** This must return the correct value immediately after the object has been
|
||||
created, and mustn't change the number of parameters later.
|
||||
*/
|
||||
virtual int getNumParameters();
|
||||
|
||||
/** Returns the name of a particular parameter. */
|
||||
virtual const String getParameterName (int parameterIndex);
|
||||
|
||||
/** Called by the host to find out the value of one of the filter's parameters.
|
||||
|
||||
The host will expect the value returned to be between 0 and 1.0.
|
||||
|
||||
This could be called quite frequently, so try to make your code efficient.
|
||||
It's also likely to be called by non-UI threads, so the code in here should
|
||||
be thread-aware.
|
||||
*/
|
||||
virtual float getParameter (int parameterIndex);
|
||||
|
||||
/** Returns the value of a parameter as a text string. */
|
||||
virtual const String getParameterText (int parameterIndex);
|
||||
|
||||
/** Returns the name of a parameter as a text string with a preferred maximum length.
|
||||
If you want to provide customised short versions of your parameter names that
|
||||
will look better in constrained spaces (e.g. the displays on hardware controller
|
||||
devices or mixing desks) then you should implement this method.
|
||||
If you don't override it, the default implementation will call getParameterText(int),
|
||||
and truncate the result.
|
||||
*/
|
||||
virtual String getParameterName (int parameterIndex, int maximumStringLength);
|
||||
|
||||
/** Returns the value of a parameter as a text string with a preferred maximum length.
|
||||
If you want to provide customised short versions of your parameter values that
|
||||
will look better in constrained spaces (e.g. the displays on hardware controller
|
||||
devices or mixing desks) then you should implement this method.
|
||||
If you don't override it, the default implementation will call getParameterText(int),
|
||||
and truncate the result.
|
||||
*/
|
||||
virtual String getParameterText (int parameterIndex, int maximumStringLength);
|
||||
|
||||
/** Returns the number of discrete steps that this parameter can represent.
|
||||
The default return value if you don't implement this method is
|
||||
AudioProcessor::getDefaultNumParameterSteps().
|
||||
If your parameter is boolean, then you may want to make this return 2.
|
||||
The value that is returned may or may not be used, depending on the host.
|
||||
*/
|
||||
virtual int getParameterNumSteps (int parameterIndex);
|
||||
|
||||
/** Returns the default number of steps for a parameter.
|
||||
@see getParameterNumSteps
|
||||
*/
|
||||
static int getDefaultNumParameterSteps() noexcept;
|
||||
|
||||
/** Returns the default value for the parameter.
|
||||
By default, this just returns 0.
|
||||
The value that is returned may or may not be used, depending on the host.
|
||||
*/
|
||||
virtual float getParameterDefaultValue (int parameterIndex);
|
||||
|
||||
/** Some plugin types may be able to return a label string for a
|
||||
parameter's units.
|
||||
*/
|
||||
virtual String getParameterLabel (int index) const;
|
||||
|
||||
/** This can be overridden to tell the host that particular parameters operate in the
|
||||
reverse direction. (Not all plugin formats or hosts will actually use this information).
|
||||
*/
|
||||
virtual bool isParameterOrientationInverted (int index) const;
|
||||
|
||||
/** The host will call this method to change the value of one of the filter's parameters.
|
||||
|
||||
The host may call this at any time, including during the audio processing
|
||||
callback, so the filter has to process this very fast and avoid blocking.
|
||||
|
||||
If you want to set the value of a parameter internally, e.g. from your
|
||||
editor component, then don't call this directly - instead, use the
|
||||
setParameterNotifyingHost() method, which will also send a message to
|
||||
the host telling it about the change. If the message isn't sent, the host
|
||||
won't be able to automate your parameters properly.
|
||||
|
||||
The value passed will be between 0 and 1.0.
|
||||
*/
|
||||
virtual void setParameter (int parameterIndex, float newValue);
|
||||
|
||||
/** Your filter can call this when it needs to change one of its parameters.
|
||||
|
||||
This could happen when the editor or some other internal operation changes
|
||||
a parameter. This method will call the setParameter() method to change the
|
||||
value, and will then send a message to the host telling it about the change.
|
||||
|
||||
Note that to make sure the host correctly handles automation, you should call
|
||||
the beginParameterChangeGesture() and endParameterChangeGesture() methods to
|
||||
tell the host when the user has started and stopped changing the parameter.
|
||||
*/
|
||||
void setParameterNotifyingHost (int parameterIndex, float newValue);
|
||||
|
||||
/** Returns true if the host can automate this parameter.
|
||||
By default, this returns true for all parameters.
|
||||
*/
|
||||
virtual bool isParameterAutomatable (int parameterIndex) const;
|
||||
|
||||
/** Should return true if this parameter is a "meta" parameter.
|
||||
A meta-parameter is a parameter that changes other params. It is used
|
||||
by some hosts (e.g. AudioUnit hosts).
|
||||
By default this returns false.
|
||||
*/
|
||||
virtual bool isMetaParameter (int parameterIndex) const;
|
||||
|
||||
/** Sends a signal to the host to tell it that the user is about to start changing this
|
||||
parameter.
|
||||
|
||||
This allows the host to know when a parameter is actively being held by the user, and
|
||||
it may use this information to help it record automation.
|
||||
|
||||
If you call this, it must be matched by a later call to endParameterChangeGesture().
|
||||
*/
|
||||
void beginParameterChangeGesture (int parameterIndex);
|
||||
|
||||
/** Tells the host that the user has finished changing this parameter.
|
||||
|
||||
This allows the host to know when a parameter is actively being held by the user, and
|
||||
it may use this information to help it record automation.
|
||||
|
||||
A call to this method must follow a call to beginParameterChangeGesture().
|
||||
*/
|
||||
void endParameterChangeGesture (int parameterIndex);
|
||||
|
||||
/** The filter can call this when something (apart from a parameter value) has changed.
|
||||
|
||||
It sends a hint to the host that something like the program, number of parameters,
|
||||
etc, has changed, and that it should update itself.
|
||||
*/
|
||||
void updateHostDisplay();
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a parameter to the list.
|
||||
The parameter object will be managed and deleted automatically by the list
|
||||
when no longer needed.
|
||||
*/
|
||||
void addParameter (AudioProcessorParameter*);
|
||||
|
||||
/** Returns the current list of parameters. */
|
||||
const OwnedArray<AudioProcessorParameter>& getParameters() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of preset programs the filter supports.
|
||||
|
||||
The value returned must be valid as soon as this object is created, and
|
||||
must not change over its lifetime.
|
||||
|
||||
This value shouldn't be less than 1.
|
||||
*/
|
||||
virtual int getNumPrograms() = 0;
|
||||
|
||||
/** Returns the number of the currently active program. */
|
||||
virtual int getCurrentProgram() = 0;
|
||||
|
||||
/** Called by the host to change the current program. */
|
||||
virtual void setCurrentProgram (int index) = 0;
|
||||
|
||||
/** Must return the name of a given program. */
|
||||
virtual const String getProgramName (int index) = 0;
|
||||
|
||||
/** Called by the host to rename a program. */
|
||||
virtual void changeProgramName (int index, const String& newName) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** The host will call this method when it wants to save the filter's internal state.
|
||||
|
||||
This must copy any info about the filter's state into the block of memory provided,
|
||||
so that the host can store this and later restore it using setStateInformation().
|
||||
|
||||
Note that there's also a getCurrentProgramStateInformation() method, which only
|
||||
stores the current program, not the state of the entire filter.
|
||||
|
||||
See also the helper function copyXmlToBinary() for storing settings as XML.
|
||||
|
||||
@see getCurrentProgramStateInformation
|
||||
*/
|
||||
virtual void getStateInformation (juce::MemoryBlock& destData) = 0;
|
||||
|
||||
/** The host will call this method if it wants to save the state of just the filter's
|
||||
current program.
|
||||
|
||||
Unlike getStateInformation, this should only return the current program's state.
|
||||
|
||||
Not all hosts support this, and if you don't implement it, the base class
|
||||
method just calls getStateInformation() instead. If you do implement it, be
|
||||
sure to also implement getCurrentProgramStateInformation.
|
||||
|
||||
@see getStateInformation, setCurrentProgramStateInformation
|
||||
*/
|
||||
virtual void getCurrentProgramStateInformation (juce::MemoryBlock& destData);
|
||||
|
||||
/** This must restore the filter's state from a block of data previously created
|
||||
using getStateInformation().
|
||||
|
||||
Note that there's also a setCurrentProgramStateInformation() method, which tries
|
||||
to restore just the current program, not the state of the entire filter.
|
||||
|
||||
See also the helper function getXmlFromBinary() for loading settings as XML.
|
||||
|
||||
@see setCurrentProgramStateInformation
|
||||
*/
|
||||
virtual void setStateInformation (const void* data, int sizeInBytes) = 0;
|
||||
|
||||
/** The host will call this method if it wants to restore the state of just the filter's
|
||||
current program.
|
||||
|
||||
Not all hosts support this, and if you don't implement it, the base class
|
||||
method just calls setStateInformation() instead. If you do implement it, be
|
||||
sure to also implement getCurrentProgramStateInformation.
|
||||
|
||||
@see setStateInformation, getCurrentProgramStateInformation
|
||||
*/
|
||||
virtual void setCurrentProgramStateInformation (const void* data, int sizeInBytes);
|
||||
|
||||
/** This method is called when the number of input or output channels is changed. */
|
||||
virtual void numChannelsChanged();
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a listener that will be called when an aspect of this processor changes. */
|
||||
virtual void addListener (AudioProcessorListener* newListener);
|
||||
|
||||
/** Removes a previously added listener. */
|
||||
virtual void removeListener (AudioProcessorListener* listenerToRemove);
|
||||
|
||||
//==============================================================================
|
||||
/** Tells the processor to use this playhead object.
|
||||
The processor will not take ownership of the object, so the caller must delete it when
|
||||
it is no longer being used.
|
||||
*/
|
||||
virtual void setPlayHead (AudioPlayHead* newPlayHead);
|
||||
|
||||
//==============================================================================
|
||||
/** This is called by the processor to specify its details before being played. */
|
||||
void setPlayConfigDetails (int numIns, int numOuts, double sampleRate, int blockSize) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Not for public use - this is called before deleting an editor component. */
|
||||
void editorBeingDeleted (AudioProcessorEditor*) noexcept;
|
||||
|
||||
/** Not for public use - this is called to initialise the processor before playing. */
|
||||
void setSpeakerArrangement (const String& inputs, const String& outputs);
|
||||
|
||||
/** Flags to indicate the type of plugin context in which a processor is being used. */
|
||||
enum WrapperType
|
||||
{
|
||||
wrapperType_Undefined = 0,
|
||||
wrapperType_VST,
|
||||
wrapperType_VST3,
|
||||
wrapperType_AudioUnit,
|
||||
wrapperType_RTAS,
|
||||
wrapperType_AAX,
|
||||
wrapperType_Standalone
|
||||
};
|
||||
|
||||
/** When loaded by a plugin wrapper, this flag will be set to indicate the type
|
||||
of plugin within which the processor is running.
|
||||
*/
|
||||
WrapperType wrapperType;
|
||||
|
||||
//==============================================================================
|
||||
/** Helper function that just converts an xml element into a binary blob.
|
||||
|
||||
Use this in your filter's getStateInformation() method if you want to
|
||||
store its state as xml.
|
||||
|
||||
Then use getXmlFromBinary() to reverse this operation and retrieve the XML
|
||||
from a binary blob.
|
||||
*/
|
||||
static void copyXmlToBinary (const XmlElement& xml,
|
||||
juce::MemoryBlock& destData);
|
||||
|
||||
/** Retrieves an XML element that was stored as binary with the copyXmlToBinary() method.
|
||||
|
||||
This might return nullptr if the data's unsuitable or corrupted. Otherwise it will return
|
||||
an XmlElement object that the caller must delete when no longer needed.
|
||||
*/
|
||||
static XmlElement* getXmlFromBinary (const void* data, int sizeInBytes);
|
||||
|
||||
/** @internal */
|
||||
static void JUCE_CALLTYPE setTypeOfNextNewPlugin (WrapperType);
|
||||
|
||||
protected:
|
||||
/** @internal */
|
||||
AudioPlayHead* playHead;
|
||||
|
||||
/** @internal */
|
||||
void sendParamChangeMessageToListeners (int parameterIndex, float newValue);
|
||||
|
||||
private:
|
||||
Array<AudioProcessorListener*> listeners;
|
||||
Component::SafePointer<AudioProcessorEditor> activeEditor;
|
||||
double sampleRate;
|
||||
int blockSize, numInputChannels, numOutputChannels, latencySamples;
|
||||
bool suspended, nonRealtime;
|
||||
CriticalSection callbackLock, listenerLock;
|
||||
String inputSpeakerArrangement, outputSpeakerArrangement;
|
||||
|
||||
OwnedArray<AudioProcessorParameter> managedParameters;
|
||||
AudioProcessorParameter* getParamChecked (int) const noexcept;
|
||||
|
||||
#if JUCE_DEBUG
|
||||
BigInteger changingParams;
|
||||
#endif
|
||||
|
||||
AudioProcessorListener* getListenerLocked (int) const noexcept;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessor)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_AUDIOPROCESSOR_H_INCLUDED
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor& p) noexcept : processor (p)
|
||||
{
|
||||
}
|
||||
|
||||
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* p) noexcept : processor (*p)
|
||||
{
|
||||
// the filter must be valid..
|
||||
jassert (p != nullptr);
|
||||
}
|
||||
|
||||
AudioProcessorEditor::~AudioProcessorEditor()
|
||||
{
|
||||
// if this fails, then the wrapper hasn't called editorBeingDeleted() on the
|
||||
// filter for some reason..
|
||||
jassert (processor.getActiveEditor() != this);
|
||||
}
|
||||
|
||||
void AudioProcessorEditor::setControlHighlight (ParameterControlHighlightInfo) {}
|
||||
int AudioProcessorEditor::getControlParameterIndex (Component&) { return -1; }
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
#define JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for the component that acts as the GUI for an AudioProcessor.
|
||||
|
||||
Derive your editor component from this class, and create an instance of it
|
||||
by overriding the AudioProcessor::createEditor() method.
|
||||
|
||||
@see AudioProcessor, GenericAudioProcessorEditor
|
||||
*/
|
||||
class JUCE_API AudioProcessorEditor : public Component
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates an editor for the specified processor. */
|
||||
AudioProcessorEditor (AudioProcessor&) noexcept;
|
||||
|
||||
/** Creates an editor for the specified processor. */
|
||||
AudioProcessorEditor (AudioProcessor*) noexcept;
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
~AudioProcessorEditor();
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** The AudioProcessor that this editor represents. */
|
||||
AudioProcessor& processor;
|
||||
|
||||
/** Returns a pointer to the processor that this editor represents.
|
||||
This method is here to support legacy code, but it's easier to just use the
|
||||
AudioProcessorEditor::processor member variable directly to get this object.
|
||||
*/
|
||||
AudioProcessor* getAudioProcessor() const noexcept { return &processor; }
|
||||
|
||||
//==============================================================================
|
||||
/** Used by the setParameterHighlighting() method. */
|
||||
struct ParameterControlHighlightInfo
|
||||
{
|
||||
int parameterIndex;
|
||||
bool isHighlighted;
|
||||
Colour suggestedColour;
|
||||
};
|
||||
|
||||
/** Some types of plugin can call this to suggest that the control for a particular
|
||||
parameter should be highlighted.
|
||||
Currently only AAX plugins will call this, and implementing it is optional.
|
||||
*/
|
||||
virtual void setControlHighlight (ParameterControlHighlightInfo);
|
||||
|
||||
/** Called by certain plug-in wrappers to find out whether a component is used
|
||||
to control a parameter.
|
||||
|
||||
If the given component represents a particular plugin parameter, then this
|
||||
method should return the index of that parameter. If not, it should return -1.
|
||||
Currently only AAX plugins will call this, and implementing it is optional.
|
||||
*/
|
||||
virtual int getControlParameterIndex (Component&);
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditor)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
+1531
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPROCESSORGRAPH_H_INCLUDED
|
||||
#define JUCE_AUDIOPROCESSORGRAPH_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A type of AudioProcessor which plays back a graph of other AudioProcessors.
|
||||
|
||||
Use one of these objects if you want to wire-up a set of AudioProcessors
|
||||
and play back the result.
|
||||
|
||||
Processors can be added to the graph as "nodes" using addNode(), and once
|
||||
added, you can connect any of their input or output channels to other
|
||||
nodes using addConnection().
|
||||
|
||||
To play back a graph through an audio device, you might want to use an
|
||||
AudioProcessorPlayer object.
|
||||
*/
|
||||
class JUCE_API AudioProcessorGraph : public AudioProcessor,
|
||||
private AsyncUpdater
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty graph. */
|
||||
AudioProcessorGraph();
|
||||
|
||||
/** Destructor.
|
||||
Any processor objects that have been added to the graph will also be deleted.
|
||||
*/
|
||||
~AudioProcessorGraph();
|
||||
|
||||
//==============================================================================
|
||||
/** Represents one of the nodes, or processors, in an AudioProcessorGraph.
|
||||
|
||||
To create a node, call AudioProcessorGraph::addNode().
|
||||
*/
|
||||
class JUCE_API Node : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** The ID number assigned to this node.
|
||||
This is assigned by the graph that owns it, and can't be changed.
|
||||
*/
|
||||
const uint32 nodeId;
|
||||
|
||||
/** The actual processor object that this node represents. */
|
||||
AudioProcessor* getProcessor() const noexcept { return processor; }
|
||||
|
||||
/** A set of user-definable properties that are associated with this node.
|
||||
|
||||
This can be used to attach values to the node for whatever purpose seems
|
||||
useful. For example, you might store an x and y position if your application
|
||||
is displaying the nodes on-screen.
|
||||
*/
|
||||
NamedValueSet properties;
|
||||
|
||||
//==============================================================================
|
||||
/** A convenient typedef for referring to a pointer to a node object. */
|
||||
typedef ReferenceCountedObjectPtr <Node> Ptr;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
friend class AudioProcessorGraph;
|
||||
|
||||
const ScopedPointer<AudioProcessor> processor;
|
||||
bool isPrepared;
|
||||
|
||||
Node (uint32 nodeId, AudioProcessor*) noexcept;
|
||||
|
||||
void setParentGraph (AudioProcessorGraph*) const;
|
||||
void prepare (double sampleRate, int blockSize, AudioProcessorGraph*);
|
||||
void unprepare();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Node)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Represents a connection between two channels of two nodes in an AudioProcessorGraph.
|
||||
|
||||
To create a connection, use AudioProcessorGraph::addConnection().
|
||||
*/
|
||||
struct JUCE_API Connection
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
Connection (uint32 sourceNodeId, int sourceChannelIndex,
|
||||
uint32 destNodeId, int destChannelIndex) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** The ID number of the node which is the input source for this connection.
|
||||
@see AudioProcessorGraph::getNodeForId
|
||||
*/
|
||||
uint32 sourceNodeId;
|
||||
|
||||
/** The index of the output channel of the source node from which this
|
||||
connection takes its data.
|
||||
|
||||
If this value is the special number AudioProcessorGraph::midiChannelIndex, then
|
||||
it is referring to the source node's midi output. Otherwise, it is the zero-based
|
||||
index of an audio output channel in the source node.
|
||||
*/
|
||||
int sourceChannelIndex;
|
||||
|
||||
/** The ID number of the node which is the destination for this connection.
|
||||
@see AudioProcessorGraph::getNodeForId
|
||||
*/
|
||||
uint32 destNodeId;
|
||||
|
||||
/** The index of the input channel of the destination node to which this
|
||||
connection delivers its data.
|
||||
|
||||
If this value is the special number AudioProcessorGraph::midiChannelIndex, then
|
||||
it is referring to the destination node's midi input. Otherwise, it is the zero-based
|
||||
index of an audio input channel in the destination node.
|
||||
*/
|
||||
int destChannelIndex;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_LEAK_DETECTOR (Connection)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Deletes all nodes and connections from this graph.
|
||||
Any processor objects in the graph will be deleted.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/** Returns the number of nodes in the graph. */
|
||||
int getNumNodes() const { return nodes.size(); }
|
||||
|
||||
/** Returns a pointer to one of the nodes in the graph.
|
||||
This will return nullptr if the index is out of range.
|
||||
@see getNodeForId
|
||||
*/
|
||||
Node* getNode (const int index) const { 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.
|
||||
@see getNode
|
||||
*/
|
||||
Node* getNodeForId (const uint32 nodeId) const;
|
||||
|
||||
/** Adds a node to the graph.
|
||||
|
||||
This creates a new node in the graph, for the specified processor. Once you have
|
||||
added a processor to the graph, the graph owns it and will delete it later when
|
||||
it is no longer needed.
|
||||
|
||||
The optional nodeId parameter lets you specify an ID to use for the node, but
|
||||
if the value is already in use, this new node will overwrite the old one.
|
||||
|
||||
If this succeeds, it returns a pointer to the newly-created node.
|
||||
*/
|
||||
Node* addNode (AudioProcessor* newProcessor, uint32 nodeId = 0);
|
||||
|
||||
/** Deletes a node within the graph which has the specified ID.
|
||||
|
||||
This will also delete any connections that are attached to this node.
|
||||
*/
|
||||
bool removeNode (uint32 nodeId);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of connections in the graph. */
|
||||
int getNumConnections() const { return connections.size(); }
|
||||
|
||||
/** Returns a pointer to one of the connections in the graph. */
|
||||
const Connection* getConnection (int index) const { return connections [index]; }
|
||||
|
||||
/** Searches for a connection between some specified channels.
|
||||
If no such connection is found, this returns nullptr.
|
||||
*/
|
||||
const Connection* getConnectionBetween (uint32 sourceNodeId,
|
||||
int sourceChannelIndex,
|
||||
uint32 destNodeId,
|
||||
int destChannelIndex) const;
|
||||
|
||||
/** Returns true if there is a connection between any of the channels of
|
||||
two specified nodes.
|
||||
*/
|
||||
bool isConnected (uint32 possibleSourceNodeId,
|
||||
uint32 possibleDestNodeId) const;
|
||||
|
||||
/** Returns true if it would be legal to connect the specified points. */
|
||||
bool canConnect (uint32 sourceNodeId, int sourceChannelIndex,
|
||||
uint32 destNodeId, int destChannelIndex) const;
|
||||
|
||||
/** Attempts to connect two specified channels of two nodes.
|
||||
|
||||
If this isn't allowed (e.g. because you're trying to connect a midi channel
|
||||
to an audio one or other such nonsense), then it'll return false.
|
||||
*/
|
||||
bool addConnection (uint32 sourceNodeId, int sourceChannelIndex,
|
||||
uint32 destNodeId, int destChannelIndex);
|
||||
|
||||
/** Deletes the connection with the specified index. */
|
||||
void removeConnection (int index);
|
||||
|
||||
/** Deletes any connection between two specified points.
|
||||
Returns true if a connection was actually deleted.
|
||||
*/
|
||||
bool removeConnection (uint32 sourceNodeId, int sourceChannelIndex,
|
||||
uint32 destNodeId, int destChannelIndex);
|
||||
|
||||
/** Removes all connections from the specified node. */
|
||||
bool disconnectNode (uint32 nodeId);
|
||||
|
||||
/** Returns true if the given connection's channel numbers map on to valid
|
||||
channels at each end.
|
||||
Even if a connection is valid when created, its status could change if
|
||||
a node changes its channel config.
|
||||
*/
|
||||
bool isConnectionLegal (const Connection* connection) const;
|
||||
|
||||
/** Performs a sanity checks of all the connections.
|
||||
|
||||
This might be useful if some of the processors are doing things like changing
|
||||
their channel counts, which could render some connections obsolete.
|
||||
*/
|
||||
bool removeIllegalConnections();
|
||||
|
||||
//==============================================================================
|
||||
/** A special number that represents the midi channel of a node.
|
||||
|
||||
This is used as a channel index value if you want to refer to the midi input
|
||||
or output instead of an audio channel.
|
||||
*/
|
||||
static const int midiChannelIndex;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** A special type of AudioProcessor that can live inside an AudioProcessorGraph
|
||||
in order to use the audio that comes into and out of the graph itself.
|
||||
|
||||
If you create an AudioGraphIOProcessor in "input" mode, it will act as a
|
||||
node in the graph which delivers the audio that is coming into the parent
|
||||
graph. This allows you to stream the data to other nodes and process the
|
||||
incoming audio.
|
||||
|
||||
Likewise, one of these in "output" mode can be sent data which it will add to
|
||||
the sum of data being sent to the graph's output.
|
||||
|
||||
@see AudioProcessorGraph
|
||||
*/
|
||||
class JUCE_API AudioGraphIOProcessor : public AudioPluginInstance
|
||||
{
|
||||
public:
|
||||
/** Specifies the mode in which this processor will operate.
|
||||
*/
|
||||
enum IODeviceType
|
||||
{
|
||||
audioInputNode, /**< In this mode, the processor has output channels
|
||||
representing all the audio input channels that are
|
||||
coming into its parent audio graph. */
|
||||
audioOutputNode, /**< In this mode, the processor has input channels
|
||||
representing all the audio output channels that are
|
||||
going out of its parent audio graph. */
|
||||
midiInputNode, /**< In this mode, the processor has a midi output which
|
||||
delivers the same midi data that is arriving at its
|
||||
parent graph. */
|
||||
midiOutputNode /**< In this mode, the processor has a midi input and
|
||||
any data sent to it will be passed out of the parent
|
||||
graph. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the mode of this processor. */
|
||||
IODeviceType getType() const { return type; }
|
||||
|
||||
/** Returns the parent graph to which this processor belongs, or nullptr if it
|
||||
hasn't yet been added to one. */
|
||||
AudioProcessorGraph* getParentGraph() const { return graph; }
|
||||
|
||||
/** True if this is an audio or midi input. */
|
||||
bool isInput() const;
|
||||
/** True if this is an audio or midi output. */
|
||||
bool isOutput() const;
|
||||
|
||||
//==============================================================================
|
||||
AudioGraphIOProcessor (const IODeviceType type);
|
||||
~AudioGraphIOProcessor();
|
||||
|
||||
const String getName() const;
|
||||
void fillInPluginDescription (PluginDescription&) const;
|
||||
|
||||
void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock);
|
||||
void releaseResources();
|
||||
void processBlock (AudioSampleBuffer&, MidiBuffer&);
|
||||
|
||||
const String getInputChannelName (int channelIndex) const;
|
||||
const String getOutputChannelName (int channelIndex) const;
|
||||
bool isInputChannelStereoPair (int index) const;
|
||||
bool isOutputChannelStereoPair (int index) const;
|
||||
bool silenceInProducesSilenceOut() const;
|
||||
double getTailLengthSeconds() const;
|
||||
bool acceptsMidi() const;
|
||||
bool producesMidi() const;
|
||||
|
||||
bool hasEditor() const;
|
||||
AudioProcessorEditor* createEditor();
|
||||
|
||||
int getNumParameters();
|
||||
const String getParameterName (int);
|
||||
float getParameter (int);
|
||||
const String getParameterText (int);
|
||||
void setParameter (int, float);
|
||||
|
||||
int getNumPrograms();
|
||||
int getCurrentProgram();
|
||||
void setCurrentProgram (int);
|
||||
const String getProgramName (int);
|
||||
void changeProgramName (int, const String&);
|
||||
|
||||
void getStateInformation (juce::MemoryBlock& destData);
|
||||
void setStateInformation (const void* data, int sizeInBytes);
|
||||
|
||||
/** @internal */
|
||||
void setParentGraph (AudioProcessorGraph*);
|
||||
|
||||
private:
|
||||
const IODeviceType type;
|
||||
AudioProcessorGraph* graph;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioGraphIOProcessor)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// AudioProcessor methods:
|
||||
|
||||
const String getName() const;
|
||||
|
||||
void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock);
|
||||
void releaseResources();
|
||||
void processBlock (AudioSampleBuffer&, MidiBuffer&);
|
||||
void reset();
|
||||
|
||||
const String getInputChannelName (int channelIndex) const;
|
||||
const String getOutputChannelName (int channelIndex) const;
|
||||
bool isInputChannelStereoPair (int index) const;
|
||||
bool isOutputChannelStereoPair (int index) const;
|
||||
bool silenceInProducesSilenceOut() const;
|
||||
double getTailLengthSeconds() const;
|
||||
|
||||
bool acceptsMidi() const;
|
||||
bool producesMidi() const;
|
||||
|
||||
bool hasEditor() const { return false; }
|
||||
AudioProcessorEditor* createEditor() { return nullptr; }
|
||||
|
||||
int getNumParameters() { return 0; }
|
||||
const String getParameterName (int) { return String(); }
|
||||
float getParameter (int) { return 0; }
|
||||
const String getParameterText (int) { return String(); }
|
||||
void setParameter (int, float) { }
|
||||
|
||||
int getNumPrograms() { return 0; }
|
||||
int getCurrentProgram() { return 0; }
|
||||
void setCurrentProgram (int) { }
|
||||
const String getProgramName (int) { return String(); }
|
||||
void changeProgramName (int, const String&) { }
|
||||
|
||||
void getStateInformation (juce::MemoryBlock&);
|
||||
void setStateInformation (const void* data, int sizeInBytes);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
ReferenceCountedArray<Node> nodes;
|
||||
OwnedArray<Connection> connections;
|
||||
uint32 lastNodeId;
|
||||
AudioSampleBuffer renderingBuffers;
|
||||
OwnedArray<MidiBuffer> midiBuffers;
|
||||
Array<void*> renderingOps;
|
||||
|
||||
friend class AudioGraphIOProcessor;
|
||||
AudioSampleBuffer* currentAudioInputBuffer;
|
||||
AudioSampleBuffer currentAudioOutputBuffer;
|
||||
MidiBuffer* currentMidiInputBuffer;
|
||||
MidiBuffer currentMidiOutputBuffer;
|
||||
|
||||
void handleAsyncUpdate() override;
|
||||
void clearRenderingSequence();
|
||||
void buildRenderingSequence();
|
||||
bool isAnInputTo (uint32 possibleInputId, uint32 possibleDestinationId, int recursionCheck) const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorGraph)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_AUDIOPROCESSORGRAPH_H_INCLUDED
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPROCESSORLISTENER_H_INCLUDED
|
||||
#define JUCE_AUDIOPROCESSORLISTENER_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for listeners that want to know about changes to an AudioProcessor.
|
||||
|
||||
Use AudioProcessor::addListener() to register your listener with an AudioProcessor.
|
||||
|
||||
@see AudioProcessor
|
||||
*/
|
||||
class JUCE_API AudioProcessorListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor. */
|
||||
virtual ~AudioProcessorListener() {}
|
||||
|
||||
//==============================================================================
|
||||
/** Receives a callback when a parameter is changed.
|
||||
|
||||
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
|
||||
this event on your message thread, use this callback to trigger an AsyncUpdater
|
||||
or ChangeBroadcaster which you can respond to on the message thread.
|
||||
*/
|
||||
virtual void audioProcessorParameterChanged (AudioProcessor* processor,
|
||||
int parameterIndex,
|
||||
float newValue) = 0;
|
||||
|
||||
/** 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
|
||||
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
|
||||
to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the
|
||||
message thread.
|
||||
*/
|
||||
virtual void audioProcessorChanged (AudioProcessor* processor) = 0;
|
||||
|
||||
/** Indicates that a parameter change gesture has started.
|
||||
|
||||
E.g. if the user is dragging a slider, this would be called when they first
|
||||
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
|
||||
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
|
||||
to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the
|
||||
message thread.
|
||||
|
||||
@see audioProcessorParameterChangeGestureEnd
|
||||
*/
|
||||
virtual void audioProcessorParameterChangeGestureBegin (AudioProcessor* processor,
|
||||
int parameterIndex);
|
||||
|
||||
/** Indicates that a parameter change gesture has finished.
|
||||
|
||||
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
|
||||
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
|
||||
to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the
|
||||
message thread.
|
||||
|
||||
@see audioProcessorParameterChangeGestureBegin
|
||||
*/
|
||||
virtual void audioProcessorParameterChangeGestureEnd (AudioProcessor* processor,
|
||||
int parameterIndex);
|
||||
};
|
||||
|
||||
#endif // JUCE_AUDIOPROCESSORLISTENER_H_INCLUDED
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIOPROCESSORPARAMETER_H_INCLUDED
|
||||
#define JUCE_AUDIOPROCESSORPARAMETER_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** An abstract base class for parameter objects that can be added to an
|
||||
AudioProcessor.
|
||||
|
||||
@see AudioProcessor::addParameter
|
||||
*/
|
||||
class JUCE_API AudioProcessorParameter
|
||||
{
|
||||
public:
|
||||
AudioProcessorParameter() noexcept;
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~AudioProcessorParameter();
|
||||
|
||||
/** Called by the host to find out the value of this parameter.
|
||||
|
||||
Hosts will expect the value returned to be between 0 and 1.0.
|
||||
|
||||
This could be called quite frequently, so try to make your code efficient.
|
||||
It's also likely to be called by non-UI threads, so the code in here should
|
||||
be thread-aware.
|
||||
*/
|
||||
virtual float getValue() const = 0;
|
||||
|
||||
/** The host will call this method to change the value of one of the filter's parameters.
|
||||
|
||||
The host may call this at any time, including during the audio processing
|
||||
callback, so the filter has to process this very fast and avoid blocking.
|
||||
|
||||
If you want to set the value of a parameter internally, e.g. from your
|
||||
editor component, then don't call this directly - instead, use the
|
||||
setValueNotifyingHost() method, which will also send a message to
|
||||
the host telling it about the change. If the message isn't sent, the host
|
||||
won't be able to automate your parameters properly.
|
||||
|
||||
The value passed will be between 0 and 1.0.
|
||||
*/
|
||||
virtual void setValue (float newValue) = 0;
|
||||
|
||||
/** Your filter can call this when it needs to change one of its parameters.
|
||||
|
||||
This could happen when the editor or some other internal operation changes
|
||||
a parameter. This method will call the setParameter() method to change the
|
||||
value, and will then send a message to the host telling it about the change.
|
||||
|
||||
Note that to make sure the host correctly handles automation, you should call
|
||||
the beginChangeGesture() and endChangeGesture() methods to tell the host when
|
||||
the user has started and stopped changing the parameter.
|
||||
*/
|
||||
void setValueNotifyingHost (float newValue);
|
||||
|
||||
/** Sends a signal to the host to tell it that the user is about to start changing this
|
||||
parameter.
|
||||
This allows the host to know when a parameter is actively being held by the user, and
|
||||
it may use this information to help it record automation.
|
||||
If you call this, it must be matched by a later call to endChangeGesture().
|
||||
*/
|
||||
void beginChangeGesture();
|
||||
|
||||
/** Tells the host that the user has finished changing this parameter.
|
||||
This allows the host to know when a parameter is actively being held by the user,
|
||||
and it may use this information to help it record automation.
|
||||
A call to this method must follow a call to beginChangeGesture().
|
||||
*/
|
||||
void endChangeGesture();
|
||||
|
||||
/** This should return the default value for this parameter. */
|
||||
virtual float getDefaultValue() const = 0;
|
||||
|
||||
/** Returns the name to display for this parameter, which should be made
|
||||
to fit within the given string length.
|
||||
*/
|
||||
virtual String getName (int maximumStringLength) const = 0;
|
||||
|
||||
/** Some parameters may be able to return a label string for
|
||||
their units. For example "Hz" or "%".
|
||||
*/
|
||||
virtual String getLabel() const = 0;
|
||||
|
||||
/** Returns the number of discrete interval steps that this parameter's range
|
||||
should be quantised into.
|
||||
|
||||
If you want a continuous range of values, don't override this method, and allow
|
||||
the default implementation to return AudioProcessor::getDefaultNumParameterSteps().
|
||||
If your parameter is boolean, then you may want to make this return 2.
|
||||
The value that is returned may or may not be used, depending on the host.
|
||||
*/
|
||||
virtual int getNumSteps() const;
|
||||
|
||||
/** Returns a textual version of the supplied 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;
|
||||
|
||||
/** Should parse a string and return the appropriate value for it. */
|
||||
virtual float getValueForText (const String& text) const = 0;
|
||||
|
||||
/** This can be overridden to tell the host that this parameter operates in the
|
||||
reverse direction.
|
||||
(Not all plugin formats or hosts will actually use this information).
|
||||
*/
|
||||
virtual bool isOrientationInverted() const;
|
||||
|
||||
/** Returns true if the host can automate this parameter.
|
||||
By default, this returns true.
|
||||
*/
|
||||
virtual bool isAutomatable() const;
|
||||
|
||||
/** Should return true if this parameter is a "meta" parameter.
|
||||
A meta-parameter is a parameter that changes other params. It is used
|
||||
by some hosts (e.g. AudioUnit hosts).
|
||||
By default this returns false.
|
||||
*/
|
||||
virtual bool isMetaParameter() const;
|
||||
|
||||
/** Returns the index of this parameter in its parent processor's parameter list. */
|
||||
int getParameterIndex() const noexcept { return parameterIndex; }
|
||||
|
||||
private:
|
||||
friend class AudioProcessor;
|
||||
AudioProcessor* processor;
|
||||
int parameterIndex;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameter)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_AUDIOPROCESSORPARAMETER_H_INCLUDED
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
class ProcessorParameterPropertyComp : public PropertyComponent,
|
||||
private AudioProcessorListener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
ProcessorParameterPropertyComp (const String& name, AudioProcessor& p, int paramIndex)
|
||||
: PropertyComponent (name),
|
||||
owner (p),
|
||||
index (paramIndex),
|
||||
paramHasChanged (false),
|
||||
slider (p, paramIndex)
|
||||
{
|
||||
startTimer (100);
|
||||
addAndMakeVisible (slider);
|
||||
owner.addListener (this);
|
||||
}
|
||||
|
||||
~ProcessorParameterPropertyComp()
|
||||
{
|
||||
owner.removeListener (this);
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
paramHasChanged = false;
|
||||
|
||||
if (slider.getThumbBeingDragged() < 0)
|
||||
slider.setValue (owner.getParameter (index), dontSendNotification);
|
||||
|
||||
slider.updateText();
|
||||
}
|
||||
|
||||
void audioProcessorChanged (AudioProcessor*) override {}
|
||||
|
||||
void audioProcessorParameterChanged (AudioProcessor*, int parameterIndex, float) override
|
||||
{
|
||||
if (parameterIndex == index)
|
||||
paramHasChanged = true;
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
if (paramHasChanged)
|
||||
{
|
||||
refresh();
|
||||
startTimerHz (50);
|
||||
}
|
||||
else
|
||||
{
|
||||
startTimer (jmin (1000 / 4, getTimerInterval() + 10));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class ParamSlider : public Slider
|
||||
{
|
||||
public:
|
||||
ParamSlider (AudioProcessor& p, int paramIndex) : owner (p), index (paramIndex)
|
||||
{
|
||||
const int steps = owner.getParameterNumSteps (index);
|
||||
|
||||
if (steps > 1 && steps < 0x7fffffff)
|
||||
setRange (0.0, 1.0, 1.0 / (steps - 1.0));
|
||||
else
|
||||
setRange (0.0, 1.0);
|
||||
|
||||
setSliderStyle (Slider::LinearBar);
|
||||
setTextBoxIsEditable (false);
|
||||
setScrollWheelEnabled (true);
|
||||
}
|
||||
|
||||
void valueChanged() override
|
||||
{
|
||||
const float newVal = (float) getValue();
|
||||
|
||||
if (owner.getParameter (index) != newVal)
|
||||
{
|
||||
owner.setParameterNotifyingHost (index, newVal);
|
||||
updateText();
|
||||
}
|
||||
}
|
||||
|
||||
String getTextFromValue (double /*value*/) override
|
||||
{
|
||||
return owner.getParameterText (index) + " " + owner.getParameterLabel (index).trimEnd();
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
AudioProcessor& owner;
|
||||
const int index;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamSlider)
|
||||
};
|
||||
|
||||
AudioProcessor& owner;
|
||||
const int index;
|
||||
bool volatile paramHasChanged;
|
||||
ParamSlider slider;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProcessorParameterPropertyComp)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const p)
|
||||
: AudioProcessorEditor (p)
|
||||
{
|
||||
jassert (p != nullptr);
|
||||
setOpaque (true);
|
||||
|
||||
addAndMakeVisible (panel);
|
||||
|
||||
Array <PropertyComponent*> params;
|
||||
|
||||
const int numParams = p->getNumParameters();
|
||||
int totalHeight = 0;
|
||||
|
||||
for (int i = 0; i < numParams; ++i)
|
||||
{
|
||||
String name (p->getParameterName (i));
|
||||
if (name.trim().isEmpty())
|
||||
name = "Unnamed";
|
||||
|
||||
ProcessorParameterPropertyComp* const pc = new ProcessorParameterPropertyComp (name, *p, i);
|
||||
params.add (pc);
|
||||
totalHeight += pc->getPreferredHeight();
|
||||
}
|
||||
|
||||
panel.addProperties (params);
|
||||
|
||||
setSize (400, jlimit (25, 400, totalHeight));
|
||||
}
|
||||
|
||||
GenericAudioProcessorEditor::~GenericAudioProcessorEditor()
|
||||
{
|
||||
}
|
||||
|
||||
void GenericAudioProcessorEditor::paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (Colours::white);
|
||||
}
|
||||
|
||||
void GenericAudioProcessorEditor::resized()
|
||||
{
|
||||
panel.setBounds (getLocalBounds());
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_GENERICAUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
#define JUCE_GENERICAUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A type of UI component that displays the parameters of an AudioProcessor as
|
||||
a simple list of sliders.
|
||||
|
||||
This can be used for showing an editor for a processor that doesn't supply
|
||||
its own custom editor.
|
||||
|
||||
@see AudioProcessor
|
||||
*/
|
||||
class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
GenericAudioProcessorEditor (AudioProcessor* owner);
|
||||
~GenericAudioProcessorEditor();
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics&) override;
|
||||
void resized() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
PropertyPanel panel;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericAudioProcessorEditor)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_GENERICAUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
PluginDescription::PluginDescription()
|
||||
: uid (0),
|
||||
isInstrument (false),
|
||||
numInputChannels (0),
|
||||
numOutputChannels (0),
|
||||
hasSharedContainer (false)
|
||||
{
|
||||
}
|
||||
|
||||
PluginDescription::~PluginDescription()
|
||||
{
|
||||
}
|
||||
|
||||
PluginDescription::PluginDescription (const PluginDescription& other)
|
||||
: name (other.name),
|
||||
descriptiveName (other.descriptiveName),
|
||||
pluginFormatName (other.pluginFormatName),
|
||||
category (other.category),
|
||||
manufacturerName (other.manufacturerName),
|
||||
version (other.version),
|
||||
fileOrIdentifier (other.fileOrIdentifier),
|
||||
lastFileModTime (other.lastFileModTime),
|
||||
uid (other.uid),
|
||||
isInstrument (other.isInstrument),
|
||||
numInputChannels (other.numInputChannels),
|
||||
numOutputChannels (other.numOutputChannels),
|
||||
hasSharedContainer (other.hasSharedContainer)
|
||||
{
|
||||
}
|
||||
|
||||
PluginDescription& PluginDescription::operator= (const PluginDescription& other)
|
||||
{
|
||||
name = other.name;
|
||||
descriptiveName = other.descriptiveName;
|
||||
pluginFormatName = other.pluginFormatName;
|
||||
category = other.category;
|
||||
manufacturerName = other.manufacturerName;
|
||||
version = other.version;
|
||||
fileOrIdentifier = other.fileOrIdentifier;
|
||||
uid = other.uid;
|
||||
isInstrument = other.isInstrument;
|
||||
lastFileModTime = other.lastFileModTime;
|
||||
numInputChannels = other.numInputChannels;
|
||||
numOutputChannels = other.numOutputChannels;
|
||||
hasSharedContainer = other.hasSharedContainer;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept
|
||||
{
|
||||
return fileOrIdentifier == other.fileOrIdentifier
|
||||
&& uid == other.uid;
|
||||
}
|
||||
|
||||
static String getPluginDescSuffix (const PluginDescription& d)
|
||||
{
|
||||
return "-" + String::toHexString (d.fileOrIdentifier.hashCode())
|
||||
+ "-" + String::toHexString (d.uid);
|
||||
}
|
||||
|
||||
bool PluginDescription::matchesIdentifierString (const String& identifierString) const
|
||||
{
|
||||
return identifierString.endsWithIgnoreCase (getPluginDescSuffix (*this));
|
||||
}
|
||||
|
||||
String PluginDescription::createIdentifierString() const
|
||||
{
|
||||
return pluginFormatName + "-" + name + getPluginDescSuffix (*this);
|
||||
}
|
||||
|
||||
XmlElement* PluginDescription::createXml() const
|
||||
{
|
||||
XmlElement* const e = new XmlElement ("PLUGIN");
|
||||
e->setAttribute ("name", name);
|
||||
if (descriptiveName != name)
|
||||
e->setAttribute ("descriptiveName", descriptiveName);
|
||||
|
||||
e->setAttribute ("format", pluginFormatName);
|
||||
e->setAttribute ("category", category);
|
||||
e->setAttribute ("manufacturer", manufacturerName);
|
||||
e->setAttribute ("version", version);
|
||||
e->setAttribute ("file", fileOrIdentifier);
|
||||
e->setAttribute ("uid", String::toHexString (uid));
|
||||
e->setAttribute ("isInstrument", isInstrument);
|
||||
e->setAttribute ("fileTime", String::toHexString (lastFileModTime.toMilliseconds()));
|
||||
e->setAttribute ("numInputs", numInputChannels);
|
||||
e->setAttribute ("numOutputs", numOutputChannels);
|
||||
e->setAttribute ("isShell", hasSharedContainer);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool PluginDescription::loadFromXml (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName ("PLUGIN"))
|
||||
{
|
||||
name = xml.getStringAttribute ("name");
|
||||
descriptiveName = xml.getStringAttribute ("descriptiveName", name);
|
||||
pluginFormatName = xml.getStringAttribute ("format");
|
||||
category = xml.getStringAttribute ("category");
|
||||
manufacturerName = xml.getStringAttribute ("manufacturer");
|
||||
version = xml.getStringAttribute ("version");
|
||||
fileOrIdentifier = xml.getStringAttribute ("file");
|
||||
uid = xml.getStringAttribute ("uid").getHexValue32();
|
||||
isInstrument = xml.getBoolAttribute ("isInstrument", false);
|
||||
lastFileModTime = Time (xml.getStringAttribute ("fileTime").getHexValue64());
|
||||
numInputChannels = xml.getIntAttribute ("numInputs");
|
||||
numOutputChannels = xml.getIntAttribute ("numOutputs");
|
||||
hasSharedContainer = xml.getBoolAttribute ("isShell", false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_PLUGINDESCRIPTION_H_INCLUDED
|
||||
#define JUCE_PLUGINDESCRIPTION_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A small class to represent some facts about a particular type of plug-in.
|
||||
|
||||
This class is for storing and managing the details about a plug-in without
|
||||
actually having to load an instance of it.
|
||||
|
||||
A KnownPluginList contains a list of PluginDescription objects.
|
||||
|
||||
@see KnownPluginList
|
||||
*/
|
||||
class JUCE_API PluginDescription
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PluginDescription();
|
||||
PluginDescription (const PluginDescription& other);
|
||||
PluginDescription& operator= (const PluginDescription& other);
|
||||
~PluginDescription();
|
||||
|
||||
//==============================================================================
|
||||
/** The name of the plug-in. */
|
||||
String name;
|
||||
|
||||
/** A more descriptive name for the plug-in.
|
||||
This may be the same as the 'name' field, but some plug-ins may provide an
|
||||
alternative name.
|
||||
*/
|
||||
String descriptiveName;
|
||||
|
||||
/** The plug-in format, e.g. "VST", "AudioUnit", etc. */
|
||||
String pluginFormatName;
|
||||
|
||||
/** A category, such as "Dynamics", "Reverbs", etc. */
|
||||
String category;
|
||||
|
||||
/** The manufacturer. */
|
||||
String manufacturerName;
|
||||
|
||||
/** The version. This string doesn't have any particular format. */
|
||||
String version;
|
||||
|
||||
/** Either the file containing the plug-in module, or some other unique way
|
||||
of identifying it.
|
||||
|
||||
E.g. for an AU, this would be an ID string that the component manager
|
||||
could use to retrieve the plug-in. For a VST, it's the file path.
|
||||
*/
|
||||
String fileOrIdentifier;
|
||||
|
||||
/** The last time the plug-in file was changed.
|
||||
This is handy when scanning for new or changed plug-ins.
|
||||
*/
|
||||
Time lastFileModTime;
|
||||
|
||||
/** A unique ID for the plug-in.
|
||||
|
||||
Note that this might not be unique between formats, e.g. a VST and some
|
||||
other format might actually have the same id.
|
||||
|
||||
@see createIdentifierString
|
||||
*/
|
||||
int uid;
|
||||
|
||||
/** True if the plug-in identifies itself as a synthesiser. */
|
||||
bool isInstrument;
|
||||
|
||||
/** The number of inputs. */
|
||||
int numInputChannels;
|
||||
|
||||
/** The number of outputs. */
|
||||
int numOutputChannels;
|
||||
|
||||
/** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */
|
||||
bool hasSharedContainer;
|
||||
|
||||
/** Returns true if the two descriptions refer to the same plug-in.
|
||||
|
||||
This isn't quite as simple as them just having the same file (because of
|
||||
shell plug-ins).
|
||||
*/
|
||||
bool isDuplicateOf (const PluginDescription& other) const noexcept;
|
||||
|
||||
/** Return true if this description is equivalent to another one which created the
|
||||
given identifier string.
|
||||
|
||||
Note that this isn't quite as simple as them just calling createIdentifierString()
|
||||
and comparing the strings, because the identifers can differ (thanks to shell plug-ins).
|
||||
*/
|
||||
bool matchesIdentifierString (const String& identifierString) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a string that can be saved and used to uniquely identify the
|
||||
plugin again.
|
||||
|
||||
This contains less info than the XML encoding, and is independent of the
|
||||
plug-in's file location, so can be used to store a plug-in ID for use
|
||||
across different machines.
|
||||
*/
|
||||
String createIdentifierString() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates an XML object containing these details.
|
||||
|
||||
@see loadFromXml
|
||||
*/
|
||||
XmlElement* createXml() const;
|
||||
|
||||
/** Reloads the info in this structure from an XML record that was previously
|
||||
saved with createXML().
|
||||
|
||||
Returns true if the XML was a valid plug-in description.
|
||||
*/
|
||||
bool loadFromXml (const XmlElement& xml);
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_LEAK_DETECTOR (PluginDescription)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_PLUGINDESCRIPTION_H_INCLUDED
|
||||
Reference in New Issue
Block a user