1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

Move files without UI dependencies to juce_audio_processors_headless

This commit is contained in:
reuk 2025-08-15 15:40:51 +01:00
parent 1f5d09d3fc
commit 407cc5b004
No known key found for this signature in database
73 changed files with 115 additions and 80 deletions

View file

@ -1,107 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioPluginFormat::AudioPluginFormat() {}
AudioPluginFormat::~AudioPluginFormat() {}
std::unique_ptr<AudioPluginInstance> AudioPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
double initialSampleRate,
int initialBufferSize)
{
String errorMessage;
return createInstanceFromDescription (desc, initialSampleRate, initialBufferSize, errorMessage);
}
std::unique_ptr<AudioPluginInstance> AudioPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
double initialSampleRate,
int initialBufferSize,
String& errorMessage)
{
if (MessageManager::getInstance()->isThisTheMessageThread()
&& requiresUnblockedMessageThreadDuringCreation (desc))
{
errorMessage = NEEDS_TRANS ("This plug-in cannot be instantiated synchronously");
return {};
}
WaitableEvent finishedSignal;
std::unique_ptr<AudioPluginInstance> instance;
auto callback = [&] (std::unique_ptr<AudioPluginInstance> p, const String& error)
{
errorMessage = error;
instance = std::move (p);
finishedSignal.signal();
};
if (! MessageManager::getInstance()->isThisTheMessageThread())
createPluginInstanceAsync (desc, initialSampleRate, initialBufferSize, std::move (callback));
else
createPluginInstance (desc, initialSampleRate, initialBufferSize, std::move (callback));
finishedSignal.wait();
return instance;
}
struct AudioPluginFormat::AsyncCreateMessage final : public Message
{
AsyncCreateMessage (const PluginDescription& d, double sr, int size, PluginCreationCallback call)
: desc (d), sampleRate (sr), bufferSize (size), callbackToUse (std::move (call))
{
}
PluginDescription desc;
double sampleRate;
int bufferSize;
PluginCreationCallback callbackToUse;
};
void AudioPluginFormat::createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate, int initialBufferSize,
PluginCreationCallback callback)
{
jassert (callback != nullptr);
postMessage (new AsyncCreateMessage (description, initialSampleRate, initialBufferSize, std::move (callback)));
}
void AudioPluginFormat::handleMessage (const Message& message)
{
if (auto m = dynamic_cast<const AsyncCreateMessage*> (&message))
createPluginInstance (m->desc, m->sampleRate, m->bufferSize, std::move (m->callbackToUse));
}
} // namespace juce

View file

@ -1,183 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc.
@see AudioPluginFormatManager
@tags{Audio}
*/
class JUCE_API AudioPluginFormat : private MessageListener
{
public:
/** Destructor. */
~AudioPluginFormat() override;
//==============================================================================
/** Returns the format name.
E.g. "VST", "AudioUnit", etc.
*/
virtual String getName() const = 0;
/** This tries to create descriptions for all the plugin types available in
a binary module file.
The file will be some kind of DLL or bundle.
Normally there will only be one type returned, but some plugins
(e.g. VST shells) can use a single DLL to create a set of different plugin
subtypes, so in that case, each subtype is returned as a separate object.
*/
virtual void findAllTypesForFile (OwnedArray<PluginDescription>& results,
const String& fileOrIdentifier) = 0;
/** Tries to recreate a type from a previously generated PluginDescription.
@see AudioPluginFormatManager::createInstance
*/
std::unique_ptr<AudioPluginInstance> createInstanceFromDescription (const PluginDescription&,
double initialSampleRate,
int initialBufferSize);
/** Same as above but with the possibility of returning an error message.
@see AudioPluginFormatManager::createInstance
*/
std::unique_ptr<AudioPluginInstance> createInstanceFromDescription (const PluginDescription&,
double initialSampleRate,
int initialBufferSize,
String& errorMessage);
/** A callback lambda that is passed to createPluginInstanceAsync() */
using PluginCreationCallback = std::function<void (std::unique_ptr<AudioPluginInstance>, const String&)>;
/** Tries to recreate a type from a previously generated PluginDescription.
When the plugin has been created, it will be passed to the caller via an
asynchronous call to the PluginCreationCallback lambda that was provided.
@see AudioPluginFormatManager::createPluginInstanceAsync
*/
void createPluginInstanceAsync (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
PluginCreationCallback);
/** Should do a quick check to see if this file or directory might be a plugin of
this format.
This is for searching for potential files, so it shouldn't actually try to
load the plugin or do anything time-consuming.
*/
virtual bool fileMightContainThisPluginType (const String& fileOrIdentifier) = 0;
/** Returns a readable version of the name of the plugin that this identifier refers to. */
virtual String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) = 0;
/** Returns true if this plugin's version or date has changed and it should be re-checked. */
virtual bool pluginNeedsRescanning (const PluginDescription&) = 0;
/** Checks whether this plugin could possibly be loaded.
It doesn't actually need to load it, just to check whether the file or component
still exists.
*/
virtual bool doesPluginStillExist (const PluginDescription&) = 0;
/** Returns true if this format needs to run a scan to find its list of plugins. */
virtual bool canScanForPlugins() const = 0;
/** Should return true if this format is both safe and quick to scan - i.e. if a file
can be scanned within a few milliseconds on a background thread, without actually
needing to load an executable.
*/
virtual bool isTrivialToScan() const = 0;
/** Searches a suggested set of directories for any plugins in this format.
The path might be ignored, e.g. by AUs, which are found by the OS rather
than manually.
@param directoriesToSearch This specifies which directories shall be
searched for plug-ins.
@param recursive Should the search recursively traverse folders.
@param allowPluginsWhichRequireAsynchronousInstantiation
If this is false then plug-ins which require
asynchronous creation will be excluded.
*/
virtual StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch,
bool recursive,
bool allowPluginsWhichRequireAsynchronousInstantiation = false) = 0;
/** Returns the typical places to look for this kind of plugin.
Note that if this returns no paths, it means that the format doesn't search in
files or folders, e.g. AudioUnits.
*/
virtual FileSearchPath getDefaultLocationsToSearch() = 0;
/** Returns true if instantiation of this plugin type must be done from a non-message thread. */
virtual bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const = 0;
/** A callback lambda that is passed to getARAFactory() */
using ARAFactoryCreationCallback = std::function<void (ARAFactoryResult)>;
/** Tries to create an ::ARAFactoryWrapper for this description.
The result of the operation will be wrapped into an ARAFactoryResult,
which will be passed to a callback object supplied by the caller.
@see AudioPluginFormatManager::createARAFactoryAsync
*/
virtual void createARAFactoryAsync (const PluginDescription&, ARAFactoryCreationCallback callback) { callback ({}); }
protected:
//==============================================================================
friend class AudioPluginFormatManager;
AudioPluginFormat();
/** Implementors must override this function. This is guaranteed to be called on
the message thread. You may call the callback on any thread.
*/
virtual void createPluginInstance (const PluginDescription&, double initialSampleRate,
int initialBufferSize, PluginCreationCallback) = 0;
private:
struct AsyncCreateMessage;
void handleMessage (const Message&) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginFormat)
};
} // namespace juce

View file

@ -1,99 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#if (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX))
namespace juce
{
static void dummyARAInterfaceAssert (ARA::ARAAssertCategory, const void*, const char*)
{}
static ARA::ARAInterfaceConfiguration createInterfaceConfig (const ARA::ARAFactory* araFactory)
{
static auto* assertFunction = &dummyARAInterfaceAssert;
#if ARA_VALIDATE_API_CALLS
assertFunction = &::ARA::ARAInterfaceAssert;
static std::once_flag flag;
std::call_once (flag, [] { ARA::ARASetExternalAssertReference (&assertFunction); });
#endif
return makeARASizedStruct (&ARA::ARAInterfaceConfiguration::assertFunctionAddress,
jmin (araFactory->highestSupportedApiGeneration, (ARA::ARAAPIGeneration) ARA::kARAAPIGeneration_2_X_Draft),
&assertFunction);
}
/* If the provided ARAFactory is not yet in use it constructs a new shared_ptr that will call the
provided onDelete function inside the custom deleter of this new shared_ptr instance.
The onDelete function is responsible for releasing the resources that guarantee the validity of
the wrapped ARAFactory*.
If however the ARAFactory is already in use the function will just return a copy of the already
existing shared_ptr and call the onDelete function immediately. This is to ensure that the
ARAFactory is only uninitialised when no plugin instance can be using it.
On both platforms the onDelete function is used to release resources that ensure that the module
providing the ARAFactory* remains loaded.
*/
static std::shared_ptr<const ARA::ARAFactory> getOrCreateARAFactory (const ARA::ARAFactory* ptr,
std::function<void()> onDelete)
{
JUCE_ASSERT_MESSAGE_THREAD
static std::unordered_map<const ARA::ARAFactory*, std::weak_ptr<const ARA::ARAFactory>> cache;
auto& cachePtr = cache[ptr];
if (const auto obj = cachePtr.lock())
{
onDelete();
return obj;
}
const auto interfaceConfig = createInterfaceConfig (ptr);
ptr->initializeARAWithConfiguration (&interfaceConfig);
const auto obj = std::shared_ptr<const ARA::ARAFactory> (ptr, [deleter = std::move (onDelete)] (const ARA::ARAFactory* factory)
{
factory->uninitializeARA();
deleter();
});
cachePtr = obj;
return obj;
}
}
#endif

View file

@ -1,98 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
namespace ARA
{
struct ARAFactory;
}
namespace juce
{
/** Encapsulates an ARAFactory pointer and makes sure that it remains in a valid state
for the lifetime of the ARAFactoryWrapper object.
@tags{ARA}
*/
class ARAFactoryWrapper
{
public:
ARAFactoryWrapper() = default;
/** @internal
Used by the framework to encapsulate ARAFactory pointers loaded from plugins.
*/
explicit ARAFactoryWrapper (std::shared_ptr<const ARA::ARAFactory> factoryIn) : factory (std::move (factoryIn)) {}
/** Returns the contained ARAFactory pointer, which can be a nullptr.
The validity of the returned pointer is only guaranteed for the lifetime of this wrapper.
*/
const ARA::ARAFactory* get() const noexcept { return factory.get(); }
private:
std::shared_ptr<const ARA::ARAFactory> factory;
};
/** Represents the result of AudioPluginFormatManager::createARAFactoryAsync().
If the operation fails then #araFactory will contain `nullptr`, and #errorMessage may
contain a reason for the failure.
The araFactory member ensures that the module necessary for the correct functioning
of the factory will remain loaded.
@tags{ARA}
*/
struct ARAFactoryResult
{
ARAFactoryWrapper araFactory;
String errorMessage;
};
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-field-initializers")
template <typename Obj, typename Member, typename... Ts>
constexpr Obj makeARASizedStruct (Member Obj::* member, Ts&&... ts)
{
return { reinterpret_cast<uintptr_t> (&(static_cast<const Obj*> (nullptr)->*member)) + sizeof (Member),
std::forward<Ts> (ts)... };
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
} // namespace juce

View file

@ -34,8 +34,6 @@
#if (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX))
#include "juce_ARAHosting.h"
#include <ARA_Library/Dispatch/ARAHostDispatch.cpp>
namespace juce

View file

@ -51,7 +51,8 @@
#include <juce_audio_basics/native/juce_CoreAudioTimeConversions_mac.h>
#include <juce_audio_basics/native/juce_CoreAudioLayouts_mac.h>
#include "juce_AU_Shared.h"
#include <juce_audio_processors/format_types/juce_AU_Shared.h>
#include <juce_audio_processors_headless/format_types/juce_ARACommonInternal.h>
namespace juce
{

View file

@ -1,227 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
JUCE_BEGIN_IGNORE_DEPRECATION_WARNINGS
class LegacyAudioParameter final : public HostedAudioProcessorParameter
{
public:
LegacyAudioParameter (AudioProcessorParameter::Listener& listener,
AudioProcessor& audioProcessorToUse,
int audioParameterIndex)
: processor (&audioProcessorToUse)
{
setOwner (&listener);
setParameterIndex (audioParameterIndex);
jassert (getParameterIndex() < processor->getNumParameters());
}
//==============================================================================
float getValue() const override { return processor->getParameter (getParameterIndex()); }
void setValue (float newValue) override { processor->setParameter (getParameterIndex(), newValue); }
float getDefaultValue() const override { return processor->getParameterDefaultValue (getParameterIndex()); }
String getName (int maxLen) const override { return processor->getParameterName (getParameterIndex(), maxLen); }
String getLabel() const override { return processor->getParameterLabel (getParameterIndex()); }
int getNumSteps() const override { return processor->getParameterNumSteps (getParameterIndex()); }
bool isDiscrete() const override { return processor->isParameterDiscrete (getParameterIndex()); }
bool isBoolean() const override { return false; }
bool isOrientationInverted() const override { return processor->isParameterOrientationInverted (getParameterIndex()); }
bool isAutomatable() const override { return processor->isParameterAutomatable (getParameterIndex()); }
bool isMetaParameter() const override { return processor->isMetaParameter (getParameterIndex()); }
Category getCategory() const override { return processor->getParameterCategory (getParameterIndex()); }
String getCurrentValueAsText() const override { return processor->getParameterText (getParameterIndex()); }
String getParameterID() const override { return processor->getParameterID (getParameterIndex()); }
//==============================================================================
float getValueForText (const String&) const override
{
// legacy parameters do not support this method
jassertfalse;
return 0.0f;
}
String getText (float, int) const override
{
// legacy parameters do not support this method
jassertfalse;
return {};
}
//==============================================================================
static bool isLegacy (AudioProcessorParameter* param) noexcept
{
return (dynamic_cast<LegacyAudioParameter*> (param) != nullptr);
}
static int getParamIndex (AudioProcessor& proc, AudioProcessorParameter* param) noexcept
{
if (auto* legacy = dynamic_cast<LegacyAudioParameter*> (param))
return legacy->getParameterIndex();
auto n = proc.getNumParameters();
jassert (n == proc.getParameters().size());
for (int i = 0; i < n; ++i)
{
if (proc.getParameters()[i] == param)
return i;
}
return -1;
}
static String getParamID (const AudioProcessorParameter* param, bool forceLegacyParamIDs) noexcept
{
if (auto* legacy = dynamic_cast<const LegacyAudioParameter*> (param))
return forceLegacyParamIDs ? String (legacy->getParameterIndex()) : legacy->getParameterID();
if (auto* paramWithID = dynamic_cast<const HostedAudioProcessorParameter*> (param))
{
if (! forceLegacyParamIDs)
return paramWithID->getParameterID();
}
if (param != nullptr)
return String (param->getParameterIndex());
return {};
}
private:
AudioProcessor* processor = nullptr;
};
//==============================================================================
class LegacyAudioParametersWrapper
{
public:
LegacyAudioParametersWrapper() = default;
LegacyAudioParametersWrapper (AudioProcessor& audioProcessor, bool forceLegacyParamIDs)
{
update (audioProcessor, forceLegacyParamIDs);
}
void update (AudioProcessor& audioProcessor, bool forceLegacyParamIDs)
{
clear();
forwarder = AudioProcessor::ParameterChangeForwarder { &audioProcessor };
legacyParamIDs = forceLegacyParamIDs;
auto numParameters = audioProcessor.getNumParameters();
usingManagedParameters = audioProcessor.getParameters().size() == numParameters;
for (int i = 0; i < numParameters; ++i)
{
auto* param = [&]() -> AudioProcessorParameter*
{
if (usingManagedParameters)
return audioProcessor.getParameters()[i];
auto newParam = std::make_unique<LegacyAudioParameter> (forwarder, audioProcessor, i);
auto* result = newParam.get();
ownedGroup.addChild (std::move (newParam));
return result;
}();
params.add (param);
}
processorGroup = usingManagedParameters ? &audioProcessor.getParameterTree()
: nullptr;
}
void clear()
{
forwarder = AudioProcessor::ParameterChangeForwarder { nullptr };
ownedGroup = AudioProcessorParameterGroup();
params.clear();
}
AudioProcessorParameter* getParamForIndex (int index) const
{
if (isPositiveAndBelow (index, params.size()))
return params[index];
return nullptr;
}
String getParamID (AudioProcessor& processor, int idx) const noexcept
{
if (usingManagedParameters && ! legacyParamIDs)
return processor.getParameterID (idx);
return String (idx);
}
const AudioProcessorParameterGroup& getGroup() const
{
return processorGroup != nullptr ? *processorGroup
: ownedGroup;
}
void addNonOwning (AudioProcessorParameter* param)
{
params.add (param);
}
size_t size() const noexcept { return (size_t) params.size(); }
bool isUsingManagedParameters() const noexcept { return usingManagedParameters; }
int getNumParameters() const noexcept { return params.size(); }
AudioProcessorParameter* const* begin() const { return params.begin(); }
AudioProcessorParameter* const* end() const { return params.end(); }
bool contains (AudioProcessorParameter* param) const
{
return params.contains (param);
}
private:
const AudioProcessorParameterGroup* processorGroup = nullptr;
AudioProcessorParameterGroup ownedGroup;
Array<AudioProcessorParameter*> params;
AudioProcessor::ParameterChangeForwarder forwarder { nullptr };
bool legacyParamIDs = false, usingManagedParameters = false;
};
JUCE_END_IGNORE_DEPRECATION_WARNINGS
} // namespace juce

View file

@ -34,6 +34,8 @@
#pragma once
#include <juce_audio_processors_headless/utilities/juce_FlagCache.h>
/** @cond */
namespace juce
{

View file

@ -37,7 +37,7 @@
#include "juce_VST3Headers.h"
#include "juce_VST3Utilities.h"
#include "juce_VST3Common.h"
#include "juce_ARACommon.h"
#include <juce_audio_processors_headless/format_types/juce_ARACommon.h>
namespace juce
{

View file

@ -180,19 +180,9 @@ private:
} // namespace juce
#include "utilities/juce_FlagCache.h"
#include "format/juce_AudioPluginFormat.cpp"
#include "format/juce_AudioPluginFormatManager.cpp"
#include "format_types/juce_LegacyAudioParameter.cpp"
#include "processors/juce_AudioProcessorParameter.cpp"
#include "processors/juce_AudioProcessor.cpp"
#include "processors/juce_AudioProcessorListener.cpp"
#include "processors/juce_AudioPluginInstance.cpp"
#include "processors/juce_AudioProcessorEditor.cpp"
#include "processors/juce_AudioProcessorGraph.cpp"
#include "processors/juce_GenericAudioProcessorEditor.cpp"
#include "processors/juce_PluginDescription.cpp"
#include "format_types/juce_ARACommon.cpp"
#include "format_types/juce_LADSPAPluginFormat.cpp"
#include "format_types/juce_VSTPluginFormat.cpp"
#include "format_types/juce_VST3PluginFormat.cpp"
@ -201,20 +191,9 @@ private:
#include "scanning/juce_KnownPluginList.cpp"
#include "scanning/juce_PluginDirectoryScanner.cpp"
#include "scanning/juce_PluginListComponent.cpp"
#include "processors/juce_AudioProcessorParameterGroup.cpp"
#include "utilities/juce_AudioProcessorParameterWithID.cpp"
#include "utilities/juce_RangedAudioParameter.cpp"
#include "utilities/juce_AudioParameterFloat.cpp"
#include "utilities/juce_AudioParameterInt.cpp"
#include "utilities/juce_AudioParameterBool.cpp"
#include "utilities/juce_AudioParameterChoice.cpp"
#include "utilities/juce_ParameterAttachments.cpp"
#include "utilities/juce_AudioProcessorValueTreeState.cpp"
#include "utilities/juce_PluginHostType.cpp"
#include "utilities/juce_AAXClientExtensions.cpp"
#include "utilities/juce_VST2ClientExtensions.cpp"
#include "utilities/juce_VST3ClientExtensions.cpp"
#include "utilities/ARA/juce_ARA_utils.cpp"
#include "format_types/juce_LV2PluginFormat.cpp"

View file

@ -137,24 +137,9 @@
#endif
//==============================================================================
#include "utilities/juce_AAXClientExtensions.h"
#include "utilities/juce_VST2ClientExtensions.h"
#include "utilities/juce_VST3Interface.h"
#include "utilities/juce_VST3ClientExtensions.h"
#include "format_types/juce_ARACommon.h"
#include "utilities/juce_ExtensionsVisitor.h"
#include "processors/juce_AudioProcessorParameter.h"
#include "processors/juce_HostedAudioProcessorParameter.h"
#include "processors/juce_AudioProcessorEditorHostContext.h"
#include "processors/juce_AudioProcessorEditor.h"
#include "processors/juce_AudioProcessorListener.h"
#include "processors/juce_AudioProcessorParameterGroup.h"
#include "processors/juce_AudioProcessor.h"
#include "processors/juce_PluginDescription.h"
#include "processors/juce_AudioPluginInstance.h"
#include "processors/juce_AudioProcessorGraph.h"
#include "processors/juce_GenericAudioProcessorEditor.h"
#include "format/juce_AudioPluginFormat.h"
#include "format/juce_AudioPluginFormatManager.h"
#include "scanning/juce_KnownPluginList.h"
#include "format_types/juce_AudioUnitPluginFormat.h"
@ -166,17 +151,9 @@
#include "format_types/juce_ARAHosting.h"
#include "scanning/juce_PluginDirectoryScanner.h"
#include "scanning/juce_PluginListComponent.h"
#include "utilities/juce_AudioProcessorParameterWithID.h"
#include "utilities/juce_RangedAudioParameter.h"
#include "utilities/juce_AudioParameterFloat.h"
#include "utilities/juce_AudioParameterInt.h"
#include "utilities/juce_AudioParameterBool.h"
#include "utilities/juce_AudioParameterChoice.h"
#include "utilities/juce_ParameterAttachments.h"
#include "utilities/juce_AudioProcessorValueTreeState.h"
#include "utilities/juce_PluginHostType.h"
#include "utilities/ARA/juce_ARADebug.h"
#include "utilities/ARA/juce_ARA_utils.h"
//==============================================================================
// These declarations are here to avoid missing-prototype warnings in user code.

View file

@ -1,51 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#include <juce_core/system/juce_CompilerWarnings.h>
#include <juce_core/system/juce_TargetPlatform.h>
#include "utilities/ARA/juce_ARADebug.h"
/* Having WIN32_LEAN_AND_MEAN defined at the point of including ARADebug.c will produce warnings.
To prevent such problems it's easiest to have it in its own translation unit.
*/
#if (JucePlugin_Enable_ARA || (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU))) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments", "-Wmissing-prototypes")
#include <ARA_Library/Debug/ARADebug.c>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif

View file

@ -1,294 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
PluginDescription AudioPluginInstance::getPluginDescription() const
{
PluginDescription desc;
fillInPluginDescription (desc);
return desc;
}
void* AudioPluginInstance::getPlatformSpecificData() { return nullptr; }
void AudioPluginInstance::getExtensions (ExtensionsVisitor& visitor) const { visitor.visitUnknown ({}); }
String AudioPluginInstance::getParameterID (int parameterIndex)
{
assertOnceOnDeprecatedMethodUse();
// Currently there is no corresponding method available in the
// AudioProcessorParameter class, and the previous behaviour of JUCE's
// plug-in hosting code simply returns a string version of the index; to
// maintain backwards compatibility you should perform the operation below
// this comment. However the caveat is that for plug-ins which change their
// number of parameters dynamically at runtime you cannot rely upon the
// returned parameter ID mapping to the correct parameter. A comprehensive
// solution to this problem requires some additional work in JUCE's hosting
// code.
return String (parameterIndex);
}
float AudioPluginInstance::getParameter (int parameterIndex)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getValue();
return 0.0f;
}
void AudioPluginInstance::setParameter (int parameterIndex, float newValue)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
param->setValue (newValue);
}
const String AudioPluginInstance::getParameterName (int parameterIndex)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getName (1024);
return {};
}
String AudioPluginInstance::getParameterName (int parameterIndex, int maximumStringLength)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getName (maximumStringLength);
return {};
}
const String AudioPluginInstance::getParameterText (int parameterIndex)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getCurrentValueAsText();
return {};
}
String AudioPluginInstance::getParameterText (int parameterIndex, int maximumStringLength)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getCurrentValueAsText().substring (0, maximumStringLength);
return {};
}
float AudioPluginInstance::getParameterDefaultValue (int parameterIndex)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getDefaultValue();
return 0.0f;
}
int AudioPluginInstance::getParameterNumSteps (int parameterIndex)
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getNumSteps();
return AudioProcessor::getDefaultNumParameterSteps();
}
bool AudioPluginInstance::isParameterDiscrete (int parameterIndex) const
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->isDiscrete();
return false;
}
bool AudioPluginInstance::isParameterAutomatable (int parameterIndex) const
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->isAutomatable();
return true;
}
String AudioPluginInstance::getParameterLabel (int parameterIndex) const
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getLabel();
return {};
}
bool AudioPluginInstance::isParameterOrientationInverted (int parameterIndex) const
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->isOrientationInverted();
return false;
}
bool AudioPluginInstance::isMetaParameter (int parameterIndex) const
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->isMetaParameter();
return false;
}
AudioProcessorParameter::Category AudioPluginInstance::getParameterCategory (int parameterIndex) const
{
assertOnceOnDeprecatedMethodUse();
if (auto* param = getParameters()[parameterIndex])
return param->getCategory();
return AudioProcessorParameter::genericParameter;
}
void AudioPluginInstance::assertOnceOnDeprecatedMethodUse() const noexcept
{
if (! deprecationAssertiontriggered)
{
// If you hit this assertion then you are using at least one of the
// methods marked as deprecated in this class. For now you can simply
// continue past this point and subsequent uses of deprecated methods
// will not trigger additional assertions. However, we will shortly be
// removing these methods so you are strongly advised to look at the
// implementation of the corresponding method in this class and use
// that approach instead.
jassertfalse;
}
deprecationAssertiontriggered = true;
}
bool AudioPluginInstance::deprecationAssertiontriggered = false;
AudioPluginInstance::Parameter::Parameter()
: onStrings { TRANS ("on"), TRANS ("yes"), TRANS ("true") },
offStrings { TRANS ("off"), TRANS ("no"), TRANS ("false") }
{
}
String AudioPluginInstance::Parameter::getText (float value, int maximumStringLength) const
{
if (isBoolean())
return value < 0.5f ? TRANS ("Off") : TRANS ("On");
return String (value).substring (0, maximumStringLength);
}
float AudioPluginInstance::Parameter::getValueForText (const String& text) const
{
auto floatValue = text.retainCharacters ("-0123456789.").getFloatValue();
if (isBoolean())
{
if (onStrings.contains (text, true))
return 1.0f;
if (offStrings.contains (text, true))
return 0.0f;
return floatValue < 0.5f ? 0.0f : 1.0f;
}
return floatValue;
}
void AudioPluginInstance::addHostedParameter (std::unique_ptr<HostedParameter> param)
{
addParameter (param.release());
}
void AudioPluginInstance::addHostedParameterGroup (std::unique_ptr<AudioProcessorParameterGroup> group)
{
#if JUCE_DEBUG
// All parameters *must* be HostedParameters, otherwise getHostedParameter will return
// garbage and your host will crash and burn
for (auto* param : group->getParameters (true))
{
jassertquiet (dynamic_cast<HostedParameter*> (param) != nullptr);
}
#endif
addParameterGroup (std::move (group));
}
void AudioPluginInstance::setHostedParameterTree (AudioProcessorParameterGroup group)
{
#if JUCE_DEBUG
// All parameters *must* be HostedParameters, otherwise getHostedParameter will return
// garbage and your host will crash and burn
for (auto* param : group.getParameters (true))
{
jassertquiet (dynamic_cast<HostedParameter*> (param) != nullptr);
}
#endif
setParameterTree (std::move (group));
}
AudioPluginInstance::HostedParameter* AudioPluginInstance::getHostedParameter (int index) const
{
// It's important that all AudioPluginInstance implementations
// only ever own HostedParameters!
return static_cast<HostedParameter*> (getParameters()[index]);
}
} // namespace juce

View file

@ -1,191 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
// MSVC does not like it if you override a deprecated method even if you
// keep the deprecation attribute. Other compilers are more forgiving.
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
//==============================================================================
/**
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
@tags{Audio}
*/
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.
*/
~AudioPluginInstance() override = default;
//==============================================================================
/** Fills-in the appropriate parts of this plugin description object. */
virtual void fillInPluginDescription (PluginDescription&) const = 0;
/** Returns a PluginDescription for this plugin.
This is just a convenience method to avoid calling fillInPluginDescription.
*/
PluginDescription getPluginDescription() const;
/** Allows retrieval of information related to the inner workings of a particular plugin format,
such as the AEffect* of a VST, or the handle of an AudioUnit.
To use this, create a new class derived from ExtensionsVisitor, and override
each of the visit member functions. If this AudioPluginInstance wraps a VST3 plugin
the visitVST3() member will be called, while if the AudioPluginInstance wraps an
unknown format the visitUnknown() member will be called. The argument of the visit function
can be queried to extract information related to the AudioPluginInstance's implementation.
*/
virtual void getExtensions (ExtensionsVisitor&) const;
using HostedParameter = HostedAudioProcessorParameter;
/** Adds a parameter to this instance.
@see AudioProcessor::addParameter()
*/
void addHostedParameter (std::unique_ptr<HostedParameter>);
/** Adds multiple parameters to this instance.
In debug mode, this will also check that all added parameters derive from
HostedParameter.
@see AudioProcessor::addParameterGroup()
*/
void addHostedParameterGroup (std::unique_ptr<AudioProcessorParameterGroup>);
/** Adds multiple parameters to this instance.
In debug mode, this will also check that all added parameters derive from
HostedParameter.
@see AudioProcessor::setParameterTree()
*/
void setHostedParameterTree (AudioProcessorParameterGroup);
/** Gets the parameter at a particular index.
If you want to find lots of parameters by their IDs, you should probably build and
use a map<String, HostedParameter*> by looping through all parameters.
*/
HostedParameter* getHostedParameter (int index) const;
/** @cond */
/** Use the new typesafe visitor-based interface rather than this function.
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.
*/
[[deprecated ("Use the new typesafe visitor-based interface rather than this function.")]]
virtual void* getPlatformSpecificData();
// Rather than using these methods you should call the corresponding methods
// on the AudioProcessorParameter objects returned from getParameters().
// See the implementations of the methods below for some examples of how to
// do this.
//
// In addition to being marked as deprecated these methods will assert on
// the first call.
[[deprecated]] String getParameterID (int index) override;
[[deprecated]] float getParameter (int parameterIndex) override;
[[deprecated]] void setParameter (int parameterIndex, float newValue) override;
[[deprecated]] const String getParameterName (int parameterIndex) override;
[[deprecated]] String getParameterName (int parameterIndex, int maximumStringLength) override;
[[deprecated]] const String getParameterText (int parameterIndex) override;
[[deprecated]] String getParameterText (int parameterIndex, int maximumStringLength) override;
[[deprecated]] int getParameterNumSteps (int parameterIndex) override;
[[deprecated]] bool isParameterDiscrete (int parameterIndex) const override;
[[deprecated]] bool isParameterAutomatable (int parameterIndex) const override;
[[deprecated]] float getParameterDefaultValue (int parameterIndex) override;
[[deprecated]] String getParameterLabel (int parameterIndex) const override;
[[deprecated]] bool isParameterOrientationInverted (int parameterIndex) const override;
[[deprecated]] bool isMetaParameter (int parameterIndex) const override;
[[deprecated]] AudioProcessorParameter::Category getParameterCategory (int parameterIndex) const override;
/** @endcond */
protected:
//==============================================================================
/** Structure used to describe plugin parameters */
struct Parameter : public HostedParameter
{
public:
Parameter();
String getText (float value, int maximumStringLength) const override;
float getValueForText (const String& text) const override;
private:
const StringArray onStrings, offStrings;
};
AudioPluginInstance() = default;
AudioPluginInstance (const BusesProperties& ioLayouts) : AudioProcessor (ioLayouts) {}
template <size_t numLayouts>
AudioPluginInstance (const short channelLayoutList[numLayouts][2]) : AudioProcessor (channelLayoutList) {}
private:
// It's not safe to add a plain AudioProcessorParameter to an AudioPluginInstance.
// Instead, all parameters must be HostedParameters.
using AudioProcessor::addParameter;
using AudioProcessor::addParameterGroup;
using AudioProcessor::setParameterTree;
void assertOnceOnDeprecatedMethodUse() const noexcept;
static bool deprecationAssertiontriggered;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginInstance)
};
JUCE_END_IGNORE_WARNINGS_MSVC
} // namespace juce

File diff suppressed because it is too large Load diff

View file

@ -1,472 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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.
@tags{Audio}
*/
class JUCE_API AudioProcessorGraph : public AudioProcessor,
public ChangeBroadcaster
{
public:
//==============================================================================
/** Creates an empty graph. */
AudioProcessorGraph();
/** Destructor.
Any processor objects that have been added to the graph will also be deleted.
*/
~AudioProcessorGraph() override;
/** Each node in the graph has a UID of this type. */
struct NodeID
{
constexpr NodeID() = default;
explicit constexpr NodeID (uint32 i) : uid (i) {}
uint32 uid = 0;
constexpr bool operator== (const NodeID& other) const noexcept { return uid == other.uid; }
constexpr bool operator!= (const NodeID& other) const noexcept { return uid != other.uid; }
constexpr bool operator< (const NodeID& other) const noexcept { return uid < other.uid; }
};
//==============================================================================
/** A special index 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.
*/
enum { midiChannelIndex = 0x1000 };
//==============================================================================
/**
Represents an input or output channel of a node in an AudioProcessorGraph.
*/
class NodeAndChannel
{
constexpr auto tie() const { return std::tie (nodeID, channelIndex); }
public:
NodeID nodeID;
int channelIndex;
constexpr bool isMIDI() const noexcept { return channelIndex == midiChannelIndex; }
constexpr bool operator== (const NodeAndChannel& other) const noexcept { return tie() == other.tie(); }
constexpr bool operator!= (const NodeAndChannel& other) const noexcept { return tie() != other.tie(); }
constexpr bool operator< (const NodeAndChannel& other) const noexcept { return tie() < other.tie(); }
};
//==============================================================================
/** 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 NodeID nodeID;
/** The actual processor object that this node represents. */
AudioProcessor* getProcessor() const noexcept { return processor.get(); }
/** 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;
//==============================================================================
/** Returns if the node is bypassed or not. */
bool isBypassed() const noexcept
{
if (processor != nullptr)
{
if (auto* bypassParam = processor->getBypassParameter())
return ! approximatelyEqual (bypassParam->getValue(), 0.0f);
}
return bypassed;
}
/** Tell this node to bypass processing. */
void setBypassed (bool shouldBeBypassed) noexcept
{
if (processor != nullptr)
{
if (auto* bypassParam = processor->getBypassParameter())
bypassParam->setValueNotifyingHost (shouldBeBypassed ? 1.0f : 0.0f);
}
bypassed = shouldBeBypassed;
}
//==============================================================================
/** A convenient typedef for referring to a pointer to a node object. */
using Ptr = ReferenceCountedObjectPtr<Node>;
/** @internal
Returns true if setBypassed (true) was called on this node.
This behaviour is different from isBypassed(), which may additionally return true if
the node has a bypass parameter that is not set to 0.
*/
bool userRequestedBypass() const { return bypassed; }
/** @internal
To create a new node, use AudioProcessorGraph::addNode.
*/
Node (NodeID n, std::unique_ptr<AudioProcessor> p) noexcept
: nodeID (n), processor (std::move (p))
{
jassert (processor != nullptr);
}
private:
//==============================================================================
std::unique_ptr<AudioProcessor> processor;
std::atomic<bool> bypassed { false };
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
{
//==============================================================================
constexpr Connection() = default;
constexpr Connection (NodeAndChannel sourceIn, NodeAndChannel destinationIn) noexcept
: source (sourceIn), destination (destinationIn) {}
constexpr Connection (const Connection&) = default;
constexpr Connection& operator= (const Connection&) = default;
constexpr bool operator== (const Connection& other) const noexcept
{
return source == other.source && destination == other.destination;
}
constexpr bool operator!= (const Connection& other) const noexcept
{
return ! operator== (other);
}
constexpr bool operator< (const Connection& other) const noexcept
{
const auto tie = [] (auto& x)
{
return std::tie (x.source.nodeID,
x.destination.nodeID,
x.source.channelIndex,
x.destination.channelIndex);
};
return tie (*this) < tie (other);
}
//==============================================================================
/** The channel and node which is the input source for this connection. */
NodeAndChannel source { {}, 0 };
/** The channel and node which is the input source for this connection. */
NodeAndChannel destination { {}, 0 };
};
//==============================================================================
/** Indicates how the graph should be updated after a change.
If you need to make lots of changes to a graph (e.g. lots of separate calls
to addNode, addConnection etc.) you can avoid rebuilding the graph on each
change by using the async update kind.
*/
enum class UpdateKind
{
sync, ///< Graph should be rebuilt immediately after modification.
async, ///< Graph rebuild should be delayed. If you make several changes to the graph
///< inside the same call stack, these changes will be applied in one go.
none ///< Graph should not be rebuilt automatically. Use rebuild() to trigger a graph
///< rebuild.
};
//==============================================================================
/** Deletes all nodes and connections from this graph.
Any processor objects in the graph will be deleted.
*/
void clear (UpdateKind = UpdateKind::sync);
/** Returns the array of nodes in the graph. */
const ReferenceCountedArray<Node>& getNodes() const noexcept;
/** Returns the number of nodes in the graph. */
int getNumNodes() const noexcept { return getNodes().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::Ptr getNode (int index) const noexcept { return getNodes()[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 (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 a unique ID to use for the node.
If the value is already in use, this method will fail and return an empty node.
If this succeeds, it returns a pointer to the newly-created node.
*/
Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, std::optional<NodeID> nodeId = std::nullopt, UpdateKind = UpdateKind::sync);
/** Deletes a node within the graph which has the specified ID.
This will also delete any connections that are attached to this node.
*/
Node::Ptr removeNode (NodeID, UpdateKind = UpdateKind::sync);
/** Deletes a node within the graph.
This will also delete any connections that are attached to this node.
*/
Node::Ptr removeNode (Node*, UpdateKind = UpdateKind::sync);
/** Returns the list of connections in the graph. */
std::vector<Connection> getConnections() const;
/** Returns true if the given connection exists. */
bool isConnected (const Connection&) const noexcept;
/** Returns true if there is a direct connection between any of the channels of
two specified nodes.
*/
bool isConnected (NodeID possibleSourceNodeID, NodeID possibleDestNodeID) const noexcept;
/** Does a recursive check to see if there's a direct or indirect series of connections
between these two nodes.
*/
bool isAnInputTo (const Node& source, const Node& destination) const noexcept;
/** Does a recursive check to see if there's a direct or indirect series of connections
between these two nodes.
*/
bool isAnInputTo (NodeID source, NodeID destination) const noexcept;
/** Returns true if it would be legal to connect the specified points. */
bool canConnect (const Connection&) 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 (const Connection&, UpdateKind = UpdateKind::sync);
/** Deletes the given connection. */
bool removeConnection (const Connection&, UpdateKind = UpdateKind::sync);
/** Removes all connections from the specified node. */
bool disconnectNode (NodeID, UpdateKind = UpdateKind::sync);
/** 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&) 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 (UpdateKind = UpdateKind::sync);
/** Rebuilds the graph if necessary.
This function will only ever rebuild the graph on the main thread. If this function is
called from another thread, the rebuild request will be dispatched asynchronously to the
main thread.
*/
void rebuild();
//==============================================================================
/** 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 noexcept { 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 noexcept { return graph; }
/** True if this is an audio or midi input. */
bool isInput() const noexcept;
/** True if this is an audio or midi output. */
bool isOutput() const noexcept;
//==============================================================================
AudioGraphIOProcessor (IODeviceType);
~AudioGraphIOProcessor() override;
const String getName() const override;
void fillInPluginDescription (PluginDescription&) const override;
void prepareToPlay (double newSampleRate, int estimatedSamplesPerBlock) override;
void releaseResources() override;
void processBlock (AudioBuffer<float>& , MidiBuffer&) override;
void processBlock (AudioBuffer<double>&, MidiBuffer&) override;
bool supportsDoublePrecisionProcessing() const override;
double getTailLengthSeconds() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
bool hasEditor() const override;
AudioProcessorEditor* createEditor() override;
int getNumPrograms() override;
int getCurrentProgram() override;
void setCurrentProgram (int) override;
const String getProgramName (int) override;
void changeProgramName (int, const String&) override;
void getStateInformation (juce::MemoryBlock& destData) override;
void setStateInformation (const void* data, int sizeInBytes) override;
/** @internal */
void setParentGraph (AudioProcessorGraph*);
private:
const IODeviceType type;
AudioProcessorGraph* graph = nullptr;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioGraphIOProcessor)
};
//==============================================================================
const String getName() const override;
void prepareToPlay (double, int) override;
void releaseResources() override;
void processBlock (AudioBuffer<float>&, MidiBuffer&) override;
void processBlock (AudioBuffer<double>&, MidiBuffer&) override;
bool supportsDoublePrecisionProcessing() const override;
void reset() override;
void setNonRealtime (bool) noexcept override;
double getTailLengthSeconds() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
bool hasEditor() const override { return false; }
AudioProcessorEditor* createEditor() override { return nullptr; }
int getNumPrograms() override { return 0; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram (int) override { }
const String getProgramName (int) override { return {}; }
void changeProgramName (int, const String&) override { }
void getStateInformation (juce::MemoryBlock&) override;
void setStateInformation (const void* data, int sizeInBytes) override;
private:
class Pimpl;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorGraph)
};
} // namespace juce

View file

@ -1,41 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) {}
void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {}
} // namespace juce

View file

@ -1,198 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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
@tags{Audio}
*/
class JUCE_API AudioProcessorListener
{
public:
//==============================================================================
/** Destructor. */
virtual ~AudioProcessorListener() = default;
//==============================================================================
/** 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;
/** Provides details about aspects of an AudioProcessor which have changed.
*/
struct JUCE_API ChangeDetails
{
/** @see withLatencyChanged */
bool latencyChanged = false;
/** @see withParameterInfoChanged */
bool parameterInfoChanged = false;
/** @see withProgramChanged */
bool programChanged = false;
/** @see withNonParameterStateChanged */
bool nonParameterStateChanged = false;
/** Indicates that the AudioProcessor's latency has changed.
Most of the time, you won't need to use this function directly.
AudioProcessor::setLatencySamples() will automatically call
AudioProcessor::updateHostDisplay(), indicating that the latency has changed.
@see latencyChanged
*/
[[nodiscard]] ChangeDetails withLatencyChanged (bool b) const noexcept { return with (&ChangeDetails::latencyChanged, b); }
/** Indicates that some attributes of the AudioProcessor's parameters have changed.
When this flag is set, the host should rescan the AudioProcessor's parameters, and
update its controls to match. This is often used to update the names of a plugin's
parameters in the host.
@see parameterInfoChanged
*/
[[nodiscard]] ChangeDetails withParameterInfoChanged (bool b) const noexcept { return with (&ChangeDetails::parameterInfoChanged, b); }
/** Indicates that the loaded program has changed.
When this flag is set, the host should call AudioProcessor::getCurrentProgram() and
update any preset list views to display the program that is currently in use.
@see programChanged
*/
[[nodiscard]] ChangeDetails withProgramChanged (bool b) const noexcept { return with (&ChangeDetails::programChanged, b); }
/** Indicates that the plugin state has changed (but not its parameters!).
An AudioProcessor can call updateHostDisplay with this flag set to notify the host that
its state has changed in a way that requires re-saving.
If a host receives a call to audioProcessorChanged with this flag set, it should offer
to save the plugin state before taking any actions that might irrevocably destroy the
current plugin state, such as closing the project.
@see nonParameterStateChanged
*/
[[nodiscard]] ChangeDetails withNonParameterStateChanged (bool b) const noexcept { return with (&ChangeDetails::nonParameterStateChanged, b); }
/** Returns the default set of flags that will be used when
AudioProcessor::updateHostDisplay() is called with no arguments.
*/
static ChangeDetails getDefaultFlags()
{
return ChangeDetails{}.withLatencyChanged (true)
.withParameterInfoChanged (true)
.withProgramChanged (true);
}
[[deprecated ("The naming of this function is misleading. Use getDefaultFlags instead.")]]
static ChangeDetails getAllChanged()
{
return getDefaultFlags();
}
private:
template <typename Member, typename Value>
ChangeDetails with (Member&& member, Value&& value) const noexcept
{
auto copy = *this;
copy.*member = std::forward<Value> (value);
return copy;
}
};
/** 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, const ChangeDetails& details) = 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);
};
} // namespace juce

View file

@ -1,171 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioProcessorParameter::~AudioProcessorParameter()
{
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING
// This will fail if you've called beginChangeGesture() without having made
// a corresponding call to endChangeGesture...
jassert (! isPerformingGesture);
#endif
}
void AudioProcessorParameter::setParameterIndex (int index) noexcept
{
jassert (parameterIndex < 0 && 0 <= index);
parameterIndex = index;
}
void AudioProcessorParameter::setOwner (Listener* listenerIn) noexcept
{
jassert (finalListener == nullptr);
finalListener = listenerIn;
}
void AudioProcessorParameter::setValueNotifyingHost (float newValue)
{
setValue (newValue);
sendValueChangedMessageToListeners (newValue);
}
void AudioProcessorParameter::beginChangeGesture()
{
// This method can't be used until the parameter has been attached to a processor!
jassert (parameterIndex >= 0);
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING
// This means you've called beginChangeGesture twice in succession without
// a matching call to endChangeGesture. That might be fine in most hosts,
// but it would be better to avoid doing it.
jassert (! isPerformingGesture);
isPerformingGesture = true;
#endif
ScopedLock lock (listenerLock);
for (int i = listeners.size(); --i >= 0;)
if (auto* l = listeners[i])
l->parameterGestureChanged (getParameterIndex(), true);
if (finalListener != nullptr)
finalListener->parameterGestureChanged (getParameterIndex(), true);
}
void AudioProcessorParameter::endChangeGesture()
{
// This method can't be used until the parameter has been attached to a processor!
jassert (parameterIndex >= 0);
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING
// This means you've called endChangeGesture without having previously
// called beginChangeGesture. That might be fine in most hosts, but it
// would be better to keep the calls matched correctly.
jassert (isPerformingGesture);
isPerformingGesture = false;
#endif
ScopedLock lock (listenerLock);
for (int i = listeners.size(); --i >= 0;)
if (auto* l = listeners[i])
l->parameterGestureChanged (getParameterIndex(), false);
if (finalListener != nullptr)
finalListener->parameterGestureChanged (getParameterIndex(), false);
}
void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue)
{
ScopedLock lock (listenerLock);
for (int i = listeners.size(); --i >= 0;)
if (auto* l = listeners [i])
l->parameterValueChanged (getParameterIndex(), newValue);
if (finalListener != nullptr)
finalListener->parameterValueChanged (getParameterIndex(), newValue);
}
bool AudioProcessorParameter::isOrientationInverted() const { return false; }
bool AudioProcessorParameter::isAutomatable() const { return true; }
bool AudioProcessorParameter::isMetaParameter() const { return false; }
AudioProcessorParameter::Category AudioProcessorParameter::getCategory() const { return genericParameter; }
int AudioProcessorParameter::getNumSteps() const { return getDefaultNumParameterSteps(); }
bool AudioProcessorParameter::isDiscrete() const { return false; }
bool AudioProcessorParameter::isBoolean() const { return false; }
String AudioProcessorParameter::getText (float value, int /*maximumStringLength*/) const
{
return String (value, 2);
}
String AudioProcessorParameter::getCurrentValueAsText() const
{
return getText (getValue(), 1024);
}
StringArray AudioProcessorParameter::getAllValueStrings() const
{
if (isDiscrete() && valueStrings.isEmpty())
{
auto maxIndex = getNumSteps() - 1;
for (int i = 0; i < getNumSteps(); ++i)
valueStrings.add (getText ((float) i / (float) maxIndex, 1024));
}
return valueStrings;
}
void AudioProcessorParameter::addListener (AudioProcessorParameter::Listener* newListener)
{
const ScopedLock sl (listenerLock);
listeners.addIfNotAlreadyThere (newListener);
}
void AudioProcessorParameter::removeListener (AudioProcessorParameter::Listener* listenerToRemove)
{
const ScopedLock sl (listenerLock);
listeners.removeFirstMatchingValue (listenerToRemove);
}
int AudioProcessorParameter::getDefaultNumParameterSteps() noexcept
{
return 0x7fffffff;
}
} // namespace juce

View file

@ -1,387 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/** An abstract base class for parameter objects that can be added to an
AudioProcessor.
@see AudioProcessor::addParameter
@tags{Audio}
*/
class JUCE_API AudioProcessorParameter
{
public:
AudioProcessorParameter() noexcept = default;
/** The version hint supplied to this constructor is used in Audio Unit plugins to aid ordering
parameter identifiers when JUCE_FORCE_USE_LEGACY_PARAM_IDS is not enabled.
When adding a parameter that is not present in a previous version of the Audio Unit, you
must ensure that the version hint supplied is a number higher than that of any parameter in
any previous plugin version.
For example, in the first release of a plugin, every parameter was created with "1" as a
version hint. If you add some parameters in the second release of the plugin, all of the
new parameters should have "2" as a version hint. Additional parameters added in subsequent
plugin versions should have "3", "4", and so forth, increasing monotonically.
Note that adding or removing parameters with a version hint that is lower than the maximum
version hint of all parameters will break saved automation in some hosts, so be careful!
A version hint of "0" will be treated as though the version hint has not been set
explicitly. When targeting the AU format, the version hint may be checked at runtime in
debug builds to ensure that it has been set.
Rationale:
According to <a href="https://developer.apple.com/documentation/audiotoolbox/audiounitparameter?language=objc">Apple's Documentation</a>:
> An audio unit parameter is uniquely identified by the combination of its scope, element, and ID.
However, Logic Pro and GarageBand have a known limitation that causes them to use parameter
indices instead of IDs to identify parameters. The effect of this is that adding parameters
to a later version of a plugin can break automation saved with an earlier version of the
plugin if the indices of existing parameters are changed. It is *always* unsafe to remove
parameters from an Audio Unit plugin that will be used in one of these hosts, because
removing a parameter will always modify the indices of following parameters.
In order to work around this limitation, parameters in AUv2 plugins are sorted first by
their version hint, and then by the hash of their string identifier. As long as the
parameters from later versions of the plugin always have a version hint that is higher than
the parameters from earlier versions of the plugin, recall of automation data will work as
expected in Logic and GarageBand.
Note that we can't just use the JUCE parameter index directly in order to preserve ordering.
This would require all new parameters to be added at the end of the parameter list, which
would make it impossible to add parameters to existing parameter groups. It would also make
it awkward to structure code sensibly, undoing all of the benefits of string-based parameter
identifiers.
At time of writing, AUv3 plugins seem to be affected by the same issue, but there does not
appear to be any API to control parameter indices in this format. Therefore, when building
AUv3 plugins you must not add or remove parameters in subsequent plugin versions if you
wish to support Logic and GarageBand.
*/
explicit AudioProcessorParameter (int versionHint)
: version (versionHint) {}
/** 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 a parameter.
The host may call this at any time, including during the audio processing
callback, so your implementation has to process this very efficiently and
avoid any kind of locking.
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;
/** A processor should 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 setValue() 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 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 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. If you
want the host to display stepped automation values, rather than a continuous
interpolation between successive values, you should override isDiscrete to return true.
@see isDiscrete
*/
virtual int getNumSteps() const;
/** Returns whether the parameter uses discrete values, based on the result of
getNumSteps, or allows the host to select values continuously.
This information may or may not be used, depending on the host. If you
want the host to display stepped automation values, rather than a continuous
interpolation between successive values, override this method to return true.
@see getNumSteps
*/
virtual bool isDiscrete() const;
/** Returns whether the parameter represents a boolean switch, typically with
"On" and "Off" states.
This information may or may not be used, depending on the host. If you
want the host to display a switch, rather than a two item dropdown menu,
override this method to return true. You also need to override
isDiscrete() to return `true` and getNumSteps() to return `2`.
@see isDiscrete getNumSteps
*/
virtual bool isBoolean() const;
/** Returns a textual version of the supplied normalised parameter value.
The default implementation just returns the floating point value
as a string, but this could do anything you need for a custom type
of value.
*/
virtual String getText (float normalisedValue, 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;
enum Category
{
genericParameter = (0 << 16) | 0, /**< If your parameter is not a meter then you should use this category */
inputGain = (1 << 16) | 0, /**< Currently not used */
outputGain = (1 << 16) | 1,
/** The following categories tell the host that this parameter is a meter level value
and therefore read-only. Most hosts will display these type of parameters as
a meter in the generic view of your plug-in. Pro-Tools will also show the meter
in the mixer view.
*/
inputMeter = (2 << 16) | 0,
outputMeter = (2 << 16) | 1,
compressorLimiterGainReductionMeter = (2 << 16) | 2,
expanderGateGainReductionMeter = (2 << 16) | 3,
analysisMeter = (2 << 16) | 4,
otherMeter = (2 << 16) | 5
};
/** Returns the parameter's category. */
virtual Category getCategory() const;
/** Returns the index of this parameter in its parent processor's parameter list. */
int getParameterIndex() const noexcept { return parameterIndex; }
/** @internal
This should only be called by the owner of the parameter after it has been added to
a processor. Do not call this function; changing the parameter index *will* break things!
*/
void setParameterIndex (int) noexcept;
//==============================================================================
/** Returns the current value of the parameter as a String.
This function can be called when you are hosting plug-ins to get a
more specialised textual representation of the current value from the
plug-in, for example "On" rather than "1.0".
If you are implementing a plug-in then you should ignore this function
and instead override getText.
*/
virtual String getCurrentValueAsText() const;
/** Returns the set of strings which represent the possible states a parameter
can be in.
If you are hosting a plug-in you can use the result of this function to
populate a ComboBox listing the allowed values.
If you are implementing a plug-in then you do not need to override this.
*/
virtual StringArray getAllValueStrings() const;
//==============================================================================
/** @see AudioProcessorParameter (int) */
int getVersionHint() const { return version; }
//==============================================================================
/**
A base class for listeners that want to know about changes to an
AudioProcessorParameter.
Use AudioProcessorParameter::addListener() to register your listener with
an AudioProcessorParameter.
This Listener replaces most of the functionality in the
AudioProcessorListener class, which will be deprecated and removed.
*/
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() = default;
/** Receives a callback when a parameter has been 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 parameterValueChanged (int parameterIndex, float newValue) = 0;
/** Indicates that a parameter change gesture has started.
E.g. if the user is dragging a slider, this would be called with gestureIsStarting
being true when they first press the mouse button, and it will be called again with
gestureIsStarting being false when they release it.
IMPORTANT NOTE: This will be called synchronously, and many audio processors will
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 parameterGestureChanged (int parameterIndex, bool gestureIsStarting) = 0;
};
/** @internal
This should only be called by the owner of the parameter after it has been added to
a processor. Do not call this function; changing the owner *will* break things!
*/
void setOwner (Listener* listener) noexcept;
/** Registers a listener to receive events when the parameter's state changes.
If the listener is already registered, this will not register it again.
@see removeListener
*/
void addListener (Listener* newListener);
/** Removes a previously registered parameter listener
@see addListener
*/
void removeListener (Listener* listener);
//==============================================================================
/** @internal */
void sendValueChangedMessageToListeners (float newValue);
/** Returns the default number of steps for a parameter.
NOTE! This method is deprecated! It's recommended that you use
AudioProcessorParameter::getNumSteps() instead.
@see getParameterNumSteps
*/
static int getDefaultNumParameterSteps() noexcept;
private:
//==============================================================================
int parameterIndex = -1;
int version = 0;
CriticalSection listenerLock;
Array<Listener*> listeners;
Listener* finalListener = nullptr;
mutable StringArray valueStrings;
#if JUCE_DEBUG
bool isPerformingGesture = false;
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameter)
};
} // namespace juce

View file

@ -1,330 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioProcessorParameterGroup::AudioProcessorParameterNode::~AudioProcessorParameterNode() = default;
AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (AudioProcessorParameterNode&& other)
: group (std::move (other.group)), parameter (std::move (other.parameter))
{
if (group != nullptr)
group->parent = parent;
}
AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameter> param,
AudioProcessorParameterGroup* parentGroup)
: parameter (std::move (param)), parent (parentGroup)
{}
AudioProcessorParameterGroup::AudioProcessorParameterNode::AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameterGroup> grp,
AudioProcessorParameterGroup* parentGroup)
: group (std::move (grp)), parent (parentGroup)
{
group->parent = parent;
}
AudioProcessorParameterGroup* AudioProcessorParameterGroup::AudioProcessorParameterNode::getParent() const { return parent; }
AudioProcessorParameter* AudioProcessorParameterGroup::AudioProcessorParameterNode::getParameter() const { return parameter.get(); }
AudioProcessorParameterGroup* AudioProcessorParameterGroup::AudioProcessorParameterNode::getGroup() const { return group.get(); }
//==============================================================================
AudioProcessorParameterGroup::AudioProcessorParameterGroup() = default;
AudioProcessorParameterGroup::AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator)
: identifier (std::move (groupID)), name (std::move (groupName)), separator (std::move (subgroupSeparator))
{
}
AudioProcessorParameterGroup::~AudioProcessorParameterGroup() = default;
AudioProcessorParameterGroup::AudioProcessorParameterGroup (AudioProcessorParameterGroup&& other)
: identifier (std::move (other.identifier)),
name (std::move (other.name)),
separator (std::move (other.separator)),
children (std::move (other.children))
{
updateChildParentage();
}
AudioProcessorParameterGroup& AudioProcessorParameterGroup::operator= (AudioProcessorParameterGroup&& other)
{
identifier = std::move (other.identifier);
name = std::move (other.name);
separator = std::move (other.separator);
children = std::move (other.children);
updateChildParentage();
return *this;
}
void AudioProcessorParameterGroup::updateChildParentage()
{
for (auto* child : children)
{
child->parent = this;
if (auto* group = child->getGroup())
group->parent = this;
}
}
String AudioProcessorParameterGroup::getID() const { return identifier; }
String AudioProcessorParameterGroup::getName() const { return name; }
String AudioProcessorParameterGroup::getSeparator() const { return separator; }
const AudioProcessorParameterGroup* AudioProcessorParameterGroup::getParent() const noexcept { return parent; }
void AudioProcessorParameterGroup::setName (String newName) { name = std::move (newName); }
const AudioProcessorParameterGroup::AudioProcessorParameterNode* const* AudioProcessorParameterGroup::begin() const noexcept { return const_cast<const AudioProcessorParameterNode**> (children.begin()); }
const AudioProcessorParameterGroup::AudioProcessorParameterNode* const* AudioProcessorParameterGroup::end() const noexcept { return const_cast<const AudioProcessorParameterNode**> (children.end()); }
void AudioProcessorParameterGroup::append (std::unique_ptr<AudioProcessorParameter> newParameter)
{
children.add (new AudioProcessorParameterNode (std::move (newParameter), this));
}
void AudioProcessorParameterGroup::append (std::unique_ptr<AudioProcessorParameterGroup> newSubGroup)
{
children.add (new AudioProcessorParameterNode (std::move (newSubGroup), this));
}
Array<const AudioProcessorParameterGroup*> AudioProcessorParameterGroup::getSubgroups (bool recursive) const
{
Array<const AudioProcessorParameterGroup*> groups;
getSubgroups (groups, recursive);
return groups;
}
Array<AudioProcessorParameter*> AudioProcessorParameterGroup::getParameters (bool recursive) const
{
Array<AudioProcessorParameter*> parameters;
getParameters (parameters, recursive);
return parameters;
}
Array<const AudioProcessorParameterGroup*> AudioProcessorParameterGroup::getGroupsForParameter (AudioProcessorParameter* parameter) const
{
Array<const AudioProcessorParameterGroup*> groups;
if (auto* group = getGroupForParameter (parameter))
{
while (group != nullptr && group != this)
{
groups.insert (0, group);
group = group->getParent();
}
}
return groups;
}
void AudioProcessorParameterGroup::getSubgroups (Array<const AudioProcessorParameterGroup*>& previousGroups, bool recursive) const
{
for (auto* child : children)
{
if (auto* group = child->getGroup())
{
previousGroups.add (group);
if (recursive)
group->getSubgroups (previousGroups, true);
}
}
}
void AudioProcessorParameterGroup::getParameters (Array<AudioProcessorParameter*>& previousParameters, bool recursive) const
{
for (auto* child : children)
{
if (auto* parameter = child->getParameter())
previousParameters.add (parameter);
else if (recursive)
child->getGroup()->getParameters (previousParameters, true);
}
}
const AudioProcessorParameterGroup* AudioProcessorParameterGroup::getGroupForParameter (AudioProcessorParameter* parameter) const
{
for (auto* child : children)
{
if (child->getParameter() == parameter)
return this;
if (auto* group = child->getGroup())
if (auto* foundGroup = group->getGroupForParameter (parameter))
return foundGroup;
}
return nullptr;
}
//==============================================================================
#if JUCE_UNIT_TESTS
class ParameterGroupTests final : public UnitTest
{
public:
ParameterGroupTests()
: UnitTest ("ParameterGroups", UnitTestCategories::audioProcessorParameters)
{}
void runTest() override
{
beginTest ("ParameterGroups");
auto g1 = std::make_unique<AudioProcessorParameterGroup> ("g1", "g1", " - ");
auto* p1 = new AudioParameterFloat ("p1", "p1", { 0.0f, 2.0f }, 0.5f);
auto* p2 = new AudioParameterFloat ("p2", "p2", { 0.0f, 2.0f }, 0.5f);
auto* p3 = new AudioParameterFloat ("p3", "p3", { 0.0f, 2.0f }, 0.5f);
g1->addChild (std::unique_ptr<AudioParameterFloat> (p1));
g1->addChild (std::unique_ptr<AudioParameterFloat> (p2),
std::unique_ptr<AudioParameterFloat> (p3));
auto p4 = std::make_unique<AudioParameterFloat> ("p4", "p4", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
auto p5 = std::make_unique<AudioParameterFloat> ("p5", "p5", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
auto p6 = std::make_unique<AudioParameterFloat> ("p6", "p6", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
g1->addChild (std::move (p4));
g1->addChild (std::move (p5),
std::move (p6));
{
auto topLevelParams = g1->getParameters (false);
auto params = g1->getParameters (true);
expect (topLevelParams == params);
expectEquals (params.size(), 6);
expect (params[0] == (AudioProcessorParameter*) p1);
expect (params[1] == (AudioProcessorParameter*) p2);
expect (params[2] == (AudioProcessorParameter*) p3);
expect (dynamic_cast<AudioParameterFloat*> (params[3])->name == "p4");
expect (dynamic_cast<AudioParameterFloat*> (params[4])->name == "p5");
expect (dynamic_cast<AudioParameterFloat*> (params[5])->name == "p6");
}
auto* p7 = new AudioParameterFloat ("p7", "p7", { 0.0f, 2.0f }, 0.5f);
auto* p8 = new AudioParameterFloat ("p8", "p8", { 0.0f, 2.0f }, 0.5f);
auto* p9 = new AudioParameterFloat ("p9", "p9", { 0.0f, 2.0f }, 0.5f);
auto p10 = std::make_unique<AudioParameterFloat> ("p10", "p10", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
auto p11 = std::make_unique<AudioParameterFloat> ("p11", "p11", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
auto p12 = std::make_unique<AudioParameterFloat> ("p12", "p12", NormalisableRange<float> (0.0f, 2.0f), 0.5f);
auto g2 = std::make_unique<AudioProcessorParameterGroup> ("g2", "g2", " | ", std::unique_ptr<AudioParameterFloat> (p7));
auto g3 = std::make_unique<AudioProcessorParameterGroup> ("g3", "g3", " | ", std::unique_ptr<AudioParameterFloat> (p8), std::unique_ptr<AudioParameterFloat> (p9));
auto g4 = std::make_unique<AudioProcessorParameterGroup> ("g4", "g4", " | ", std::move (p10));
auto g5 = std::make_unique<AudioProcessorParameterGroup> ("g5", "g5", " | ", std::move (p11), std::move (p12));
g1->addChild (std::move (g2));
g4->addChild (std::move (g5));
g1->addChild (std::move (g3), std::move (g4));
{
auto topLevelParams = g1->getParameters (false);
auto params = g1->getParameters (true);
expectEquals (topLevelParams.size(), 6);
expectEquals (params.size(), 12);
expect (params[0] == (AudioProcessorParameter*) p1);
expect (params[1] == (AudioProcessorParameter*) p2);
expect (params[2] == (AudioProcessorParameter*) p3);
expect (dynamic_cast<AudioParameterFloat*> (params[3])->name == "p4");
expect (dynamic_cast<AudioParameterFloat*> (params[4])->name == "p5");
expect (dynamic_cast<AudioParameterFloat*> (params[5])->name == "p6");
expect (params[6] == (AudioProcessorParameter*) p7);
expect (params[7] == (AudioProcessorParameter*) p8);
expect (params[8] == (AudioProcessorParameter*) p9);
expect (dynamic_cast<AudioParameterFloat*> (params[9]) ->name == "p10");
expect (dynamic_cast<AudioParameterFloat*> (params[10])->name == "p11");
expect (dynamic_cast<AudioParameterFloat*> (params[11])->name == "p12");
}
g1->addChild (std::make_unique<AudioProcessorParameterGroup> ("g6", "g6", " | ",
std::make_unique<AudioParameterFloat> ("p13", "p13", NormalisableRange<float> (0.0f, 2.0f), 0.5f),
std::make_unique<AudioProcessorParameterGroup> ("g7", "g7", " | ",
std::make_unique<AudioParameterFloat> ("p14", "p14", NormalisableRange<float> (0.0f, 2.0f), 0.5f)),
std::make_unique<AudioParameterFloat> ("p15", "p15", NormalisableRange<float> (0.0f, 2.0f), 0.5f)));
TestAudioProcessor processor;
processor.addParameter (new AudioParameterFloat ("pstart", "pstart", NormalisableRange<float> (0.0f, 2.0f), 0.5f));
auto groupParams = g1->getParameters (true);
processor.addParameterGroup (std::move (g1));
processor.addParameter (new AudioParameterFloat ("pend", "pend", NormalisableRange<float> (0.0f, 2.0f), 0.5f));
auto& processorParams = processor.getParameters();
expect (dynamic_cast<AudioParameterFloat*> (processorParams.getFirst())->name == "pstart");
expect (dynamic_cast<AudioParameterFloat*> (processorParams.getLast()) ->name == "pend");
auto numParams = processorParams.size();
for (int i = 1; i < numParams - 1; ++i)
expect (processorParams[i] == groupParams[i - 1]);
}
private:
struct TestAudioProcessor final : public AudioProcessor
{
const String getName() const override { return "ap"; }
void prepareToPlay (double, int) override {}
void releaseResources() override {}
void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}
using AudioProcessor::processBlock;
double getTailLengthSeconds() const override { return 0.0; }
bool acceptsMidi() const override { return false; }
bool producesMidi() const override { return false; }
AudioProcessorEditor* createEditor() override { return nullptr; }
bool hasEditor() const override { return false; }
int getNumPrograms() override { return 0; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram (int) override {}
const String getProgramName (int) override { return {}; }
void changeProgramName (int, const String&) override {}
void getStateInformation (MemoryBlock&) override {}
void setStateInformation (const void*, int) override {}
};
};
static ParameterGroupTests parameterGroupTests;
#endif
} // namespace juce

View file

@ -1,263 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/** A class encapsulating a group of AudioProcessorParameters and nested
AudioProcessorParameterGroups.
This class is predominantly write-only; there are methods for adding group
members but none for removing them. Ultimately you will probably want to
add a fully constructed group to an AudioProcessor.
@see AudioProcessor::addParameterGroup
@tags{Audio}
*/
class JUCE_API AudioProcessorParameterGroup
{
public:
//==============================================================================
/** A child of an AudioProcessorParameterGroup.
This can contain either an AudioProcessorParameter or an
AudioProcessorParameterGroup. You can query which using the
getParameter and getGroup methods.
@code
for (auto* child : group)
if (auto* parameter = node.getParameter())
parameter->setValueNotifyingHost (0.5f);
else
node.getGroup()->AddChild (new Parameter());
@endcode
*/
class AudioProcessorParameterNode
{
public:
//==============================================================================
AudioProcessorParameterNode (AudioProcessorParameterNode&&);
~AudioProcessorParameterNode();
/** Returns the parent group or nullptr if this is a top-level group. */
AudioProcessorParameterGroup* getParent() const;
/** Returns a pointer to a parameter if this node contains a parameter, nullptr otherwise. */
AudioProcessorParameter* getParameter() const;
/** Returns a pointer to a group if this node contains a group, nullptr otherwise. */
AudioProcessorParameterGroup* getGroup() const;
private:
//==============================================================================
AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameter>, AudioProcessorParameterGroup*);
AudioProcessorParameterNode (std::unique_ptr<AudioProcessorParameterGroup>, AudioProcessorParameterGroup*);
std::unique_ptr<AudioProcessorParameterGroup> group;
std::unique_ptr<AudioProcessorParameter> parameter;
AudioProcessorParameterGroup* parent = nullptr;
friend class AudioProcessorParameterGroup;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterNode)
};
//==============================================================================
/** Creates an empty AudioProcessorParameterGroup with no name or ID. */
AudioProcessorParameterGroup();
/** Creates an empty AudioProcessorParameterGroup.
@param groupID A unique identifier for the group. Keep it basic; don't use any special
characters like "." and avoid pure integer strings which could collide with
legacy parameter IDs.
@param groupName The group's name, which will be displayed in the host.
@param subgroupSeparator A separator string to use between the name of this group and the name of any
subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
layers of nested subgroups, but AU plug-ins cannot have any subgroups.
*/
AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator);
/** Creates an AudioProcessorParameterGroup with a single child.
@param groupID A unique identifier for the group. Keep it basic; don't use any special
characters like "." and avoid pure integer strings which could collide with
legacy parameter IDs.
@param groupName The group's name, which will be displayed in the host.
@param subgroupSeparator A separator string to use between the name of this group and the name of any
subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
layers of nested subgroups, but AU plug-ins cannot have any subgroups.
@param child An AudioProcessorParameter or an AudioProcessorParameterGroup to add to the group.
*/
template <typename ParameterOrGroup>
AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator,
std::unique_ptr<ParameterOrGroup> child)
: AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator)
{
addChild (std::move (child));
}
/** Creates an AudioProcessorParameterGroup with multiple children.
@param groupID A unique identifier for the group. Keep it basic; don't use any special
characters like "." and avoid pure integer strings which could collide with
legacy parameter IDs.
@param groupName The group's name, which will be displayed in the host.
@param subgroupSeparator A separator string to use between the name of this group and the name of any
subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
layers of nested subgroups, but AU plug-ins cannot have any subgroups.
@param firstChild An AudioProcessorParameter or an AudioProcessorParameterGroup to add to the group.
@param remainingChildren A list of more AudioProcessorParameters or AudioProcessorParameterGroups to add to the group.
*/
template <typename ParameterOrGroup, typename... Args>
AudioProcessorParameterGroup (String groupID, String groupName, String subgroupSeparator,
std::unique_ptr<ParameterOrGroup> firstChild, Args&&... remainingChildren)
: AudioProcessorParameterGroup (groupID, groupName, subgroupSeparator, std::move (firstChild))
{
addChild (std::forward<Args> (remainingChildren)...);
}
/** Once a group has been added to an AudioProcessor don't try to mutate it by
moving or swapping it - this will crash most hosts.
*/
AudioProcessorParameterGroup (AudioProcessorParameterGroup&&);
/** Once a group has been added to an AudioProcessor don't try to mutate it by
moving or swapping it - this will crash most hosts.
*/
AudioProcessorParameterGroup& operator= (AudioProcessorParameterGroup&&);
/** Destructor. */
~AudioProcessorParameterGroup();
//==============================================================================
/** Returns the group's ID. */
String getID() const;
/** Returns the group's name. */
String getName() const;
/** Returns the group's separator string. */
String getSeparator() const;
/** Returns the parent of the group, or nullptr if this is a top-level group. */
const AudioProcessorParameterGroup* getParent() const noexcept;
//==============================================================================
/** Changes the name of the group. If you do this after the group has been added
to an AudioProcessor, call updateHostDisplay() to inform the host of the
change. Not all hosts support dynamic group name changes.
*/
void setName (String newName);
//==============================================================================
const AudioProcessorParameterNode* const* begin() const noexcept;
const AudioProcessorParameterNode* const* end() const noexcept;
//==============================================================================
/** Returns all subgroups of this group.
@param recursive If this is true then this method will fetch all nested
subgroups using a depth first search.
*/
Array<const AudioProcessorParameterGroup*> getSubgroups (bool recursive) const;
/** Returns all the parameters in this group.
@param recursive If this is true then this method will fetch all nested
parameters using a depth first search.
*/
Array<AudioProcessorParameter*> getParameters (bool recursive) const;
/** Searches this group recursively for a parameter and returns a depth ordered
list of the groups it belongs to.
*/
Array<const AudioProcessorParameterGroup*> getGroupsForParameter (AudioProcessorParameter*) const;
//==============================================================================
/** Adds a child to the group.
Do not add children to a group which has itself already been added to the
AudioProcessor - the new elements will be ignored.
*/
template <typename ParameterOrGroup>
void addChild (std::unique_ptr<ParameterOrGroup> child)
{
// If you hit a compiler error here then you are attempting to add a
// child that is neither a pointer to an AudioProcessorParameterGroup
// nor a pointer to an AudioProcessorParameter.
append (std::move (child));
}
/** Adds multiple parameters or sub-groups to this group.
Do not add children to a group which has itself already been added to the
AudioProcessor - the new elements will be ignored.
*/
template <typename ParameterOrGroup, typename... Args>
void addChild (std::unique_ptr<ParameterOrGroup> firstChild, Args&&... remainingChildren)
{
addChild (std::move (firstChild));
addChild (std::forward<Args> (remainingChildren)...);
}
/** @cond */
[[deprecated ("This class now has a move operator, so if you're trying to move them around, you "
"should use that, or if you really need to swap two groups, just call std::swap. "
"However, remember that swapping a group that's already owned by an AudioProcessor "
"will most likely crash the host, so don't do that.")]]
void swapWith (AudioProcessorParameterGroup& other) { std::swap (*this, other); }
/** @endcond */
private:
//==============================================================================
void getSubgroups (Array<const AudioProcessorParameterGroup*>&, bool recursive) const;
void getParameters (Array<AudioProcessorParameter*>&, bool recursive) const;
const AudioProcessorParameterGroup* getGroupForParameter (AudioProcessorParameter*) const;
void updateChildParentage();
void append (std::unique_ptr<AudioProcessorParameter>);
void append (std::unique_ptr<AudioProcessorParameterGroup>);
//==============================================================================
String identifier, name, separator;
OwnedArray<AudioProcessorParameterNode> children;
AudioProcessorParameterGroup* parent = nullptr;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterGroup)
};
} // namespace juce

View file

@ -32,6 +32,8 @@
==============================================================================
*/
#include <juce_audio_processors_headless/format_types/juce_LegacyAudioParameter.h>
namespace juce
{

View file

@ -1,61 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A parameter with functions that are useful for plugin hosts.
@tags{Audio}
*/
struct JUCE_API HostedAudioProcessorParameter : public AudioProcessorParameter
{
using AudioProcessorParameter::AudioProcessorParameter;
/** Returns an ID that is unique to this parameter.
Parameter indices are unstable across plugin versions, which means that the
parameter found at a particular index in one version of a plugin might move
to a different index in the subsequent version.
Unlike the parameter index, the ID returned by this function should be
somewhat stable (depending on the format of the plugin), so it is more
suitable for storing/recalling automation data.
*/
virtual String getParameterID() const = 0;
};
} // namespace juce

View file

@ -1,126 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept
{
const auto tie = [] (const PluginDescription& d)
{
return std::tie (d.fileOrIdentifier, d.deprecatedUid, d.uniqueId);
};
return tie (*this) == tie (other);
}
static String getPluginDescSuffix (const PluginDescription& d, int uid)
{
return "-" + String::toHexString (d.fileOrIdentifier.hashCode())
+ "-" + String::toHexString (uid);
}
bool PluginDescription::matchesIdentifierString (const String& identifierString) const
{
const auto matches = [&] (int uid)
{
return identifierString.endsWithIgnoreCase (getPluginDescSuffix (*this, uid));
};
return matches (uniqueId) || matches (deprecatedUid);
}
String PluginDescription::createIdentifierString() const
{
const auto idToUse = uniqueId != 0 ? uniqueId : deprecatedUid;
return pluginFormatName + "-" + name + getPluginDescSuffix (*this, idToUse);
}
std::unique_ptr<XmlElement> PluginDescription::createXml() const
{
auto e = std::make_unique<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 ("uniqueId", String::toHexString (uniqueId));
e->setAttribute ("isInstrument", isInstrument);
e->setAttribute ("fileTime", String::toHexString (lastFileModTime.toMilliseconds()));
e->setAttribute ("infoUpdateTime", String::toHexString (lastInfoUpdateTime.toMilliseconds()));
e->setAttribute ("numInputs", numInputChannels);
e->setAttribute ("numOutputs", numOutputChannels);
e->setAttribute ("isShell", hasSharedContainer);
e->setAttribute ("hasARAExtension", hasARAExtension);
e->setAttribute ("uid", String::toHexString (deprecatedUid));
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");
isInstrument = xml.getBoolAttribute ("isInstrument", false);
lastFileModTime = Time (xml.getStringAttribute ("fileTime").getHexValue64());
lastInfoUpdateTime = Time (xml.getStringAttribute ("infoUpdateTime").getHexValue64());
numInputChannels = xml.getIntAttribute ("numInputs");
numOutputChannels = xml.getIntAttribute ("numOutputs");
hasSharedContainer = xml.getBoolAttribute ("isShell", false);
hasARAExtension = xml.getBoolAttribute ("hasARAExtension", false);
deprecatedUid = xml.getStringAttribute ("uid").getHexValue32();
uniqueId = xml.getStringAttribute ("uniqueId", "0").getHexValue32();
return true;
}
return false;
}
} // namespace juce

View file

@ -1,189 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
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
@tags{Audio}
*/
class JUCE_API PluginDescription
{
public:
//==============================================================================
PluginDescription() = default;
PluginDescription (const PluginDescription&) = default;
PluginDescription (PluginDescription&&) = default;
PluginDescription& operator= (const PluginDescription&) = default;
PluginDescription& operator= (PluginDescription&&) = default;
//==============================================================================
/** 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;
/** The last time that this information was updated. This would typically have
been during a scan when this plugin was first tested or found to have changed.
*/
Time lastInfoUpdateTime;
/** Deprecated: New projects should use uniqueId instead.
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 deprecatedUid = 0;
/** 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.
The uniqueId field replaces the deprecatedUid field, and fixes an issue
where VST3 plugins with matching FUIDs would generate different uid
values depending on the platform. The deprecatedUid field is kept for
backwards compatibility, allowing existing hosts to migrate from the
old uid to the new uniqueId.
@see createIdentifierString
*/
int uniqueId = 0;
/** True if the plug-in identifies itself as a synthesiser. */
bool isInstrument = false;
/** The number of inputs. */
int numInputChannels = 0;
/** The number of outputs. */
int numOutputChannels = 0;
/** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */
bool hasSharedContainer = false;
/** True if the plug-in is ARA enabled and can supply a valid ARAFactoryWrapper. */
bool hasARAExtension = false;
/** 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 identifiers 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
*/
std::unique_ptr<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)
};
} // namespace juce

View file

@ -1,78 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
#include <juce_core/system/juce_PlatformDefs.h>
/** @cond */
#ifndef JUCE_API
#define JUCE_API
#endif
/** @endcond */
#if (JucePlugin_Enable_ARA || (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU))) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)
namespace juce
{
//==============================================================================
#if (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS) || JUCE_LOG_ASSERTIONS
#define ARA_ENABLE_INTERNAL_ASSERTS 1
#else
#define ARA_ENABLE_INTERNAL_ASSERTS 0
#endif // (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS) || JUCE_LOG_ASSERTIONS
//==============================================================================
#if ARA_ENABLE_INTERNAL_ASSERTS
JUCE_API void JUCE_CALLTYPE handleARAAssertion (const char* file, const int line, const char* diagnosis) noexcept;
#if !defined(ARA_HANDLE_ASSERT)
#define ARA_HANDLE_ASSERT(file, line, diagnosis) juce::handleARAAssertion (file, line, diagnosis)
#endif
#if JUCE_LOG_ASSERTIONS
#define ARA_ENABLE_DEBUG_OUTPUT 1
#endif
#endif
} // namespace juce
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments", "-Wmissing-prototypes")
#include <ARA_Library/Debug/ARADebug.h>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif

View file

@ -1,986 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
class ARADocumentControllerSpecialisation::ARADocumentControllerImpl : public ARADocumentController
{
public:
ARADocumentControllerImpl (const ARA::PlugIn::PlugInEntry* entry,
const ARA::ARADocumentControllerHostInstance* instance,
ARADocumentControllerSpecialisation* spec)
: ARADocumentController (entry, instance), specialisation (spec)
{
}
template <typename PlaybackRenderer_t = ARAPlaybackRenderer>
std::vector<PlaybackRenderer_t*> const& getPlaybackRenderers() const noexcept
{
return ARA::PlugIn::DocumentController::getPlaybackRenderers<PlaybackRenderer_t>();
}
template <typename EditorRenderer_t = ARAEditorRenderer>
std::vector<EditorRenderer_t*> const& getEditorRenderers() const noexcept
{
return ARA::PlugIn::DocumentController::getEditorRenderers<EditorRenderer_t>();
}
template <typename EditorView_t = ARAEditorView>
std::vector<EditorView_t*> const& getEditorViews() const noexcept
{
return ARA::PlugIn::DocumentController::getEditorViews<EditorView_t>();
}
auto getSpecialisation() { return specialisation; }
protected:
//==============================================================================
bool doRestoreObjectsFromStream (ARAInputStream& input, const ARARestoreObjectsFilter* filter) noexcept
{
return specialisation->doRestoreObjectsFromStream (input, filter);
}
bool doStoreObjectsToStream (ARAOutputStream& output, const ARAStoreObjectsFilter* filter) noexcept
{
return specialisation->doStoreObjectsToStream (output, filter);
}
//==============================================================================
// Model object creation
ARA::PlugIn::Document* doCreateDocument () noexcept override;
ARA::PlugIn::MusicalContext* doCreateMusicalContext (ARA::PlugIn::Document* document, ARA::ARAMusicalContextHostRef hostRef) noexcept override;
ARA::PlugIn::RegionSequence* doCreateRegionSequence (ARA::PlugIn::Document* document, ARA::ARARegionSequenceHostRef hostRef) noexcept override;
ARA::PlugIn::AudioSource* doCreateAudioSource (ARA::PlugIn::Document* document, ARA::ARAAudioSourceHostRef hostRef) noexcept override;
ARA::PlugIn::AudioModification* doCreateAudioModification (ARA::PlugIn::AudioSource* audioSource, ARA::ARAAudioModificationHostRef hostRef, const ARA::PlugIn::AudioModification* optionalModificationToClone) noexcept override;
ARA::PlugIn::PlaybackRegion* doCreatePlaybackRegion (ARA::PlugIn::AudioModification* modification, ARA::ARAPlaybackRegionHostRef hostRef) noexcept override;
//==============================================================================
// Plugin role implementation
friend class ARAPlaybackRegionReader;
ARA::PlugIn::PlaybackRenderer* doCreatePlaybackRenderer() noexcept override;
ARA::PlugIn::EditorRenderer* doCreateEditorRenderer() noexcept override;
ARA::PlugIn::EditorView* doCreateEditorView() noexcept override;
//==============================================================================
// ARAAudioSource content access
bool doIsAudioSourceContentAvailable (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type) noexcept override;
ARA::ARAContentGrade doGetAudioSourceContentGrade (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type) noexcept override;
ARA::PlugIn::ContentReader* doCreateAudioSourceContentReader (ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range) noexcept override;
//==============================================================================
// ARAAudioModification content access
bool doIsAudioModificationContentAvailable (const ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type) noexcept override;
ARA::ARAContentGrade doGetAudioModificationContentGrade (const ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type) noexcept override;
ARA::PlugIn::ContentReader* doCreateAudioModificationContentReader (ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range) noexcept override;
//==============================================================================
// ARAPlaybackRegion content access
bool doIsPlaybackRegionContentAvailable (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type) noexcept override;
ARA::ARAContentGrade doGetPlaybackRegionContentGrade (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type) noexcept override;
ARA::PlugIn::ContentReader* doCreatePlaybackRegionContentReader (ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range) noexcept override;
void doGetPlaybackRegionHeadAndTailTime (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARATimeDuration* headTime,
ARA::ARATimeDuration* tailTime) noexcept override;
//==============================================================================
// ARAAudioSource analysis
bool doIsAudioSourceContentAnalysisIncomplete (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type) noexcept override;
void doRequestAudioSourceContentAnalysis (ARA::PlugIn::AudioSource* audioSource,
std::vector<ARA::ARAContentType> const& contentTypes) noexcept override;
//==============================================================================
// Analysis Algorithm selection
ARA::ARAInt32 doGetProcessingAlgorithmsCount() noexcept override;
const ARA::ARAProcessingAlgorithmProperties* doGetProcessingAlgorithmProperties (ARA::ARAInt32 algorithmIndex) noexcept override;
ARA::ARAInt32 doGetProcessingAlgorithmForAudioSource (const ARA::PlugIn::AudioSource* audioSource) noexcept override;
void doRequestProcessingAlgorithmForAudioSource (ARA::PlugIn::AudioSource* audioSource,
ARA::ARAInt32 algorithmIndex) noexcept override;
/** @cond */
//==============================================================================
bool doRestoreObjectsFromArchive (ARA::PlugIn::HostArchiveReader* archiveReader, const ARA::PlugIn::RestoreObjectsFilter* filter) noexcept override;
bool doStoreObjectsToArchive (ARA::PlugIn::HostArchiveWriter* archiveWriter, const ARA::PlugIn::StoreObjectsFilter* filter) noexcept override;
//==============================================================================
// Document notifications
void willBeginEditing() noexcept override;
void didEndEditing() noexcept override;
void willNotifyModelUpdates() noexcept override;
void didNotifyModelUpdates() noexcept override;
void willUpdateDocumentProperties (ARA::PlugIn::Document* document, ARADocument::PropertiesPtr newProperties) noexcept override;
void didUpdateDocumentProperties (ARA::PlugIn::Document* document) noexcept override;
void didAddMusicalContextToDocument (ARA::PlugIn::Document* document, ARA::PlugIn::MusicalContext* musicalContext) noexcept override;
void willRemoveMusicalContextFromDocument (ARA::PlugIn::Document* document, ARA::PlugIn::MusicalContext* musicalContext) noexcept override;
void didReorderMusicalContextsInDocument (ARA::PlugIn::Document* document) noexcept override;
void didAddRegionSequenceToDocument (ARA::PlugIn::Document* document, ARA::PlugIn::RegionSequence* regionSequence) noexcept override;
void willRemoveRegionSequenceFromDocument (ARA::PlugIn::Document* document, ARA::PlugIn::RegionSequence* regionSequence) noexcept override;
void didReorderRegionSequencesInDocument (ARA::PlugIn::Document* document) noexcept override;
void didAddAudioSourceToDocument (ARA::PlugIn::Document* document, ARA::PlugIn::AudioSource* audioSource) noexcept override;
void willRemoveAudioSourceFromDocument (ARA::PlugIn::Document* document, ARA::PlugIn::AudioSource* audioSource) noexcept override;
void willDestroyDocument (ARA::PlugIn::Document* document) noexcept override;
//==============================================================================
// MusicalContext notifications
void willUpdateMusicalContextProperties (ARA::PlugIn::MusicalContext* musicalContext, ARAMusicalContext::PropertiesPtr newProperties) noexcept override;
void didUpdateMusicalContextProperties (ARA::PlugIn::MusicalContext* musicalContext) noexcept override;
void doUpdateMusicalContextContent (ARA::PlugIn::MusicalContext* musicalContext, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes flags) noexcept override;
void didAddRegionSequenceToMusicalContext (ARA::PlugIn::MusicalContext* musicalContext, ARA::PlugIn::RegionSequence* regionSequence) noexcept override;
void willRemoveRegionSequenceFromMusicalContext (ARA::PlugIn::MusicalContext* musicalContext, ARA::PlugIn::RegionSequence* regionSequence) noexcept override;
void didReorderRegionSequencesInMusicalContext (ARA::PlugIn::MusicalContext* musicalContext) noexcept override;
void willDestroyMusicalContext (ARA::PlugIn::MusicalContext* musicalContext) noexcept override;
//==============================================================================
// RegionSequence notifications, typically not overridden further
void willUpdateRegionSequenceProperties (ARA::PlugIn::RegionSequence* regionSequence, ARARegionSequence::PropertiesPtr newProperties) noexcept override;
void didUpdateRegionSequenceProperties (ARA::PlugIn::RegionSequence* regionSequence) noexcept override;
void didAddPlaybackRegionToRegionSequence (ARA::PlugIn::RegionSequence* regionSequence, ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override;
void willRemovePlaybackRegionFromRegionSequence (ARA::PlugIn::RegionSequence* regionSequence, ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override;
void willDestroyRegionSequence (ARA::PlugIn::RegionSequence* regionSequence) noexcept override;
//==============================================================================
// AudioSource notifications
void willUpdateAudioSourceProperties (ARA::PlugIn::AudioSource* audioSource, ARAAudioSource::PropertiesPtr newProperties) noexcept override;
void didUpdateAudioSourceProperties (ARA::PlugIn::AudioSource* audioSource) noexcept override;
void doUpdateAudioSourceContent (ARA::PlugIn::AudioSource* audioSource, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes flags) noexcept override;
void willEnableAudioSourceSamplesAccess (ARA::PlugIn::AudioSource* audioSource, bool enable) noexcept override;
void didEnableAudioSourceSamplesAccess (ARA::PlugIn::AudioSource* audioSource, bool enable) noexcept override;
void didAddAudioModificationToAudioSource (ARA::PlugIn::AudioSource* audioSource, ARA::PlugIn::AudioModification* audioModification) noexcept override;
void willRemoveAudioModificationFromAudioSource (ARA::PlugIn::AudioSource* audioSource, ARA::PlugIn::AudioModification* audioModification) noexcept override;
void willDeactivateAudioSourceForUndoHistory (ARA::PlugIn::AudioSource* audioSource, bool deactivate) noexcept override;
void didDeactivateAudioSourceForUndoHistory (ARA::PlugIn::AudioSource* audioSource, bool deactivate) noexcept override;
void willDestroyAudioSource (ARA::PlugIn::AudioSource* audioSource) noexcept override;
//==============================================================================
// AudioModification notifications
void willUpdateAudioModificationProperties (ARA::PlugIn::AudioModification* audioModification, ARAAudioModification::PropertiesPtr newProperties) noexcept override;
void didUpdateAudioModificationProperties (ARA::PlugIn::AudioModification* audioModification) noexcept override;
void didAddPlaybackRegionToAudioModification (ARA::PlugIn::AudioModification* audioModification, ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override;
void willRemovePlaybackRegionFromAudioModification (ARA::PlugIn::AudioModification* audioModification, ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override;
void willDeactivateAudioModificationForUndoHistory (ARA::PlugIn::AudioModification* audioModification, bool deactivate) noexcept override;
void didDeactivateAudioModificationForUndoHistory (ARA::PlugIn::AudioModification* audioModification, bool deactivate) noexcept override;
void willDestroyAudioModification (ARA::PlugIn::AudioModification* audioModification) noexcept override;
//==============================================================================
// PlaybackRegion notifications
void willUpdatePlaybackRegionProperties (ARA::PlugIn::PlaybackRegion* playbackRegion, ARAPlaybackRegion::PropertiesPtr newProperties) noexcept override;
void didUpdatePlaybackRegionProperties (ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override;
void willDestroyPlaybackRegion (ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override;
/** @endcond */
public:
/** @cond */
//==============================================================================
/** @internal */
void internalNotifyAudioSourceAnalysisProgressStarted (ARAAudioSource* audioSource) override;
/** @internal */
void internalNotifyAudioSourceAnalysisProgressUpdated (ARAAudioSource* audioSource, float progress) override;
/** @internal */
void internalNotifyAudioSourceAnalysisProgressCompleted (ARAAudioSource* audioSource) override;
/** @internal */
void internalDidUpdateAudioSourceAnalysisProgress (ARAAudioSource* audioSource,
ARAAudioSource::ARAAnalysisProgressState state,
float progress) override;
//==============================================================================
/** @internal */
void internalNotifyAudioSourceContentChanged (ARAAudioSource* audioSource,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost) override;
/** @internal */
void internalNotifyAudioModificationContentChanged (ARAAudioModification* audioModification,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost) override;
/** @internal */
void internalNotifyPlaybackRegionContentChanged (ARAPlaybackRegion* playbackRegion,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost) override;
/** @endcond */
private:
//==============================================================================
ARADocumentControllerSpecialisation* specialisation;
std::atomic<bool> internalAnalysisProgressIsSynced { true };
ScopedJuceInitialiser_GUI libraryInitialiser;
int activeAudioSourcesCount = 0;
std::optional<TimedCallback> analysisTimer;
void analysisTimerCallback();
//==============================================================================
template <typename ModelObject, typename Function, typename... Ts>
void notifyListeners (Function ModelObject::Listener::* function, ModelObject* modelObject, Ts... ts)
{
(specialisation->*function) (modelObject, ts...);
modelObject->notifyListeners ([&] (auto& l)
{
try
{
(l.*function) (modelObject, ts...);
}
catch (...)
{
}
});
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARADocumentControllerImpl)
};
ARA::PlugIn::DocumentController* ARADocumentControllerSpecialisation::getDocumentController() noexcept
{
return documentController.get();
}
//==============================================================================
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalNotifyAudioSourceAnalysisProgressStarted (ARAAudioSource* audioSource)
{
if (audioSource->internalAnalysisProgressTracker.updateProgress (ARA::kARAAnalysisProgressStarted, 0.0f))
internalAnalysisProgressIsSynced.store (false, std::memory_order_release);
DocumentController::notifyAudioSourceAnalysisProgressStarted (audioSource);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalNotifyAudioSourceAnalysisProgressUpdated (ARAAudioSource* audioSource,
float progress)
{
if (audioSource->internalAnalysisProgressTracker.updateProgress (ARA::kARAAnalysisProgressUpdated, progress))
internalAnalysisProgressIsSynced.store (false, std::memory_order_release);
DocumentController::notifyAudioSourceAnalysisProgressUpdated (audioSource, progress);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalNotifyAudioSourceAnalysisProgressCompleted (ARAAudioSource* audioSource)
{
if (audioSource->internalAnalysisProgressTracker.updateProgress (ARA::kARAAnalysisProgressCompleted, 1.0f))
internalAnalysisProgressIsSynced.store (false, std::memory_order_release);
DocumentController::notifyAudioSourceAnalysisProgressCompleted (audioSource);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalDidUpdateAudioSourceAnalysisProgress (ARAAudioSource* audioSource,
ARAAudioSource::ARAAnalysisProgressState state,
float progress)
{
specialisation->didUpdateAudioSourceAnalysisProgress (audioSource, state, progress);
}
//==============================================================================
ARADocumentControllerSpecialisation* ARADocumentControllerSpecialisation::getSpecialisedDocumentControllerImpl (ARA::PlugIn::DocumentController* dc)
{
return static_cast<ARADocumentControllerImpl*> (dc)->getSpecialisation();
}
ARADocument* ARADocumentControllerSpecialisation::getDocumentImpl()
{
return documentController->getDocument();
}
//==============================================================================
// some helper macros to ease repeated declaration & implementation of notification functions below:
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments")
// no notification arguments
#define OVERRIDE_TO_NOTIFY_1(function, ModelObjectType, modelObject) \
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::function (ARA::PlugIn::ModelObjectType* modelObject) noexcept \
{ \
notifyListeners (&ARA##ModelObjectType::Listener::function, static_cast<ARA##ModelObjectType*> (modelObject)); \
}
// single notification argument, model object version
#define OVERRIDE_TO_NOTIFY_2(function, ModelObjectType, modelObject, ArgumentType, argument) \
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::function (ARA::PlugIn::ModelObjectType* modelObject, ARA::PlugIn::ArgumentType argument) noexcept \
{ \
notifyListeners (&ARA##ModelObjectType::Listener::function, static_cast<ARA##ModelObjectType*> (modelObject), static_cast<ARA##ArgumentType> (argument)); \
}
// single notification argument, non-model object version
#define OVERRIDE_TO_NOTIFY_3(function, ModelObjectType, modelObject, ArgumentType, argument) \
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::function (ARA::PlugIn::ModelObjectType* modelObject, ArgumentType argument) noexcept \
{ \
notifyListeners (&ARA##ModelObjectType::Listener::function, static_cast<ARA##ModelObjectType*> (modelObject), argument); \
}
//==============================================================================
ARA::PlugIn::Document* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateDocument() noexcept
{
auto* document = specialisation->doCreateDocument();
// Your Document subclass must inherit from juce::ARADocument
jassert (dynamic_cast<ARADocument*> (document));
return document;
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::willBeginEditing() noexcept
{
notifyListeners (&ARADocument::Listener::willBeginEditing, static_cast<ARADocument*> (getDocument()));
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::didEndEditing() noexcept
{
notifyListeners (&ARADocument::Listener::didEndEditing, static_cast<ARADocument*> (getDocument()));
if (activeAudioSourcesCount == 0)
{
analysisTimer.reset();
}
else if (! analysisTimer.has_value() && (activeAudioSourcesCount > 0))
{
analysisTimer.emplace ([this] { analysisTimerCallback(); });
analysisTimer->startTimerHz (20);
}
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::willNotifyModelUpdates() noexcept
{
notifyListeners (&ARADocument::Listener::willNotifyModelUpdates, static_cast<ARADocument*> (getDocument()));
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::didNotifyModelUpdates() noexcept
{
notifyListeners (&ARADocument::Listener::didNotifyModelUpdates, static_cast<ARADocument*> (getDocument()));
}
//==============================================================================
bool ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doRestoreObjectsFromArchive (ARA::PlugIn::HostArchiveReader* archiveReader,
const ARA::PlugIn::RestoreObjectsFilter* filter) noexcept
{
ARAInputStream reader (archiveReader);
return doRestoreObjectsFromStream (reader, filter);
}
bool ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doStoreObjectsToArchive (ARA::PlugIn::HostArchiveWriter* archiveWriter,
const ARA::PlugIn::StoreObjectsFilter* filter) noexcept
{
ARAOutputStream writer (archiveWriter);
return doStoreObjectsToStream (writer, filter);
}
//==============================================================================
OVERRIDE_TO_NOTIFY_3 (willUpdateDocumentProperties, Document, document, ARADocument::PropertiesPtr, newProperties)
OVERRIDE_TO_NOTIFY_1 (didUpdateDocumentProperties, Document, document)
OVERRIDE_TO_NOTIFY_2 (didAddMusicalContextToDocument, Document, document, MusicalContext*, musicalContext)
OVERRIDE_TO_NOTIFY_2 (willRemoveMusicalContextFromDocument, Document, document, MusicalContext*, musicalContext)
OVERRIDE_TO_NOTIFY_1 (didReorderMusicalContextsInDocument, Document, document)
OVERRIDE_TO_NOTIFY_2 (didAddRegionSequenceToDocument, Document, document, RegionSequence*, regionSequence)
OVERRIDE_TO_NOTIFY_2 (willRemoveRegionSequenceFromDocument, Document, document, RegionSequence*, regionSequence)
OVERRIDE_TO_NOTIFY_1 (didReorderRegionSequencesInDocument, Document, document)
OVERRIDE_TO_NOTIFY_2 (didAddAudioSourceToDocument, Document, document, AudioSource*, audioSource)
OVERRIDE_TO_NOTIFY_2 (willRemoveAudioSourceFromDocument, Document, document, AudioSource*, audioSource)
OVERRIDE_TO_NOTIFY_1 (willDestroyDocument, Document, document)
//==============================================================================
ARA::PlugIn::MusicalContext* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateMusicalContext (ARA::PlugIn::Document* document,
ARA::ARAMusicalContextHostRef hostRef) noexcept
{
return specialisation->doCreateMusicalContext (static_cast<ARADocument*> (document), hostRef);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doUpdateMusicalContextContent (ARA::PlugIn::MusicalContext* musicalContext,
const ARA::ARAContentTimeRange*,
ARA::ContentUpdateScopes flags) noexcept
{
notifyListeners (&ARAMusicalContext::Listener::doUpdateMusicalContextContent,
static_cast<ARAMusicalContext*> (musicalContext),
flags);
}
OVERRIDE_TO_NOTIFY_3 (willUpdateMusicalContextProperties, MusicalContext, musicalContext, ARAMusicalContext::PropertiesPtr, newProperties)
OVERRIDE_TO_NOTIFY_1 (didUpdateMusicalContextProperties, MusicalContext, musicalContext)
OVERRIDE_TO_NOTIFY_2 (didAddRegionSequenceToMusicalContext, MusicalContext, musicalContext, RegionSequence*, regionSequence)
OVERRIDE_TO_NOTIFY_2 (willRemoveRegionSequenceFromMusicalContext, MusicalContext, musicalContext, RegionSequence*, regionSequence)
OVERRIDE_TO_NOTIFY_1 (didReorderRegionSequencesInMusicalContext, MusicalContext, musicalContext)
OVERRIDE_TO_NOTIFY_1 (willDestroyMusicalContext, MusicalContext, musicalContext)
//==============================================================================
ARA::PlugIn::RegionSequence* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateRegionSequence (ARA::PlugIn::Document* document, ARA::ARARegionSequenceHostRef hostRef) noexcept
{
return specialisation->doCreateRegionSequence (static_cast<ARADocument*> (document), hostRef);
}
OVERRIDE_TO_NOTIFY_3 (willUpdateRegionSequenceProperties, RegionSequence, regionSequence, ARARegionSequence::PropertiesPtr, newProperties)
OVERRIDE_TO_NOTIFY_1 (didUpdateRegionSequenceProperties, RegionSequence, regionSequence)
OVERRIDE_TO_NOTIFY_2 (didAddPlaybackRegionToRegionSequence, RegionSequence, regionSequence, PlaybackRegion*, playbackRegion)
OVERRIDE_TO_NOTIFY_2 (willRemovePlaybackRegionFromRegionSequence, RegionSequence, regionSequence, PlaybackRegion*, playbackRegion)
OVERRIDE_TO_NOTIFY_1 (willDestroyRegionSequence, RegionSequence, regionSequence)
//==============================================================================
ARA::PlugIn::AudioSource* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateAudioSource (ARA::PlugIn::Document* document, ARA::ARAAudioSourceHostRef hostRef) noexcept
{
++activeAudioSourcesCount;
return specialisation->doCreateAudioSource (static_cast<ARADocument*> (document), hostRef);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doUpdateAudioSourceContent (ARA::PlugIn::AudioSource* audioSource,
const ARA::ARAContentTimeRange*,
ARA::ContentUpdateScopes flags) noexcept
{
notifyListeners (&ARAAudioSource::Listener::doUpdateAudioSourceContent, static_cast<ARAAudioSource*> (audioSource), flags);
}
OVERRIDE_TO_NOTIFY_3 (willUpdateAudioSourceProperties, AudioSource, audioSource, ARAAudioSource::PropertiesPtr, newProperties)
OVERRIDE_TO_NOTIFY_1 (didUpdateAudioSourceProperties, AudioSource, audioSource)
OVERRIDE_TO_NOTIFY_3 (willEnableAudioSourceSamplesAccess, AudioSource, audioSource, bool, enable)
OVERRIDE_TO_NOTIFY_3 (didEnableAudioSourceSamplesAccess, AudioSource, audioSource, bool, enable)
OVERRIDE_TO_NOTIFY_2 (didAddAudioModificationToAudioSource, AudioSource, audioSource, AudioModification*, audioModification)
OVERRIDE_TO_NOTIFY_2 (willRemoveAudioModificationFromAudioSource, AudioSource, audioSource, AudioModification*, audioModification)
OVERRIDE_TO_NOTIFY_3 (willDeactivateAudioSourceForUndoHistory, AudioSource, audioSource, bool, deactivate)
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::didDeactivateAudioSourceForUndoHistory (ARA::PlugIn::AudioSource* audioSource,
bool deactivate) noexcept
{
activeAudioSourcesCount += (deactivate ? -1 : 1);
notifyListeners (&ARAAudioSource::Listener::didDeactivateAudioSourceForUndoHistory,
static_cast<ARAAudioSource*> (audioSource),
deactivate);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::willDestroyAudioSource (ARA::PlugIn::AudioSource* audioSource) noexcept
{
if (! audioSource->isDeactivatedForUndoHistory())
--activeAudioSourcesCount;
notifyListeners (&ARAAudioSource::Listener::willDestroyAudioSource, static_cast<ARAAudioSource*> (audioSource));
}
//==============================================================================
ARA::PlugIn::AudioModification* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateAudioModification (ARA::PlugIn::AudioSource* audioSource,
ARA::ARAAudioModificationHostRef hostRef,
const ARA::PlugIn::AudioModification* optionalModificationToClone) noexcept
{
return specialisation->doCreateAudioModification (static_cast<ARAAudioSource*> (audioSource),
hostRef,
static_cast<const ARAAudioModification*> (optionalModificationToClone));
}
OVERRIDE_TO_NOTIFY_3 (willUpdateAudioModificationProperties, AudioModification, audioModification, ARAAudioModification::PropertiesPtr, newProperties)
OVERRIDE_TO_NOTIFY_1 (didUpdateAudioModificationProperties, AudioModification, audioModification)
OVERRIDE_TO_NOTIFY_2 (didAddPlaybackRegionToAudioModification, AudioModification, audioModification, PlaybackRegion*, playbackRegion)
OVERRIDE_TO_NOTIFY_2 (willRemovePlaybackRegionFromAudioModification, AudioModification, audioModification, PlaybackRegion*, playbackRegion)
OVERRIDE_TO_NOTIFY_3 (willDeactivateAudioModificationForUndoHistory, AudioModification, audioModification, bool, deactivate)
OVERRIDE_TO_NOTIFY_3 (didDeactivateAudioModificationForUndoHistory, AudioModification, audioModification, bool, deactivate)
OVERRIDE_TO_NOTIFY_1 (willDestroyAudioModification, AudioModification, audioModification)
//==============================================================================
ARA::PlugIn::PlaybackRegion* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreatePlaybackRegion (ARA::PlugIn::AudioModification* modification,
ARA::ARAPlaybackRegionHostRef hostRef) noexcept
{
return specialisation->doCreatePlaybackRegion (static_cast<ARAAudioModification*> (modification), hostRef);
}
OVERRIDE_TO_NOTIFY_3 (willUpdatePlaybackRegionProperties, PlaybackRegion, playbackRegion, ARAPlaybackRegion::PropertiesPtr, newProperties)
OVERRIDE_TO_NOTIFY_1 (didUpdatePlaybackRegionProperties, PlaybackRegion, playbackRegion)
OVERRIDE_TO_NOTIFY_1 (willDestroyPlaybackRegion, PlaybackRegion, playbackRegion)
//==============================================================================
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalNotifyAudioSourceContentChanged (ARAAudioSource* audioSource,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost)
{
if (notifyARAHost)
DocumentController::notifyAudioSourceContentChanged (audioSource, scopeFlags);
notifyListeners (&ARAAudioSource::Listener::doUpdateAudioSourceContent, audioSource, scopeFlags);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalNotifyAudioModificationContentChanged (ARAAudioModification* audioModification,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost)
{
if (notifyARAHost)
DocumentController::notifyAudioModificationContentChanged (audioModification, scopeFlags);
notifyListeners (&ARAAudioModification::Listener::didUpdateAudioModificationContent, audioModification, scopeFlags);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::internalNotifyPlaybackRegionContentChanged (ARAPlaybackRegion* playbackRegion,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost)
{
if (notifyARAHost)
DocumentController::notifyPlaybackRegionContentChanged (playbackRegion, scopeFlags);
notifyListeners (&ARAPlaybackRegion::Listener::didUpdatePlaybackRegionContent, playbackRegion, scopeFlags);
}
//==============================================================================
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#undef OVERRIDE_TO_NOTIFY_1
#undef OVERRIDE_TO_NOTIFY_2
#undef OVERRIDE_TO_NOTIFY_3
//==============================================================================
ARADocument* ARADocumentControllerSpecialisation::doCreateDocument()
{
return new ARADocument (static_cast<ARADocumentControllerImpl*> (getDocumentController()));
}
ARAMusicalContext* ARADocumentControllerSpecialisation::doCreateMusicalContext (ARADocument* document,
ARA::ARAMusicalContextHostRef hostRef)
{
return new ARAMusicalContext (static_cast<ARADocument*> (document), hostRef);
}
ARARegionSequence* ARADocumentControllerSpecialisation::doCreateRegionSequence (ARADocument* document,
ARA::ARARegionSequenceHostRef hostRef)
{
return new ARARegionSequence (static_cast<ARADocument*> (document), hostRef);
}
ARAAudioSource* ARADocumentControllerSpecialisation::doCreateAudioSource (ARADocument* document,
ARA::ARAAudioSourceHostRef hostRef)
{
return new ARAAudioSource (static_cast<ARADocument*> (document), hostRef);
}
ARAAudioModification* ARADocumentControllerSpecialisation::doCreateAudioModification (
ARAAudioSource* audioSource,
ARA::ARAAudioModificationHostRef hostRef,
const ARAAudioModification* optionalModificationToClone)
{
return new ARAAudioModification (static_cast<ARAAudioSource*> (audioSource),
hostRef,
static_cast<const ARAAudioModification*> (optionalModificationToClone));
}
ARAPlaybackRegion*
ARADocumentControllerSpecialisation::doCreatePlaybackRegion (ARAAudioModification* modification,
ARA::ARAPlaybackRegionHostRef hostRef)
{
return new ARAPlaybackRegion (static_cast<ARAAudioModification*> (modification), hostRef);
}
//==============================================================================
ARA::PlugIn::PlaybackRenderer* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreatePlaybackRenderer() noexcept
{
return specialisation->doCreatePlaybackRenderer();
}
ARA::PlugIn::EditorRenderer* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateEditorRenderer() noexcept
{
return specialisation->doCreateEditorRenderer();
}
ARA::PlugIn::EditorView* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateEditorView() noexcept
{
return specialisation->doCreateEditorView();
}
bool ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doIsAudioSourceContentAvailable (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type) noexcept
{
return specialisation->doIsAudioSourceContentAvailable (audioSource, type);
}
ARA::ARAContentGrade ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetAudioSourceContentGrade (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type) noexcept
{
return specialisation->doGetAudioSourceContentGrade (audioSource, type);
}
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateAudioSourceContentReader (ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range) noexcept
{
return specialisation->doCreateAudioSourceContentReader (audioSource, type, range);
}
bool ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doIsAudioModificationContentAvailable (const ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type) noexcept
{
return specialisation->doIsAudioModificationContentAvailable (audioModification, type);
}
ARA::ARAContentGrade ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetAudioModificationContentGrade (const ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type) noexcept
{
return specialisation->doGetAudioModificationContentGrade (audioModification, type);
}
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreateAudioModificationContentReader (ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range) noexcept
{
return specialisation->doCreateAudioModificationContentReader (audioModification, type, range);
}
bool ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doIsPlaybackRegionContentAvailable (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type) noexcept
{
return specialisation->doIsPlaybackRegionContentAvailable (playbackRegion, type);
}
ARA::ARAContentGrade
ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetPlaybackRegionContentGrade (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type) noexcept
{
return specialisation->doGetPlaybackRegionContentGrade (playbackRegion, type);
}
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doCreatePlaybackRegionContentReader (ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range) noexcept
{
return specialisation->doCreatePlaybackRegionContentReader (playbackRegion, type, range);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetPlaybackRegionHeadAndTailTime (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARATimeDuration* headTime,
ARA::ARATimeDuration* tailTime) noexcept
{
specialisation->doGetPlaybackRegionHeadAndTailTime (playbackRegion, headTime, tailTime);
}
bool ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doIsAudioSourceContentAnalysisIncomplete (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type) noexcept
{
return specialisation->doIsAudioSourceContentAnalysisIncomplete (audioSource, type);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doRequestAudioSourceContentAnalysis (ARA::PlugIn::AudioSource* audioSource,
std::vector<ARA::ARAContentType> const& contentTypes) noexcept
{
specialisation->doRequestAudioSourceContentAnalysis (audioSource, contentTypes);
}
ARA::ARAInt32 ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetProcessingAlgorithmsCount() noexcept
{
return specialisation->doGetProcessingAlgorithmsCount();
}
const ARA::ARAProcessingAlgorithmProperties* ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetProcessingAlgorithmProperties (ARA::ARAInt32 algorithmIndex) noexcept
{
return specialisation->doGetProcessingAlgorithmProperties (algorithmIndex);
}
ARA::ARAInt32 ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doGetProcessingAlgorithmForAudioSource (const ARA::PlugIn::AudioSource* audioSource) noexcept
{
return specialisation->doGetProcessingAlgorithmForAudioSource (audioSource);
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::doRequestProcessingAlgorithmForAudioSource (ARA::PlugIn::AudioSource* audioSource,
ARA::ARAInt32 algorithmIndex) noexcept
{
return specialisation->doRequestProcessingAlgorithmForAudioSource (audioSource, algorithmIndex);
}
//==============================================================================
// Helper code for ARADocumentControllerSpecialisation::ARADocumentControllerImpl::timerCallback() to
// rewire the host-related ARA SDK's progress tracker to our internal update mechanism.
namespace ModelUpdateControllerProgressAdapter
{
using namespace ARA;
static void ARA_CALL notifyAudioSourceAnalysisProgress (ARAModelUpdateControllerHostRef /*controllerHostRef*/,
ARAAudioSourceHostRef audioSourceHostRef, ARAAnalysisProgressState state, float value) noexcept
{
auto audioSource = reinterpret_cast<ARAAudioSource*> (audioSourceHostRef);
audioSource->getDocumentController<ARADocumentController>()->internalDidUpdateAudioSourceAnalysisProgress (audioSource, state, value);
audioSource->notifyListeners ([&] (ARAAudioSource::Listener& l) { l.didUpdateAudioSourceAnalysisProgress (audioSource, state, value); });
}
static void ARA_CALL notifyAudioSourceContentChanged (ARAModelUpdateControllerHostRef, ARAAudioSourceHostRef,
const ARAContentTimeRange*, ARAContentUpdateFlags) noexcept
{
jassertfalse; // not to be called - this adapter only forwards analysis progress
}
static void ARA_CALL notifyAudioModificationContentChanged (ARAModelUpdateControllerHostRef, ARAAudioModificationHostRef,
const ARAContentTimeRange*, ARAContentUpdateFlags) noexcept
{
jassertfalse; // not to be called - this adapter only forwards analysis progress
}
static void ARA_CALL notifyPlaybackRegionContentChanged (ARAModelUpdateControllerHostRef, ARAPlaybackRegionHostRef,
const ARAContentTimeRange*, ARAContentUpdateFlags) noexcept
{
jassertfalse; // not to be called - this adapter only forwards analysis progress
}
static ARA::PlugIn::HostModelUpdateController* get()
{
static const auto modelUpdateControllerInterface = makeARASizedStruct (&ARA::ARAModelUpdateControllerInterface::notifyPlaybackRegionContentChanged,
ModelUpdateControllerProgressAdapter::notifyAudioSourceAnalysisProgress,
ModelUpdateControllerProgressAdapter::notifyAudioSourceContentChanged,
ModelUpdateControllerProgressAdapter::notifyAudioModificationContentChanged,
ModelUpdateControllerProgressAdapter::notifyPlaybackRegionContentChanged);
static const auto instance = makeARASizedStruct (&ARA::ARADocumentControllerHostInstance::playbackControllerInterface,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&modelUpdateControllerInterface,
nullptr,
nullptr);
static auto progressAdapter = ARA::PlugIn::HostModelUpdateController { &instance };
return &progressAdapter;
}
}
void ARADocumentControllerSpecialisation::ARADocumentControllerImpl::analysisTimerCallback()
{
if (! internalAnalysisProgressIsSynced.exchange (true, std::memory_order_release))
for (auto& audioSource : getDocument()->getAudioSources())
audioSource->internalAnalysisProgressTracker.notifyProgress (ModelUpdateControllerProgressAdapter::get(),
reinterpret_cast<ARA::ARAAudioSourceHostRef> (audioSource));
}
//==============================================================================
ARAInputStream::ARAInputStream (ARA::PlugIn::HostArchiveReader* reader)
: archiveReader (reader),
size ((int64) reader->getArchiveSize())
{}
int ARAInputStream::read (void* destBuffer, int maxBytesToRead)
{
const auto bytesToRead = std::min ((int64) maxBytesToRead, size - position);
if (bytesToRead > 0 && ! archiveReader->readBytesFromArchive ((ARA::ARASize) position, (ARA::ARASize) bytesToRead,
static_cast<ARA::ARAByte*> (destBuffer)))
{
failure = true;
return 0;
}
position += bytesToRead;
return (int) bytesToRead;
}
bool ARAInputStream::setPosition (int64 newPosition)
{
position = jlimit ((int64) 0, size, newPosition);
return true;
}
bool ARAInputStream::isExhausted()
{
return position >= size;
}
ARAOutputStream::ARAOutputStream (ARA::PlugIn::HostArchiveWriter* writer)
: archiveWriter (writer)
{}
bool ARAOutputStream::write (const void* dataToWrite, size_t numberOfBytes)
{
if (! archiveWriter->writeBytesToArchive ((ARA::ARASize) position, numberOfBytes, (const ARA::ARAByte*) dataToWrite))
return false;
position += (int64) numberOfBytes;
return true;
}
bool ARAOutputStream::setPosition (int64 newPosition)
{
position = newPosition;
return true;
}
//==============================================================================
ARADocumentControllerSpecialisation::ARADocumentControllerSpecialisation (
const ARA::PlugIn::PlugInEntry* entry,
const ARA::ARADocumentControllerHostInstance* instance)
: documentController (std::make_unique<ARADocumentControllerImpl> (entry, instance, this))
{
}
ARADocumentControllerSpecialisation::~ARADocumentControllerSpecialisation() = default;
ARAPlaybackRenderer* ARADocumentControllerSpecialisation::doCreatePlaybackRenderer()
{
return new ARAPlaybackRenderer (getDocumentController());
}
ARAEditorRenderer* ARADocumentControllerSpecialisation::doCreateEditorRenderer()
{
return new ARAEditorRenderer (getDocumentController());
}
ARAEditorView* ARADocumentControllerSpecialisation::doCreateEditorView()
{
return new ARAEditorView (getDocumentController());
}
bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAvailable ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource,
[[maybe_unused]] ARA::ARAContentType type)
{
return false;
}
ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioSourceContentGrade ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource,
[[maybe_unused]] ARA::ARAContentType type)
{
// Overriding doIsAudioSourceContentAvailable() requires overriding
// doGetAudioSourceContentGrade() accordingly!
jassertfalse;
return ARA::kARAContentGradeInitial;
}
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioSourceContentReader ([[maybe_unused]] ARA::PlugIn::AudioSource* audioSource,
[[maybe_unused]] ARA::ARAContentType type,
[[maybe_unused]] const ARA::ARAContentTimeRange* range)
{
// Overriding doIsAudioSourceContentAvailable() requires overriding
// doCreateAudioSourceContentReader() accordingly!
jassertfalse;
return nullptr;
}
bool ARADocumentControllerSpecialisation::doIsAudioModificationContentAvailable ([[maybe_unused]] const ARA::PlugIn::AudioModification* audioModification,
[[maybe_unused]] ARA::ARAContentType type)
{
return false;
}
ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioModificationContentGrade ([[maybe_unused]] const ARA::PlugIn::AudioModification* audioModification,
[[maybe_unused]] ARA::ARAContentType type)
{
// Overriding doIsAudioModificationContentAvailable() requires overriding
// doGetAudioModificationContentGrade() accordingly!
jassertfalse;
return ARA::kARAContentGradeInitial;
}
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioModificationContentReader ([[maybe_unused]] ARA::PlugIn::AudioModification* audioModification,
[[maybe_unused]] ARA::ARAContentType type,
[[maybe_unused]] const ARA::ARAContentTimeRange* range)
{
// Overriding doIsAudioModificationContentAvailable() requires overriding
// doCreateAudioModificationContentReader() accordingly!
jassertfalse;
return nullptr;
}
bool ARADocumentControllerSpecialisation::doIsPlaybackRegionContentAvailable ([[maybe_unused]] const ARA::PlugIn::PlaybackRegion* playbackRegion,
[[maybe_unused]] ARA::ARAContentType type)
{
return false;
}
ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetPlaybackRegionContentGrade ([[maybe_unused]] const ARA::PlugIn::PlaybackRegion* playbackRegion,
[[maybe_unused]] ARA::ARAContentType type)
{
// Overriding doIsPlaybackRegionContentAvailable() requires overriding
// doGetPlaybackRegionContentGrade() accordingly!
jassertfalse;
return ARA::kARAContentGradeInitial;
}
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreatePlaybackRegionContentReader ([[maybe_unused]] ARA::PlugIn::PlaybackRegion* playbackRegion,
[[maybe_unused]] ARA::ARAContentType type,
[[maybe_unused]] const ARA::ARAContentTimeRange* range)
{
// Overriding doIsPlaybackRegionContentAvailable() requires overriding
// doCreatePlaybackRegionContentReader() accordingly!
jassertfalse;
return nullptr;
}
void ARADocumentControllerSpecialisation::doGetPlaybackRegionHeadAndTailTime ([[maybe_unused]] const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARATimeDuration* headTime,
ARA::ARATimeDuration* tailTime)
{
*headTime = 0.0;
*tailTime = 0.0;
}
bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAnalysisIncomplete ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource,
[[maybe_unused]] ARA::ARAContentType type)
{
return false;
}
void ARADocumentControllerSpecialisation::doRequestAudioSourceContentAnalysis ([[maybe_unused]] ARA::PlugIn::AudioSource* audioSource,
[[maybe_unused]] std::vector<ARA::ARAContentType> const& contentTypes)
{
}
ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmsCount() { return 0; }
const ARA::ARAProcessingAlgorithmProperties*
ARADocumentControllerSpecialisation::doGetProcessingAlgorithmProperties ([[maybe_unused]] ARA::ARAInt32 algorithmIndex)
{
return nullptr;
}
ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmForAudioSource ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource)
{
// doGetProcessingAlgorithmForAudioSource() must be implemented if the supported
// algorithm count is greater than zero.
if (getDocumentController()->getProcessingAlgorithmsCount() > 0)
jassertfalse;
return 0;
}
void ARADocumentControllerSpecialisation::doRequestProcessingAlgorithmForAudioSource ([[maybe_unused]] ARA::PlugIn::AudioSource* audioSource,
[[maybe_unused]] ARA::ARAInt32 algorithmIndex)
{
// doRequestProcessingAlgorithmForAudioSource() must be implemented if the supported
// algorithm count is greater than zero.
jassert (getDocumentController()->getProcessingAlgorithmsCount() <= 0);
}
} // namespace juce

View file

@ -1,538 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
namespace juce
{
class ARAPlaybackRenderer;
class ARAEditorRenderer;
class ARAEditorView;
class ARAInputStream;
class ARAOutputStream;
/** This class contains the customisation points for the JUCE provided ARA document controller
implementation.
Every ARA enabled plugin must provide its own document controller implementation. To do this,
inherit from this class, and override its protected methods as needed. Then you need to
implement a global function somewhere in your module called createARAFactory(). This function
must return an ARAFactory* that will instantiate document controller objects using your
specialisation. There are helper functions inside ARADocumentControllerSpecialisation, so the
implementation of createARAFactory() can always be a simple one-liner. For example
@code
class MyDocumentController : public ARADocumentControllerSpecialisation
{
//...
};
const ARA::ARAFactory* JUCE_CALLTYPE createARAFactory()
{
return juce::ARADocumentControllerSpecialisation::createARAFactory<MyDocumentController>();
}
@endcode
Most member functions have a default implementation so you can build up your required feature
set gradually. The protected functions of this class fall in three distinct groups:
- interactive editing and playback,
- analysis features provided by the plugin and utilised by the host, and
- maintaining the ARA model graph.
On top of the pure virtual functions, you will probably want to override
doCreatePlaybackRenderer() at the very least if you want your plugin to play any sound. This
function belongs to the first group.
If your plugin has analysis capabilities and wants to allow the host to access these, functions
in the second group should be overridden.
The default implementation of the ARA model object classes - i.e. ARADocument, ARAMusicalContext,
ARARegionSequence, ARAAudioSource, ARAAudioModification, ARAPlaybackRegion - should be sufficient
for maintaining a representation of the ARA model graph, hence overriding the model object
creation functions e.g. doCreateMusicalContext() is considered an advanced use case. Hence you
should be able to get a lot done without overriding functions in the third group.
In order to react to the various ARA state changes you can override any of the ARA model object
Listener functions that ARADocumentControllerSpecialisation inherits from. Such listener
functions can be attached to one particular model objects instance, but the listener functions
inside ARADocumentControllerSpecialisation will respond to the events of all instances of the
model objects.
@tags{ARA}
*/
class ARADocumentControllerSpecialisation : public ARADocument::Listener,
public ARAMusicalContext::Listener,
public ARARegionSequence::Listener,
public ARAAudioSource::Listener,
public ARAAudioModification::Listener,
public ARAPlaybackRegion::Listener
{
public:
//==============================================================================
/** Constructor. Used internally by the ARAFactory implementation.
*/
ARADocumentControllerSpecialisation (const ARA::PlugIn::PlugInEntry* entry,
const ARA::ARADocumentControllerHostInstance* instance);
/** Destructor. */
virtual ~ARADocumentControllerSpecialisation();
/** Returns the underlying DocumentController object that references this specialisation.
*/
ARA::PlugIn::DocumentController* getDocumentController() noexcept;
/** Helper function for implementing the global createARAFactory() function.
For example
@code
class MyDocumentController : public ARADocumentControllerSpecialisation
{
//...
};
const ARA::ARAFactory* JUCE_CALLTYPE createARAFactory()
{
return juce::ARADocumentControllerSpecialisation::createARAFactory<MyDocumentController>();
}
@endcode
*/
template <typename SpecialisationType>
static const ARA::ARAFactory* createARAFactory()
{
static_assert (std::is_base_of_v<ARADocumentControllerSpecialisation, SpecialisationType>,
"DocumentController specialization types must inherit from ARADocumentControllerSpecialisation");
return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory();
}
/** Returns a pointer to the ARADocumentControllerSpecialisation instance that is referenced
by the provided DocumentController. You can use this function to access your specialisation
from anywhere where you have access to ARA::PlugIn::DocumentController*.
*/
template <typename Specialisation = ARADocumentControllerSpecialisation>
static Specialisation* getSpecialisedDocumentController (ARA::PlugIn::DocumentController* dc)
{
return static_cast<Specialisation*> (getSpecialisedDocumentControllerImpl (dc));
}
/** Returns a pointer to the ARA document root maintained by this document controller. */
template <typename DocumentType = ARADocument>
DocumentType* getDocument()
{
return static_cast<DocumentType*> (getDocumentImpl());
}
protected:
//==============================================================================
/** Read an ARADocument archive from a juce::InputStream.
@param input Data stream containing previously persisted data to be used when restoring the ARADocument
@param filter A filter to be applied to the stream
Return true if the operation is successful.
@see ARADocumentControllerInterface::restoreObjectsFromArchive
*/
virtual bool doRestoreObjectsFromStream (ARAInputStream& input, const ARARestoreObjectsFilter* filter) = 0;
/** Write an ARADocument archive to a juce::OutputStream.
@param output Data stream that should be used to write the persistent ARADocument data
@param filter A filter to be applied to the stream
Returns true if the operation is successful.
@see ARADocumentControllerInterface::storeObjectsToArchive
*/
virtual bool doStoreObjectsToStream (ARAOutputStream& output, const ARAStoreObjectsFilter* filter) = 0;
//==============================================================================
/** Override to return a custom subclass instance of ARAPlaybackRenderer. */
virtual ARAPlaybackRenderer* doCreatePlaybackRenderer();
/** Override to return a custom subclass instance of ARAEditorRenderer. */
virtual ARAEditorRenderer* doCreateEditorRenderer();
/** Override to return a custom subclass instance of ARAEditorView. */
virtual ARAEditorView* doCreateEditorView();
//==============================================================================
// ARAAudioSource content access
/** Override to implement isAudioSourceContentAvailable() for all your supported content types -
the default implementation always returns false, preventing any calls to doGetAudioSourceContentGrade()
and doCreateAudioSourceContentReader().
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doIsAudioSourceContentAvailable.
*/
virtual bool doIsAudioSourceContentAvailable (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type);
/** Override to implement getAudioSourceContentGrade() for all your supported content types.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doGetAudioSourceContentGrade.
*/
virtual ARA::ARAContentGrade doGetAudioSourceContentGrade (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type);
/** Override to implement createAudioSourceContentReader() for all your supported content types,
returning a custom subclass instance of ContentReader providing data of the requested type.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doCreateAudioSourceContentReader.
*/
virtual ARA::PlugIn::ContentReader* doCreateAudioSourceContentReader (ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range);
//==============================================================================
// ARAAudioModification content access
/** Override to implement isAudioModificationContentAvailable() for all your supported content types -
the default implementation always returns false.
For read-only data directly inherited from the underlying audio source you can just delegate the
call to the audio source, but user-editable modification data must be specifically handled here.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doIsAudioModificationContentAvailable.
*/
virtual bool doIsAudioModificationContentAvailable (const ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type);
/** Override to implement getAudioModificationContentGrade() for all your supported content types.
For read-only data directly inherited from the underlying audio source you can just delegate the
call to the audio source, but user-editable modification data must be specifically handled here.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doGetAudioModificationContentGrade.
*/
virtual ARA::ARAContentGrade doGetAudioModificationContentGrade (const ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type);
/** Override to implement createAudioModificationContentReader() for all your supported content types,
returning a custom subclass instance of ContentReader providing data of the requested \p type.
For read-only data directly inherited from the underlying audio source you can just delegate the
call to the audio source, but user-editable modification data must be specifically handled here.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doCreateAudioModificationContentReader.
*/
virtual ARA::PlugIn::ContentReader* doCreateAudioModificationContentReader (ARA::PlugIn::AudioModification* audioModification,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range);
//==============================================================================
// ARAPlaybackRegion content access
/** Override to implement isPlaybackRegionContentAvailable() for all your supported content types -
the default implementation always returns false.
Typically, this call can directly delegate to the underlying audio modification, since most
plug-ins will apply their modification data to the playback region with a transformation that
does not affect content availability.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doIsPlaybackRegionContentAvailable.
*/
virtual bool doIsPlaybackRegionContentAvailable (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type);
/** Override to implement getPlaybackRegionContentGrade() for all your supported content types.
Typically, this call can directly delegate to the underlying audio modification, since most
plug-ins will apply their modification data to the playback region with a transformation that
does not affect content grade.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doGetPlaybackRegionContentGrade.
*/
virtual ARA::ARAContentGrade doGetPlaybackRegionContentGrade (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type);
/** Override to implement createPlaybackRegionContentReader() for all your supported content types,
returning a custom subclass instance of ContentReader providing data of the requested type.
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doCreatePlaybackRegionContentReader.
*/
virtual ARA::PlugIn::ContentReader* doCreatePlaybackRegionContentReader (ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARAContentType type,
const ARA::ARAContentTimeRange* range);
/** Override to implement getPlaybackRegionHeadAndTailTime().
This function is called within
ARA::PlugIn::DocumentControllerDelegate::doGetPlaybackRegionHeadAndTailTime.
*/
virtual void doGetPlaybackRegionHeadAndTailTime (const ARA::PlugIn::PlaybackRegion* playbackRegion,
ARA::ARATimeDuration* headTime,
ARA::ARATimeDuration* tailTime);
//==============================================================================
// ARAAudioSource analysis
/** Override to implement isAudioSourceContentAnalysisIncomplete().
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doIsAudioSourceContentAnalysisIncomplete.
*/
virtual bool doIsAudioSourceContentAnalysisIncomplete (const ARA::PlugIn::AudioSource* audioSource,
ARA::ARAContentType type);
/** Override to implement requestAudioSourceContentAnalysis().
This function's called from
ARA::PlugIn::DocumentControllerDelegate::doRequestAudioSourceContentAnalysis.
*/
virtual void doRequestAudioSourceContentAnalysis (ARA::PlugIn::AudioSource* audioSource,
std::vector<ARA::ARAContentType> const& contentTypes);
//==============================================================================
// Analysis Algorithm selection
/** Override to implement getProcessingAlgorithmsCount().
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doGetProcessingAlgorithmsCount.
*/
virtual ARA::ARAInt32 doGetProcessingAlgorithmsCount ();
/** Override to implement getProcessingAlgorithmProperties().
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doGetProcessingAlgorithmProperties.
*/
virtual const ARA::ARAProcessingAlgorithmProperties*
doGetProcessingAlgorithmProperties (ARA::ARAInt32 algorithmIndex);
/** Override to implement getProcessingAlgorithmForAudioSource().
This function's result is returned from
ARA::PlugIn::DocumentControllerDelegate::doGetProcessingAlgorithmForAudioSource.
*/
virtual ARA::ARAInt32 doGetProcessingAlgorithmForAudioSource (const ARA::PlugIn::AudioSource* audioSource);
/** Override to implement requestProcessingAlgorithmForAudioSource().
This function's called from
ARA::PlugIn::DocumentControllerDelegate::doRequestProcessingAlgorithmForAudioSource.
*/
virtual void doRequestProcessingAlgorithmForAudioSource (ARA::PlugIn::AudioSource* audioSource, ARA::ARAInt32 algorithmIndex);
//==============================================================================
/** Override to return a custom subclass instance of ARADocument. */
virtual ARADocument* doCreateDocument();
/** Override to return a custom subclass instance of ARAMusicalContext. */
virtual ARAMusicalContext* doCreateMusicalContext (ARADocument* document,
ARA::ARAMusicalContextHostRef hostRef);
/** Override to return a custom subclass instance of ARARegionSequence. */
virtual ARARegionSequence* doCreateRegionSequence (ARADocument* document,
ARA::ARARegionSequenceHostRef hostRef);
/** Override to return a custom subclass instance of ARAAudioSource. */
virtual ARAAudioSource* doCreateAudioSource (ARADocument* document,
ARA::ARAAudioSourceHostRef hostRef);
/** Override to return a custom subclass instance of ARAAudioModification. */
virtual ARAAudioModification* doCreateAudioModification (ARAAudioSource* audioSource,
ARA::ARAAudioModificationHostRef hostRef,
const ARAAudioModification* optionalModificationToClone);
/** Override to return a custom subclass instance of ARAPlaybackRegion. */
virtual ARAPlaybackRegion* doCreatePlaybackRegion (ARAAudioModification* modification,
ARA::ARAPlaybackRegionHostRef hostRef);
private:
//==============================================================================
template <typename SpecialisationType>
class FactoryConfig : public ARA::PlugIn::FactoryConfig
{
public:
FactoryConfig() noexcept
{
const juce::String compatibleDocumentArchiveIDString = JucePlugin_ARACompatibleArchiveIDs;
if (compatibleDocumentArchiveIDString.isNotEmpty())
{
compatibleDocumentArchiveIDStrings = juce::StringArray::fromLines (compatibleDocumentArchiveIDString);
for (const auto& compatibleID : compatibleDocumentArchiveIDStrings)
compatibleDocumentArchiveIDs.push_back (compatibleID.toRawUTF8());
}
// Update analyzeable content types
static constexpr std::array<ARA::ARAContentType, 6> contentTypes {
ARA::kARAContentTypeNotes,
ARA::kARAContentTypeTempoEntries,
ARA::kARAContentTypeBarSignatures,
ARA::kARAContentTypeStaticTuning,
ARA::kARAContentTypeKeySignatures,
ARA::kARAContentTypeSheetChords
};
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6313)
for (size_t i = 0; i < contentTypes.size(); ++i)
if (JucePlugin_ARAContentTypes & (1 << i))
analyzeableContentTypes.push_back (contentTypes[i]);
JUCE_END_IGNORE_WARNINGS_MSVC
// Update playback transformation flags
static constexpr std::array<ARA::ARAPlaybackTransformationFlags, 4> playbackTransformationFlags {
ARA::kARAPlaybackTransformationTimestretch,
ARA::kARAPlaybackTransformationTimestretchReflectingTempo,
ARA::kARAPlaybackTransformationContentBasedFadeAtTail,
ARA::kARAPlaybackTransformationContentBasedFadeAtHead
};
supportedPlaybackTransformationFlags = 0;
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6313)
for (size_t i = 0; i < playbackTransformationFlags.size(); ++i)
if (JucePlugin_ARATransformationFlags & (1 << i))
supportedPlaybackTransformationFlags |= playbackTransformationFlags[i];
JUCE_END_IGNORE_WARNINGS_MSVC
}
const char* getFactoryID() const noexcept override { return JucePlugin_ARAFactoryID; }
const char* getPlugInName() const noexcept override { return JucePlugin_Name; }
const char* getManufacturerName() const noexcept override { return JucePlugin_Manufacturer; }
const char* getInformationURL() const noexcept override { return JucePlugin_ManufacturerWebsite; }
const char* getVersion() const noexcept override { return JucePlugin_VersionString; }
const char* getDocumentArchiveID() const noexcept override { return JucePlugin_ARADocumentArchiveID; }
ARA::ARASize getCompatibleDocumentArchiveIDsCount() const noexcept override
{
return compatibleDocumentArchiveIDs.size();
}
const ARA::ARAPersistentID* getCompatibleDocumentArchiveIDs() const noexcept override
{
return compatibleDocumentArchiveIDs.empty() ? nullptr : compatibleDocumentArchiveIDs.data();
}
ARA::ARASize getAnalyzeableContentTypesCount() const noexcept override
{
return analyzeableContentTypes.size();
}
const ARA::ARAContentType* getAnalyzeableContentTypes() const noexcept override
{
return analyzeableContentTypes.empty() ? nullptr : analyzeableContentTypes.data();
}
ARA::ARAPlaybackTransformationFlags getSupportedPlaybackTransformationFlags() const noexcept override
{
return supportedPlaybackTransformationFlags;
}
ARA::PlugIn::DocumentController* createDocumentController (const ARA::PlugIn::PlugInEntry* entry,
const ARA::ARADocumentControllerHostInstance* instance) const noexcept override
{
auto* spec = new SpecialisationType (entry, instance);
return spec->getDocumentController();
}
void destroyDocumentController (ARA::PlugIn::DocumentController* controller) const noexcept override
{
delete getSpecialisedDocumentController (controller);
}
private:
juce::StringArray compatibleDocumentArchiveIDStrings;
std::vector<ARA::ARAPersistentID> compatibleDocumentArchiveIDs;
std::vector<ARA::ARAContentType> analyzeableContentTypes;
ARA::ARAPlaybackTransformationFlags supportedPlaybackTransformationFlags;
};
//==============================================================================
static ARADocumentControllerSpecialisation* getSpecialisedDocumentControllerImpl (ARA::PlugIn::DocumentController*);
ARADocument* getDocumentImpl();
//==============================================================================
class ARADocumentControllerImpl;
std::unique_ptr<ARADocumentControllerImpl> documentController;
};
/** Used to read persisted ARA archives - see doRestoreObjectsFromStream() for details.
@tags{ARA}
*/
class ARAInputStream : public InputStream
{
public:
explicit ARAInputStream (ARA::PlugIn::HostArchiveReader*);
int64 getPosition() override { return position; }
int64 getTotalLength() override { return size; }
int read (void*, int) override;
bool setPosition (int64) override;
bool isExhausted() override;
bool failed() const { return failure; }
private:
ARA::PlugIn::HostArchiveReader* archiveReader;
int64 position = 0;
int64 size;
bool failure = false;
};
/** Used to write persistent ARA archives - see doStoreObjectsToStream() for details.
@tags{ARA}
*/
class ARAOutputStream : public OutputStream
{
public:
explicit ARAOutputStream (ARA::PlugIn::HostArchiveWriter*);
int64 getPosition() override { return position; }
void flush() override {}
bool write (const void*, size_t) override;
bool setPosition (int64) override;
private:
ARA::PlugIn::HostArchiveWriter* archiveWriter;
int64 position = 0;
};
} // namespace juce

View file

@ -1,80 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
class ARADocumentController : public ARA::PlugIn::DocumentController
{
public:
using ARA::PlugIn::DocumentController::DocumentController;
template <typename Document_t = ARADocument>
Document_t* getDocument() const noexcept { return ARA::PlugIn::DocumentController::getDocument<Document_t>(); }
//==============================================================================
/** @internal */
virtual void internalNotifyAudioSourceAnalysisProgressStarted (ARAAudioSource* audioSource) = 0;
/** @internal */
virtual void internalNotifyAudioSourceAnalysisProgressUpdated (ARAAudioSource* audioSource, float progress) = 0;
/** @internal */
virtual void internalNotifyAudioSourceAnalysisProgressCompleted (ARAAudioSource* audioSource) = 0;
/** @internal */
virtual void internalDidUpdateAudioSourceAnalysisProgress (ARAAudioSource* audioSource,
ARAAudioSource::ARAAnalysisProgressState state,
float progress) = 0;
//==============================================================================
/** @internal */
virtual void internalNotifyAudioSourceContentChanged (ARAAudioSource* audioSource,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost) = 0;
/** @internal */
virtual void internalNotifyAudioModificationContentChanged (ARAAudioModification* audioModification,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost) = 0;
/** @internal */
virtual void internalNotifyPlaybackRegionContentChanged (ARAPlaybackRegion* playbackRegion,
ARAContentUpdateScopes scopeFlags,
bool notifyARAHost) = 0;
friend class ARAPlaybackRegionReader;
};
} // namespace juce

View file

@ -1,302 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
size_t ARADocument::getNumChildren() const noexcept
{
return getMusicalContexts().size() + getRegionSequences().size() + getAudioSources().size();
}
ARAObject* ARADocument::getChild (size_t index)
{
auto& musicalContexts = getMusicalContexts();
if (index < musicalContexts.size())
return musicalContexts[index];
const auto numMusicalContexts = musicalContexts.size();
auto& regionSequences = getRegionSequences();
if (index < numMusicalContexts + regionSequences.size())
return regionSequences[index - numMusicalContexts];
const auto numMusicalContextsAndRegionSequences = numMusicalContexts + regionSequences.size();
auto& audioSources = getAudioSources();
if (index < numMusicalContextsAndRegionSequences + audioSources.size())
return getAudioSources()[index - numMusicalContextsAndRegionSequences];
return nullptr;
}
//==============================================================================
size_t ARARegionSequence::getNumChildren() const noexcept
{
return 0;
}
ARAObject* ARARegionSequence::getChild (size_t)
{
return nullptr;
}
Range<double> ARARegionSequence::getTimeRange (ARAPlaybackRegion::IncludeHeadAndTail includeHeadAndTail) const
{
if (getPlaybackRegions().empty())
return {};
auto startTime = std::numeric_limits<double>::max();
auto endTime = std::numeric_limits<double>::lowest();
for (const auto& playbackRegion : getPlaybackRegions())
{
const auto regionTimeRange = playbackRegion->getTimeRange (includeHeadAndTail);
startTime = jmin (startTime, regionTimeRange.getStart());
endTime = jmax (endTime, regionTimeRange.getEnd());
}
return { startTime, endTime };
}
double ARARegionSequence::getCommonSampleRate() const
{
const auto getSampleRate = [] (auto* playbackRegion)
{
return playbackRegion->getAudioModification()->getAudioSource()->getSampleRate();
};
const auto range = getPlaybackRegions();
const auto sampleRate = range.size() > 0 ? getSampleRate (range.front()) : 0.0;
if (std::any_of (range.begin(), range.end(), [&] (auto& x) { return ! exactlyEqual (getSampleRate (x), sampleRate); }))
return 0.0;
return sampleRate;
}
//==============================================================================
size_t ARAAudioSource::getNumChildren() const noexcept
{
return getAudioModifications().size();
}
ARAObject* ARAAudioSource::getChild (size_t index)
{
return getAudioModifications()[index];
}
void ARAAudioSource::notifyAnalysisProgressStarted()
{
getDocumentController<ARADocumentController>()->internalNotifyAudioSourceAnalysisProgressStarted (this);
}
void ARAAudioSource::notifyAnalysisProgressUpdated (float progress)
{
getDocumentController<ARADocumentController>()->internalNotifyAudioSourceAnalysisProgressUpdated (this, progress);
}
void ARAAudioSource::notifyAnalysisProgressCompleted()
{
getDocumentController<ARADocumentController>()->internalNotifyAudioSourceAnalysisProgressCompleted (this);
}
void ARAAudioSource::notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost)
{
getDocumentController<ARADocumentController>()->internalNotifyAudioSourceContentChanged (this,
scopeFlags,
notifyARAHost);
}
//==============================================================================
size_t ARAAudioModification::getNumChildren() const noexcept
{
return getPlaybackRegions().size();
}
ARAObject* ARAAudioModification::getChild (size_t index)
{
return getPlaybackRegions()[index];
}
void ARAAudioModification::notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost)
{
getDocumentController<ARADocumentController>()->internalNotifyAudioModificationContentChanged (this,
scopeFlags,
notifyARAHost);
}
//==============================================================================
ARAObject* ARAPlaybackRegion::getParent() { return getAudioModification(); }
Range<double> ARAPlaybackRegion::getTimeRange (IncludeHeadAndTail includeHeadAndTail) const
{
auto startTime = getStartInPlaybackTime();
auto endTime = getEndInPlaybackTime();
if (includeHeadAndTail == IncludeHeadAndTail::yes)
{
ARA::ARATimeDuration headTime {}, tailTime {};
getDocumentController()->getPlaybackRegionHeadAndTailTime (toRef (this), &headTime, &tailTime);
startTime -= headTime;
endTime += tailTime;
}
return { startTime, endTime };
}
Range<int64> ARAPlaybackRegion::getSampleRange (double sampleRate, IncludeHeadAndTail includeHeadAndTail) const
{
const auto timeRange = getTimeRange (includeHeadAndTail);
return { ARA::samplePositionAtTime (timeRange.getStart(), sampleRate),
ARA::samplePositionAtTime (timeRange.getEnd(), sampleRate) };
}
double ARAPlaybackRegion::getHeadTime() const
{
ARA::ARATimeDuration headTime {}, tailTime {};
getDocumentController()->getPlaybackRegionHeadAndTailTime (toRef (this), &headTime, &tailTime);
return headTime;
}
double ARAPlaybackRegion::getTailTime() const
{
ARA::ARATimeDuration headTime {}, tailTime {};
getDocumentController()->getPlaybackRegionHeadAndTailTime (toRef (this), &headTime, &tailTime);
return tailTime;
}
void ARAPlaybackRegion::notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost)
{
getDocumentController<ARADocumentController>()->internalNotifyPlaybackRegionContentChanged (this,
scopeFlags,
notifyARAHost);
}
//==============================================================================
void ARADocumentListener::willBeginEditing ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::didEndEditing ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::willNotifyModelUpdates ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::didNotifyModelUpdates ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::willUpdateDocumentProperties ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties> newProperties) {}
void ARADocumentListener::didUpdateDocumentProperties ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::didAddMusicalContextToDocument ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARAMusicalContext* musicalContext) {}
void ARADocumentListener::willRemoveMusicalContextFromDocument ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARAMusicalContext* musicalContext) {}
void ARADocumentListener::didReorderMusicalContextsInDocument ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::didAddRegionSequenceToDocument ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARARegionSequence* regionSequence) {}
void ARADocumentListener::willRemoveRegionSequenceFromDocument ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARARegionSequence* regionSequence) {}
void ARADocumentListener::didReorderRegionSequencesInDocument ([[maybe_unused]] ARADocument* document) {}
void ARADocumentListener::didAddAudioSourceToDocument ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARAAudioSource* audioSource) {}
void ARADocumentListener::willRemoveAudioSourceFromDocument ([[maybe_unused]] ARADocument* document,
[[maybe_unused]] ARAAudioSource* audioSource) {}
void ARADocumentListener::willDestroyDocument ([[maybe_unused]] ARADocument* document) {}
//==============================================================================
void ARAMusicalContextListener::willUpdateMusicalContextProperties ([[maybe_unused]] ARAMusicalContext* musicalContext,
[[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties> newProperties) {}
void ARAMusicalContextListener::didUpdateMusicalContextProperties ([[maybe_unused]] ARAMusicalContext* musicalContext) {}
void ARAMusicalContextListener::doUpdateMusicalContextContent ([[maybe_unused]] ARAMusicalContext* musicalContext,
[[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}
void ARAMusicalContextListener::didAddRegionSequenceToMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext,
[[maybe_unused]] ARARegionSequence* regionSequence) {}
void ARAMusicalContextListener::willRemoveRegionSequenceFromMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext,
[[maybe_unused]] ARARegionSequence* regionSequence) {}
void ARAMusicalContextListener::didReorderRegionSequencesInMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext) {}
void ARAMusicalContextListener::willDestroyMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext) {}
//==============================================================================
void ARAPlaybackRegionListener::willUpdatePlaybackRegionProperties ([[maybe_unused]] ARAPlaybackRegion* playbackRegion,
[[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties> newProperties) {}
void ARAPlaybackRegionListener::didUpdatePlaybackRegionProperties ([[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}
void ARAPlaybackRegionListener::didUpdatePlaybackRegionContent ([[maybe_unused]] ARAPlaybackRegion* playbackRegion,
[[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}
void ARAPlaybackRegionListener::willDestroyPlaybackRegion ([[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}
//==============================================================================
void ARARegionSequenceListener::willUpdateRegionSequenceProperties ([[maybe_unused]] ARARegionSequence* regionSequence,
[[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties> newProperties) {}
void ARARegionSequenceListener::didUpdateRegionSequenceProperties ([[maybe_unused]] ARARegionSequence* regionSequence) {}
void ARARegionSequenceListener::willRemovePlaybackRegionFromRegionSequence ([[maybe_unused]] ARARegionSequence* regionSequence,
[[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}
void ARARegionSequenceListener::didAddPlaybackRegionToRegionSequence ([[maybe_unused]] ARARegionSequence* regionSequence,
[[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}
void ARARegionSequenceListener::willDestroyRegionSequence ([[maybe_unused]] ARARegionSequence* regionSequence) {}
//==============================================================================
void ARAAudioSourceListener::willUpdateAudioSourceProperties ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties> newProperties) {}
void ARAAudioSourceListener::didUpdateAudioSourceProperties ([[maybe_unused]] ARAAudioSource* audioSource) {}
void ARAAudioSourceListener::doUpdateAudioSourceContent ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}
void ARAAudioSourceListener::didUpdateAudioSourceAnalysisProgress ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] ARA::ARAAnalysisProgressState state,
[[maybe_unused]] float progress) {}
void ARAAudioSourceListener::willEnableAudioSourceSamplesAccess ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] bool enable) {}
void ARAAudioSourceListener::didEnableAudioSourceSamplesAccess ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] bool enable) {}
void ARAAudioSourceListener::willDeactivateAudioSourceForUndoHistory ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] bool deactivate) {}
void ARAAudioSourceListener::didDeactivateAudioSourceForUndoHistory ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] bool deactivate) {}
void ARAAudioSourceListener::didAddAudioModificationToAudioSource ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] ARAAudioModification* audioModification) {}
void ARAAudioSourceListener::willRemoveAudioModificationFromAudioSource ([[maybe_unused]] ARAAudioSource* audioSource,
[[maybe_unused]] ARAAudioModification* audioModification) {}
void ARAAudioSourceListener::willDestroyAudioSource ([[maybe_unused]] ARAAudioSource* audioSource) {}
//==============================================================================
void ARAAudioModificationListener::willUpdateAudioModificationProperties ([[maybe_unused]] ARAAudioModification* audioModification,
[[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties> newProperties) {}
void ARAAudioModificationListener::didUpdateAudioModificationProperties ([[maybe_unused]] ARAAudioModification* audioModification) {}
void ARAAudioModificationListener::didUpdateAudioModificationContent ([[maybe_unused]] ARAAudioModification* audioModification,
[[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}
void ARAAudioModificationListener::willDeactivateAudioModificationForUndoHistory ([[maybe_unused]] ARAAudioModification* audioModification,
[[maybe_unused]] bool deactivate) {}
void ARAAudioModificationListener::didDeactivateAudioModificationForUndoHistory ([[maybe_unused]] ARAAudioModification* audioModification,
[[maybe_unused]] bool deactivate) {}
void ARAAudioModificationListener::didAddPlaybackRegionToAudioModification ([[maybe_unused]] ARAAudioModification* audioModification,
[[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}
void ARAAudioModificationListener::willRemovePlaybackRegionFromAudioModification ([[maybe_unused]] ARAAudioModification* audioModification,
[[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}
void ARAAudioModificationListener::willDestroyAudioModification ([[maybe_unused]] ARAAudioModification* audioModification) {}
} // namespace juce

View file

@ -1,983 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
namespace juce
{
class ARADocumentController;
class ARADocument;
class ARAMusicalContext;
class ARARegionSequence;
class ARAAudioSource;
class ARAAudioModification;
class ARAPlaybackRegion;
/** Base class used by the JUCE ARA model objects to provide listenable interfaces.
@tags{ARA}
*/
template <class ListenerType>
class JUCE_API ARAListenableModelClass
{
public:
/** Constructor. */
ARAListenableModelClass() = default;
/** Destructor. */
virtual ~ARAListenableModelClass() = default;
/** Subscribe \p l to notified by changes to the object.
@param l The listener instance.
*/
void addListener (ListenerType* l) { listeners.add (l); }
/** Unsubscribe \p l from object notifications.
@param l The listener instance.
*/
void removeListener (ListenerType* l) { listeners.remove (l); }
/** Call the provided callback for each of the added listeners. */
template <typename Callback>
void notifyListeners (Callback&& callback)
{
listeners.call (callback);
}
private:
ListenerList<ListenerType> listeners;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAListenableModelClass)
};
/** Create a derived implementation of this class and pass it to ARAObject::visit() to retrieve the
concrete type of a model object.
Combined with ARAObject::traverse() on the ARADocument object it is possible to discover the
entire model graph.
Note that the references passed to the visit member functions are only guaranteed to live for
the duration of the function call, so don't store pointers to these objects!
@tags{Audio}
*/
class ARAObjectVisitor
{
public:
/** Destructor. */
virtual ~ARAObjectVisitor() = default;
/** Called when visiting an ARADocument object. */
virtual void visitDocument (juce::ARADocument&) {}
/** Called when visiting an ARAMusicalContext object. */
virtual void visitMusicalContext (juce::ARAMusicalContext&) {}
/** Called when visiting an ARARegionSequence object. */
virtual void visitRegionSequence (juce::ARARegionSequence&) {}
/** Called when visiting an ARAPlaybackRegion object. */
virtual void visitPlaybackRegion (juce::ARAPlaybackRegion&) {}
/** Called when visiting an ARAAudioModification object. */
virtual void visitAudioModification (juce::ARAAudioModification&) {}
/** Called when visiting an ARAAudioSource object. */
virtual void visitAudioSource (juce::ARAAudioSource&) {}
};
/** Common base class for all JUCE ARA model objects to aid with the discovery and traversal of the
entire ARA model graph.
@tags{ARA}
*/
class ARAObject
{
public:
/** Destructor. */
virtual ~ARAObject() = default;
/** Returns the number of ARA model objects aggregated by this object. Objects that are merely
referred to, but not aggregated by the current object are not included in this count, e.g.
a referenced RegionSequence does not count as a child of the referring PlaybackRegion.
See the ARA documentation's ARA Model Graph Overview for more details.
*/
virtual size_t getNumChildren() const noexcept = 0;
/** Returns the child object associated with the given index.
The index should be smaller than the value returned by getNumChildren().
Note that the index of a particular object may change when the ARA model graph is edited.
*/
virtual ARAObject* getChild (size_t index) = 0;
/** Returns the ARA model object that aggregates this object.
Returns nullptr for the ARADocument root object.
*/
virtual ARAObject* getParent() = 0;
/** Implements a depth first traversal of the ARA model graph starting from the current object,
and visiting its children recursively.
The provided function should accept a single ARAObject& parameter.
*/
template <typename Fn>
void traverse (Fn&& fn)
{
fn (*this);
for (size_t i = 0; i < getNumChildren(); ++i)
{
getChild (i)->traverse (fn);
}
}
/** Allows the retrieval of the concrete type of a model object.
To use this, create a new class derived from ARAObjectVisitor and override its functions
depending on which concrete types you are interested in.
Calling this function inside the function passed to ARAObject::traverse() allows you to
map the entire ARA model graph.
*/
virtual void visit (ARAObjectVisitor& visitor) = 0;
};
/** A base class for listeners that want to know about changes to an ARADocument object.
Use ARADocument::addListener() to register your listener with an ARADocument.
@tags{ARA}
*/
class JUCE_API ARADocumentListener
{
public:
/** Destructor */
virtual ~ARADocumentListener() = default;
/** Called before the document enters an editing state.
@param document The document about to enter an editing state.
*/
virtual void willBeginEditing (ARADocument* document);
/** Called after the document exits an editing state.
@param document The document about exit an editing state.
*/
virtual void didEndEditing (ARADocument* document);
/** Called before sending model updates do the host.
@param document The document whose model updates are about to be sent.
*/
virtual void willNotifyModelUpdates (ARADocument* document);
/** Called after sending model updates do the host.
@param document The document whose model updates have just been sent.
*/
virtual void didNotifyModelUpdates (ARADocument* document);
/** Called before the document's properties are updated.
@param document The document whose properties will be updated.
@param newProperties The document properties that will be assigned to \p document.
*/
virtual void willUpdateDocumentProperties (ARADocument* document,
ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties> newProperties);
/** Called after the document's properties are updated.
@param document The document whose properties were updated.
*/
virtual void didUpdateDocumentProperties (ARADocument* document);
/** Called after a musical context is added to the document.
@param document The document that \p musicalContext was added to.
@param musicalContext The musical context that was added to \p document.
*/
virtual void didAddMusicalContextToDocument (ARADocument* document, ARAMusicalContext* musicalContext);
/** Called before a musical context is removed from the document.
@param document The document that \p musicalContext will be removed from.
@param musicalContext The musical context that will be removed from \p document.
*/
virtual void willRemoveMusicalContextFromDocument (ARADocument* document, ARAMusicalContext* musicalContext);
/** Called after the musical contexts are reordered in an ARA document
Musical contexts are sorted by their order index -
this callback signals a change in this ordering within the document.
@param document The document with reordered musical contexts.
*/
virtual void didReorderMusicalContextsInDocument (ARADocument* document);
/** Called after a region sequence is added to the document.
@param document The document that \p regionSequence was added to.
@param regionSequence The region sequence that was added to \p document.
*/
virtual void didAddRegionSequenceToDocument (ARADocument* document, ARARegionSequence* regionSequence);
/** Called before a region sequence is removed from the document.
@param document The document that \p regionSequence will be removed from.
@param regionSequence The region sequence that will be removed from \p document.
*/
virtual void willRemoveRegionSequenceFromDocument (ARADocument* document, ARARegionSequence* regionSequence);
/** Called after the region sequences are reordered in an ARA document
Region sequences are sorted by their order index -
this callback signals a change in this ordering within the document.
@param document The document with reordered region sequences.
*/
virtual void didReorderRegionSequencesInDocument (ARADocument* document);
/** Called after an audio source is added to the document.
@param document The document that \p audioSource was added to.
@param audioSource The audio source that was added to \p document.
*/
virtual void didAddAudioSourceToDocument (ARADocument* document, ARAAudioSource* audioSource);
/** Called before an audio source is removed from the document.
@param document The document that \p audioSource will be removed from .
@param audioSource The audio source that will be removed from \p document.
*/
virtual void willRemoveAudioSourceFromDocument (ARADocument* document, ARAAudioSource* audioSource);
/** Called before the document is destroyed by the ARA host.
@param document The document that will be destroyed.
*/
virtual void willDestroyDocument (ARADocument* document);
};
//==============================================================================
/** Base class representing an ARA document.
@tags{ARA}
*/
class JUCE_API ARADocument : public ARA::PlugIn::Document,
public ARAListenableModelClass<ARADocumentListener>,
public ARAObject
{
public:
using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties>;
using Listener = ARADocumentListener;
using ARA::PlugIn::Document::Document;
/** Returns the result of ARA::PlugIn::Document::getAudioSources() with the pointers within
cast to ARAAudioSource*.
If you have overridden ARADocumentControllerSpecialisation::doCreateAudioSource(), then
you can use the template parameter to cast the pointers to your subclass of ARAAudioSource.
*/
template <typename AudioSource_t = ARAAudioSource>
const std::vector<AudioSource_t*>& getAudioSources() const noexcept
{
return ARA::PlugIn::Document::getAudioSources<AudioSource_t>();
}
/** Returns the result of ARA::PlugIn::Document::getMusicalContexts() with the pointers within
cast to ARAMusicalContext*.
If you have overridden ARADocumentControllerSpecialisation::doCreateMusicalContext(), then
you can use the template parameter to cast the pointers to your subclass of ARAMusicalContext.
*/
template <typename MusicalContext_t = ARAMusicalContext>
const std::vector<MusicalContext_t*>& getMusicalContexts() const noexcept
{
return ARA::PlugIn::Document::getMusicalContexts<MusicalContext_t>();
}
/** Returns the result of ARA::PlugIn::Document::getRegionSequences() with the pointers within
cast to ARARegionSequence*.
If you have overridden ARADocumentControllerSpecialisation::doCreateRegionSequence(), then
you can use the template parameter to cast the pointers to your subclass of ARARegionSequence.
*/
template <typename RegionSequence_t = ARARegionSequence>
const std::vector<RegionSequence_t*>& getRegionSequences() const noexcept
{
return ARA::PlugIn::Document::getRegionSequences<RegionSequence_t>();
}
size_t getNumChildren() const noexcept override;
ARAObject* getChild (size_t index) override;
ARAObject* getParent() override { return nullptr; }
void visit (ARAObjectVisitor& visitor) override { visitor.visitDocument (*this); }
};
/** A base class for listeners that want to know about changes to an ARAMusicalContext object.
Use ARAMusicalContext::addListener() to register your listener with an ARAMusicalContext.
@tags{ARA}
*/
class JUCE_API ARAMusicalContextListener
{
public:
virtual ~ARAMusicalContextListener() = default;
/** Called before the musical context's properties are updated.
@param musicalContext The musical context whose properties will be updated.
@param newProperties The musical context properties that will be assigned to \p musicalContext.
*/
virtual void willUpdateMusicalContextProperties (ARAMusicalContext* musicalContext,
ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties> newProperties);
/** Called after the musical context's properties are updated by the host.
@param musicalContext The musical context whose properties were updated.
*/
virtual void didUpdateMusicalContextProperties (ARAMusicalContext* musicalContext);
/** Called when the musical context's content (i.e tempo entries or chords) changes.
@param musicalContext The musical context with updated content.
@param scopeFlags The scope of the content update indicating what has changed.
*/
virtual void doUpdateMusicalContextContent (ARAMusicalContext* musicalContext, ARAContentUpdateScopes scopeFlags);
/** Called after a region sequence is added to the musical context.
@param musicalContext The musical context that \p regionSequence was added to.
@param regionSequence The region sequence that was added to \p musicalContext.
*/
virtual void didAddRegionSequenceToMusicalContext (ARAMusicalContext* musicalContext, ARARegionSequence* regionSequence);
/** Called before a region sequence is removed from the musical context.
@param musicalContext The musical context that \p regionSequence will be removed from.
@param regionSequence The region sequence that will be removed from \p musicalContext.
*/
virtual void willRemoveRegionSequenceFromMusicalContext (ARAMusicalContext* musicalContext,
ARARegionSequence* regionSequence);
/** Called after the region sequences are reordered in an ARA MusicalContext
Region sequences are sorted by their order index -
this callback signals a change in this ordering within the musical context.
@param musicalContext The musical context with reordered region sequences.
*/
virtual void didReorderRegionSequencesInMusicalContext (ARAMusicalContext* musicalContext);
/** Called before the musical context is destroyed.
@param musicalContext The musical context that will be destroyed.
*/
virtual void willDestroyMusicalContext (ARAMusicalContext* musicalContext);
};
//==============================================================================
/** Base class representing an ARA musical context.
@tags{ARA}
*/
class JUCE_API ARAMusicalContext : public ARA::PlugIn::MusicalContext,
public ARAListenableModelClass<ARAMusicalContextListener>,
public ARAObject
{
public:
using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties>;
using Listener = ARAMusicalContextListener;
using ARA::PlugIn::MusicalContext::MusicalContext;
/** Returns the result of ARA::PlugIn::MusicalContext::getDocument() with the pointer cast
to ARADocument*.
If you have overridden ARADocumentControllerSpecialisation::doCreateDocument(), then you
can use the template parameter to cast the pointers to your subclass of ARADocument.
*/
template <typename Document_t = ARADocument>
Document_t* getDocument() const noexcept
{
return ARA::PlugIn::MusicalContext::getDocument<Document_t>();
}
/** Returns the result of ARA::PlugIn::MusicalContext::getRegionSequences() with the pointers
within cast to ARARegionSequence*.
If you have overridden ARADocumentControllerSpecialisation::doCreateRegionSequence(), then you
can use the template parameter to cast the pointers to your subclass of ARARegionSequence.
*/
template <typename RegionSequence_t = ARARegionSequence>
const std::vector<RegionSequence_t*>& getRegionSequences() const noexcept
{
return ARA::PlugIn::MusicalContext::getRegionSequences<RegionSequence_t>();
}
size_t getNumChildren() const noexcept override { return 0; }
ARAObject* getChild (size_t) override { return nullptr; }
ARAObject* getParent() override { return getDocument(); }
void visit (ARAObjectVisitor& visitor) override { visitor.visitMusicalContext (*this); }
};
/** A base class for listeners that want to know about changes to an ARAPlaybackRegion object.
Use ARAPlaybackRegion::addListener() to register your listener with an ARAPlaybackRegion.
@tags{ARA}
*/
class JUCE_API ARAPlaybackRegionListener
{
public:
/** Destructor. */
virtual ~ARAPlaybackRegionListener() = default;
/** Called before the playback region's properties are updated.
@param playbackRegion The playback region whose properties will be updated.
@param newProperties The playback region properties that will be assigned to \p playbackRegion.
*/
virtual void willUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion,
ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties> newProperties);
/** Called after the playback region's properties are updated.
@param playbackRegion The playback region whose properties were updated.
*/
virtual void didUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion);
/** Called when the playback region's content (i.e. samples or notes) changes.
@param playbackRegion The playback region with updated content.
@param scopeFlags The scope of the content update.
*/
virtual void didUpdatePlaybackRegionContent (ARAPlaybackRegion* playbackRegion,
ARAContentUpdateScopes scopeFlags);
/** Called before the playback region is destroyed.
@param playbackRegion The playback region that will be destroyed.
*/
virtual void willDestroyPlaybackRegion (ARAPlaybackRegion* playbackRegion);
};
//==============================================================================
/** Base class representing an ARA playback region.
@tags{ARA}
*/
class JUCE_API ARAPlaybackRegion : public ARA::PlugIn::PlaybackRegion,
public ARAListenableModelClass<ARAPlaybackRegionListener>,
public ARAObject
{
public:
using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties>;
using Listener = ARAPlaybackRegionListener;
using ARA::PlugIn::PlaybackRegion::PlaybackRegion;
/** Returns the result of ARA::PlugIn::PlaybackRegion::getAudioModification() with the pointer cast
to ARAAudioModification*.
If you have overridden ARADocumentControllerSpecialisation::doCreateAudioModification(), then you
can use the template parameter to cast the pointers to your subclass of ARAAudioModification.
*/
template <typename AudioModification_t = ARAAudioModification>
AudioModification_t* getAudioModification() const noexcept
{
return ARA::PlugIn::PlaybackRegion::getAudioModification<AudioModification_t>();
}
/** Returns the result of ARA::PlugIn::PlaybackRegion::getRegionSequence() with the pointer cast
to ARARegionSequence*.
If you have overridden ARADocumentControllerSpecialisation::doCreateRegionSequence(), then you
can use the template parameter to cast the pointers to your subclass of ARARegionSequence.
*/
template <typename RegionSequence_t = ARARegionSequence>
RegionSequence_t* getRegionSequence() const noexcept
{
return ARA::PlugIn::PlaybackRegion::getRegionSequence<RegionSequence_t>();
}
size_t getNumChildren() const noexcept override { return 0; }
ARAObject* getChild (size_t) override { return nullptr; }
ARAObject* getParent() override;
void visit (ARAObjectVisitor& visitor) override { visitor.visitPlaybackRegion (*this); }
/** Used in getTimeRange to indicate whether the head and tail times should be included in the result.
*/
enum class IncludeHeadAndTail { no, yes };
/** Returns the playback time range of this playback region.
@param includeHeadAndTail Whether or not the range includes the head and tail
time of all playback regions in the sequence.
*/
Range<double> getTimeRange (IncludeHeadAndTail includeHeadAndTail = IncludeHeadAndTail::no) const;
/** Returns the playback sample range of this playback region.
@param sampleRate The rate at which the sample position should be calculated from
the time range.
@param includeHeadAndTail Whether or not the range includes the head and tail
time of all playback regions in the sequence.
*/
Range<int64> getSampleRange (double sampleRate, IncludeHeadAndTail includeHeadAndTail = IncludeHeadAndTail::no) const;
/** Get the head length in seconds before the start of the region's playback time. */
double getHeadTime() const;
/** Get the tail length in seconds after the end of the region's playback time. */
double getTailTime() const;
/** Notify the ARA host and any listeners of a content update initiated by the plug-in.
This must be called by the plug-in model management code on the message thread whenever updating
the internal content representation, such as after the user edited the pitch of a note in the
underlying audio modification.
Listeners will be notified immediately. If \p notifyARAHost is true, a notification to the host
will be enqueued and sent out the next time it polls for updates.
@param scopeFlags The scope of the content update.
@param notifyARAHost If true, the ARA host will be notified of the content change.
*/
void notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost);
};
/** A base class for listeners that want to know about changes to an ARARegionSequence object.
Use ARARegionSequence::addListener() to register your listener with an ARARegionSequence.
@tags{ARA}
*/
class JUCE_API ARARegionSequenceListener
{
public:
/** Destructor. */
virtual ~ARARegionSequenceListener() = default;
/** Called before the region sequence's properties are updated.
@param regionSequence The region sequence whose properties will be updated.
@param newProperties The region sequence properties that will be assigned to \p regionSequence.
*/
virtual void willUpdateRegionSequenceProperties (ARARegionSequence* regionSequence,
ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties> newProperties);
/** Called after the region sequence's properties are updated.
@param regionSequence The region sequence whose properties were updated.
*/
virtual void didUpdateRegionSequenceProperties (ARARegionSequence* regionSequence);
/** Called before a playback region is removed from the region sequence.
@param regionSequence The region sequence that \p playbackRegion will be removed from.
@param playbackRegion The playback region that will be removed from \p regionSequence.
*/
virtual void willRemovePlaybackRegionFromRegionSequence (ARARegionSequence* regionSequence,
ARAPlaybackRegion* playbackRegion);
/** Called after a playback region is added to the region sequence.
@param regionSequence The region sequence that \p playbackRegion was added to.
@param playbackRegion The playback region that was added to \p regionSequence.
*/
virtual void didAddPlaybackRegionToRegionSequence (ARARegionSequence* regionSequence,
ARAPlaybackRegion* playbackRegion);
/** Called before the region sequence is destroyed.
@param regionSequence The region sequence that will be destroyed.
*/
virtual void willDestroyRegionSequence (ARARegionSequence* regionSequence);
};
//==============================================================================
/** Base class representing an ARA region sequence.
@tags{ARA}
*/
class JUCE_API ARARegionSequence : public ARA::PlugIn::RegionSequence,
public ARAListenableModelClass<ARARegionSequenceListener>,
public ARAObject
{
public:
using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties>;
using Listener = ARARegionSequenceListener;
using ARA::PlugIn::RegionSequence::RegionSequence;
/** Returns the result of ARA::PlugIn::RegionSequence::getDocument() with the pointer cast
to ARADocument*.
If you have overridden ARADocumentControllerSpecialisation::doCreateDocument(), then you
can use the template parameter to cast the pointers to your subclass of ARADocument.
*/
template <typename Document_t = ARADocument>
Document_t* getDocument() const noexcept
{
return ARA::PlugIn::RegionSequence::getDocument<Document_t>();
}
/** Returns the result of ARA::PlugIn::RegionSequence::getMusicalContext() with the pointer cast
to ARAMusicalContext*.
If you have overridden ARADocumentControllerSpecialisation::doCreateMusicalContext(), then you
can use the template parameter to cast the pointers to your subclass of ARAMusicalContext.
*/
template <typename MusicalContext_t = ARAMusicalContext>
MusicalContext_t* getMusicalContext() const noexcept
{
return ARA::PlugIn::RegionSequence::getMusicalContext<MusicalContext_t>();
}
/** Returns the result of ARA::PlugIn::RegionSequence::getPlaybackRegions() with the pointers within cast
to ARAPlaybackRegion*.
If you have overridden ARADocumentControllerSpecialisation::doCreatePlaybackRegion(), then you
can use the template parameter to cast the pointers to your subclass of ARAPlaybackRegion.
*/
template <typename PlaybackRegion_t = ARAPlaybackRegion>
const std::vector<PlaybackRegion_t*>& getPlaybackRegions() const noexcept
{
return ARA::PlugIn::RegionSequence::getPlaybackRegions<PlaybackRegion_t>();
}
size_t getNumChildren() const noexcept override;
ARAObject* getChild (size_t index) override;
ARAObject* getParent() override { return getDocument(); }
void visit (ARAObjectVisitor& visitor) override { visitor.visitRegionSequence (*this); }
/** Returns the playback time range covered by the regions in this sequence.
@param includeHeadAndTail Whether or not the range includes the playback region's head and tail time.
*/
Range<double> getTimeRange (ARAPlaybackRegion::IncludeHeadAndTail includeHeadAndTail = ARAPlaybackRegion::IncludeHeadAndTail::no) const;
/** If all audio sources used by the playback regions in this region sequence have the same
sample rate, this rate is returned here, otherwise 0.0 is returned.
If the region sequence has no playback regions, this also returns 0.0.
*/
double getCommonSampleRate() const;
};
/** A base class for listeners that want to know about changes to an ARAAudioSource object.
Use ARAAudioSource::addListener() to register your listener with an ARAAudioSource.
@tags{ARA}
*/
class JUCE_API ARAAudioSourceListener
{
public:
/** Destructor. */
virtual ~ARAAudioSourceListener() = default;
/** Called before the audio source's properties are updated.
@param audioSource The audio source whose properties will be updated.
@param newProperties The audio source properties that will be assigned to \p audioSource.
*/
virtual void willUpdateAudioSourceProperties (ARAAudioSource* audioSource,
ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties> newProperties);
/** Called after the audio source's properties are updated.
@param audioSource The audio source whose properties were updated.
*/
virtual void didUpdateAudioSourceProperties (ARAAudioSource* audioSource);
/** Called when the audio source's content (i.e. samples or notes) changes.
@param audioSource The audio source with updated content.
@param scopeFlags The scope of the content update.
*/
virtual void doUpdateAudioSourceContent (ARAAudioSource* audioSource, ARAContentUpdateScopes scopeFlags);
/** Called to notify progress when an audio source is being analyzed.
@param audioSource The audio source being analyzed.
@param state Indicates start, intermediate update or completion of the analysis.
@param progress Progress normalized to the 0..1 range.
*/
virtual void didUpdateAudioSourceAnalysisProgress (ARAAudioSource* audioSource,
ARA::ARAAnalysisProgressState state,
float progress);
/** Called before access to an audio source's samples is enabled or disabled.
@param audioSource The audio source whose sample access state will be changed.
@param enable A bool indicating whether or not sample access will be enabled or disabled.
*/
virtual void willEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource,
bool enable);
/** Called after access to an audio source's samples is enabled or disabled.
@param audioSource The audio source whose sample access state was changed.
@param enable A bool indicating whether or not sample access was enabled or disabled.
*/
virtual void didEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource,
bool enable);
/** Called before an audio source is activated or deactivated when being removed / added from the host's undo history.
@param audioSource The audio source that will be activated or deactivated
@param deactivate A bool indicating whether \p audioSource was deactivated or activated.
*/
virtual void willDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource,
bool deactivate);
/** Called after an audio source is activated or deactivated when being removed / added from the host's undo history.
@param audioSource The audio source that was activated or deactivated
@param deactivate A bool indicating whether \p audioSource was deactivated or activated.
*/
virtual void didDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource,
bool deactivate);
/** Called after an audio modification is added to the audio source.
@param audioSource The region sequence that \p audioModification was added to.
@param audioModification The playback region that was added to \p audioSource.
*/
virtual void didAddAudioModificationToAudioSource (ARAAudioSource* audioSource,
ARAAudioModification* audioModification);
/** Called before an audio modification is removed from the audio source.
@param audioSource The audio source that \p audioModification will be removed from.
@param audioModification The audio modification that will be removed from \p audioSource.
*/
virtual void willRemoveAudioModificationFromAudioSource (ARAAudioSource* audioSource,
ARAAudioModification* audioModification);
/** Called before the audio source is destroyed.
@param audioSource The audio source that will be destroyed.
*/
virtual void willDestroyAudioSource (ARAAudioSource* audioSource);
};
//==============================================================================
/** Base class representing an ARA audio source.
@tags{ARA}
*/
class JUCE_API ARAAudioSource : public ARA::PlugIn::AudioSource,
public ARAListenableModelClass<ARAAudioSourceListener>,
public ARAObject
{
public:
using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties>;
using ARAAnalysisProgressState = ARA::ARAAnalysisProgressState;
using Listener = ARAAudioSourceListener;
using ARA::PlugIn::AudioSource::AudioSource;
/** Returns the result of ARA::PlugIn::AudioSource::getDocument() with the pointer cast
to ARADocument*.
If you have overridden ARADocumentControllerSpecialisation::doCreateDocument(), then you
can use the template parameter to cast the pointers to your subclass of ARADocument.
*/
template <typename Document_t = ARADocument>
Document_t* getDocument() const noexcept
{
return ARA::PlugIn::AudioSource::getDocument<Document_t>();
}
/** Returns the result of ARA::PlugIn::AudioSource::getAudioModifications() with the pointers
within cast to ARAAudioModification*.
If you have overridden ARADocumentControllerSpecialisation::doCreateAudioModification(),
then you can use the template parameter to cast the pointers to your subclass of
ARAAudioModification.
*/
template <typename AudioModification_t = ARAAudioModification>
const std::vector<AudioModification_t*>& getAudioModifications() const noexcept
{
return ARA::PlugIn::AudioSource::getAudioModifications<AudioModification_t>();
}
size_t getNumChildren() const noexcept override;
ARAObject* getChild (size_t index) override;
ARAObject* getParent() override { return getDocument(); }
void visit (ARAObjectVisitor& visitor) override { visitor.visitAudioSource (*this); }
/** Notify the ARA host and any listeners of analysis progress.
Contrary to most ARA functions, this call can be made from any thread.
The implementation will enqueue these notifications and later post them from the message thread.
Calling code must ensure start and completion state are always balanced,
and must send updates in ascending order.
*/
void notifyAnalysisProgressStarted();
/** \copydoc notifyAnalysisProgressStarted
@param progress Progress normalized to the 0..1 range.
*/
void notifyAnalysisProgressUpdated (float progress);
/** \copydoc notifyAnalysisProgressStarted
*/
void notifyAnalysisProgressCompleted();
/** Notify the ARA host and any listeners of a content update initiated by the plug-in.
This must be called by the plug-in model management code on the message thread whenever updating
the internal content representation, such as after successfully analyzing a new tempo map.
Listeners will be notified immediately. If \p notifyARAHost is true, a notification to the host
will be enqueued and sent out the next time it polls for updates.
\p notifyARAHost must be false if the update was triggered by the host via doUpdateAudioSourceContent().
Furthermore, \p notifyARAHost must be false if the updated content is being restored from an archive.
@param scopeFlags The scope of the content update.
@param notifyARAHost If true, the ARA host will be notified of the content change.
*/
void notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost);
public:
friend ARADocumentController;
ARA::PlugIn::AnalysisProgressTracker internalAnalysisProgressTracker;
};
/** A base class for listeners that want to know about changes to an ARAAudioModification object.
Use ARAAudioModification::addListener() to register your listener with an ARAAudioModification.
@tags{ARA}
*/
class JUCE_API ARAAudioModificationListener
{
public:
/** Destructor. */
virtual ~ARAAudioModificationListener() = default;
/** Called before the audio modification's properties are updated.
@param audioModification The audio modification whose properties will be updated.
@param newProperties The audio modification properties that will be assigned to \p audioModification.
*/
virtual void willUpdateAudioModificationProperties (ARAAudioModification* audioModification,
ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties> newProperties);
/** Called after the audio modification's properties are updated.
@param audioModification The audio modification whose properties were updated.
*/
virtual void didUpdateAudioModificationProperties (ARAAudioModification* audioModification);
/** Called when the audio modification's content (i.e. samples or notes) changes.
@param audioModification The audio modification with updated content.
@param scopeFlags The scope of the content update.
*/
virtual void didUpdateAudioModificationContent (ARAAudioModification* audioModification,
ARAContentUpdateScopes scopeFlags);
/** Called before an audio modification is activated or deactivated when being removed / added from the host's undo history.
@param audioModification The audio modification that was activated or deactivated
@param deactivate A bool indicating whether \p audioModification was deactivated or activated.
*/
virtual void willDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification,
bool deactivate);
/** Called after an audio modification is activated or deactivated when being removed / added from the host's undo history.
@param audioModification The audio modification that was activated or deactivated
@param deactivate A bool indicating whether \p audioModification was deactivated or activated.
*/
virtual void didDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification,
bool deactivate);
/** Called after a playback region is added to the audio modification.
@param audioModification The audio modification that \p playbackRegion was added to.
@param playbackRegion The playback region that was added to \p audioModification.
*/
virtual void didAddPlaybackRegionToAudioModification (ARAAudioModification* audioModification,
ARAPlaybackRegion* playbackRegion);
/** Called before a playback region is removed from the audio modification.
@param audioModification The audio modification that \p playbackRegion will be removed from.
@param playbackRegion The playback region that will be removed from \p audioModification.
*/
virtual void willRemovePlaybackRegionFromAudioModification (ARAAudioModification* audioModification,
ARAPlaybackRegion* playbackRegion);
/** Called before the audio modification is destroyed.
@param audioModification The audio modification that will be destroyed.
*/
virtual void willDestroyAudioModification (ARAAudioModification* audioModification);
};
//==============================================================================
/** Base class representing an ARA audio modification.
@tags{ARA}
*/
class JUCE_API ARAAudioModification : public ARA::PlugIn::AudioModification,
public ARAListenableModelClass<ARAAudioModificationListener>,
public ARAObject
{
public:
using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties>;
using Listener = ARAAudioModificationListener;
using ARA::PlugIn::AudioModification::AudioModification;
/** Returns the result of ARA::PlugIn::AudioModification::getAudioSource() with the pointer cast
to ARAAudioSource*.
If you have overridden ARADocumentControllerSpecialisation::doCreateAudioSource(), then you
can use the template parameter to cast the pointers to your subclass of ARAAudioSource.
*/
template <typename AudioSource_t = ARAAudioSource>
AudioSource_t* getAudioSource() const noexcept
{
return ARA::PlugIn::AudioModification::getAudioSource<AudioSource_t>();
}
/** Returns the result of ARA::PlugIn::AudioModification::getPlaybackRegions() with the
pointers within cast to ARAPlaybackRegion*.
If you have overridden ARADocumentControllerSpecialisation::doCreatePlaybackRegion(), then
you can use the template parameter to cast the pointers to your subclass of ARAPlaybackRegion.
*/
template <typename PlaybackRegion_t = ARAPlaybackRegion>
const std::vector<PlaybackRegion_t*>& getPlaybackRegions() const noexcept
{
return ARA::PlugIn::AudioModification::getPlaybackRegions<PlaybackRegion_t>();
}
size_t getNumChildren() const noexcept override;
ARAObject* getChild (size_t index) override;
ARAObject* getParent() override { return getAudioSource(); }
void visit (ARAObjectVisitor& visitor) override { visitor.visitAudioModification (*this); }
/** Notify the ARA host and any listeners of a content update initiated by the plug-in.
This must be called by the plug-in model management code on the message thread whenever updating
the internal content representation, such as after the user editing the pitch of a note.
Listeners will be notified immediately. If \p notifyARAHost is true, a notification to the host
will be enqueued and sent out the next time it polls for updates.
\p notifyARAHost must be false if the updated content is being restored from an archive.
@param scopeFlags The scope of the content update.
@param notifyARAHost If true, the ARA host will be notified of the content change.
*/
void notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost);
};
} // namespace juce

View file

@ -1,123 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#include "juce_ARAPlugInInstanceRoles.h"
namespace juce
{
bool ARARenderer::processBlock ([[maybe_unused]] AudioBuffer<double>& buffer,
[[maybe_unused]] AudioProcessor::Realtime realtime,
[[maybe_unused]] const AudioPlayHead::PositionInfo& positionInfo) noexcept
{
// If you hit this assertion then either the caller called the double
// precision version of processBlock on a processor which does not support it
// (i.e. supportsDoublePrecisionProcessing() returns false), or the implementation
// of the ARARenderer forgot to override the double precision version of this method
jassertfalse;
return false;
}
void ARARenderer::prepareToPlay ([[maybe_unused]] double sampleRate,
[[maybe_unused]] int maximumSamplesPerBlock,
[[maybe_unused]] int numChannels,
[[maybe_unused]] AudioProcessor::ProcessingPrecision precision,
[[maybe_unused]] AlwaysNonRealtime alwaysNonRealtime) {}
//==============================================================================
#if ARA_VALIDATE_API_CALLS
void ARAPlaybackRenderer::addPlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept
{
if (araExtension)
ARA_VALIDATE_API_STATE (! araExtension->isPrepared);
ARA::PlugIn::PlaybackRenderer::addPlaybackRegion (playbackRegionRef);
}
void ARAPlaybackRenderer::removePlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept
{
if (araExtension)
ARA_VALIDATE_API_STATE (! araExtension->isPrepared);
ARA::PlugIn::PlaybackRenderer::removePlaybackRegion (playbackRegionRef);
}
#endif
bool ARAPlaybackRenderer::processBlock ([[maybe_unused]] AudioBuffer<float>& buffer,
[[maybe_unused]] AudioProcessor::Realtime realtime,
[[maybe_unused]] const AudioPlayHead::PositionInfo& positionInfo) noexcept
{
return false;
}
//==============================================================================
bool ARAEditorRenderer::processBlock ([[maybe_unused]] AudioBuffer<float>& buffer,
[[maybe_unused]] AudioProcessor::Realtime isNonRealtime,
[[maybe_unused]] const AudioPlayHead::PositionInfo& positionInfo) noexcept
{
return true;
}
//==============================================================================
void ARAEditorView::doNotifySelection (const ARA::PlugIn::ViewSelection* viewSelection) noexcept
{
listeners.call ([&] (Listener& l)
{
l.onNewSelection (*viewSelection);
});
}
void ARAEditorView::doNotifyHideRegionSequences (std::vector<ARA::PlugIn::RegionSequence*> const& regionSequences) noexcept
{
listeners.call ([&] (Listener& l)
{
l.onHideRegionSequences (ARA::vector_cast<ARARegionSequence*> (regionSequences));
});
}
void ARAEditorView::addListener (Listener* l)
{
listeners.add (l);
}
void ARAEditorView::removeListener (Listener* l)
{
listeners.remove (l);
}
void ARAEditorView::Listener::onNewSelection ([[maybe_unused]] const ARAViewSelection& viewSelection) {}
void ARAEditorView::Listener::onHideRegionSequences ([[maybe_unused]] const std::vector<ARARegionSequence*>& regionSequences) {}
} // namespace juce

View file

@ -1,263 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
namespace juce
{
//==============================================================================
/** Base class for a renderer fulfilling either the ARAPlaybackRenderer or the ARAEditorRenderer role.
Instances of either subclass are constructed by the DocumentController.
@tags{ARA}
*/
class JUCE_API ARARenderer
{
public:
enum class AlwaysNonRealtime { no, yes };
virtual ~ARARenderer() = default;
/** Initialises the renderer for playback.
@param sampleRate The sample rate that will be used for the data that is sent
to the renderer
@param maximumSamplesPerBlock The maximum number of samples that will be in the blocks
sent to process() method
@param numChannels The number of channels that the process() method will be
expected to handle
@param precision This should be the same as the result of getProcessingPrecision()
for the enclosing AudioProcessor
@param alwaysNonRealtime yes if this renderer is never used in realtime (e.g. if
providing data for views only)
*/
virtual void prepareToPlay (double sampleRate,
int maximumSamplesPerBlock,
int numChannels,
AudioProcessor::ProcessingPrecision precision,
AlwaysNonRealtime alwaysNonRealtime = AlwaysNonRealtime::no);
/** Frees render resources allocated in prepareToPlay(). */
virtual void releaseResources() {}
/** Resets the internal state variables of the renderer. */
virtual void reset() {}
/** Renders the output into the given buffer. Returns true if rendering executed without error,
false otherwise.
@param buffer The output buffer for the rendering. ARAPlaybackRenderers will
replace the sample data, while ARAEditorRenderer will add to it.
@param realtime Indicates whether the call is executed under real time constraints.
The value of this parameter may change from one call to the next,
and if the value is yes, the rendering may fail if the required
samples cannot be obtained in time.
@param positionInfo Current song position, playback state and playback loop location.
There should be no need to access the bpm, timeSig and ppqPosition
members in any ARA renderer since ARA provides that information with
random access in its model graph.
Returns false if non-ARA fallback rendering is required and true otherwise.
*/
virtual bool processBlock (AudioBuffer<float>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept = 0;
/** Renders the output into the given buffer. Returns true if rendering executed without error,
false otherwise.
@param buffer The output buffer for the rendering. ARAPlaybackRenderers will
replace the sample data, while ARAEditorRenderer will add to it.
@param realtime Indicates whether the call is executed under real time constraints.
The value of this parameter may change from one call to the next,
and if the value is yes, the rendering may fail if the required
samples cannot be obtained in time.
@param positionInfo Current song position, playback state and playback loop location.
There should be no need to access the bpm, timeSig and ppqPosition
members in any ARA renderer since ARA provides that information with
random access in its model graph.
Returns false if non-ARA fallback rendering is required and true otherwise.
*/
virtual bool processBlock (AudioBuffer<double>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept;
};
//==============================================================================
/** Base class for a renderer fulfilling the ARAPlaybackRenderer role as described in the ARA SDK.
Instances of this class are constructed by the DocumentController. If you are subclassing
ARAPlaybackRenderer, make sure to call the base class implementation of any overridden function,
except for processBlock.
@tags{ARA}
*/
class JUCE_API ARAPlaybackRenderer : public ARA::PlugIn::PlaybackRenderer,
public ARARenderer
{
public:
using ARA::PlugIn::PlaybackRenderer::PlaybackRenderer;
bool processBlock (AudioBuffer<float>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept override;
using ARARenderer::processBlock;
// Shadowing templated getters to default to JUCE versions of the returned classes
/** Returns the PlaybackRegions
*
* @tparam PlaybackRegion_t
* @return
*/
template <typename PlaybackRegion_t = ARAPlaybackRegion>
std::vector<PlaybackRegion_t*> const& getPlaybackRegions() const noexcept
{
return ARA::PlugIn::PlaybackRenderer::getPlaybackRegions<PlaybackRegion_t>();
}
#if ARA_VALIDATE_API_CALLS
void addPlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept override;
void removePlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept override;
AudioProcessorARAExtension* araExtension {};
#endif
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAPlaybackRenderer)
};
//==============================================================================
/** Base class for a renderer fulfilling the ARAEditorRenderer role as described in the ARA SDK.
Instances of this class are constructed by the DocumentController. If you are subclassing
ARAEditorRenderer, make sure to call the base class implementation of any overridden function,
except for processBlock.
@tags{ARA}
*/
class JUCE_API ARAEditorRenderer : public ARA::PlugIn::EditorRenderer,
public ARARenderer
{
public:
using ARA::PlugIn::EditorRenderer::EditorRenderer;
// Shadowing templated getters to default to JUCE versions of the returned classes
template <typename PlaybackRegion_t = ARAPlaybackRegion>
std::vector<PlaybackRegion_t*> const& getPlaybackRegions() const noexcept
{
return ARA::PlugIn::EditorRenderer::getPlaybackRegions<PlaybackRegion_t>();
}
template <typename RegionSequence_t = ARARegionSequence>
std::vector<RegionSequence_t*> const& getRegionSequences() const noexcept
{
return ARA::PlugIn::EditorRenderer::getRegionSequences<RegionSequence_t>();
}
// By default, editor renderers will just let the signal pass through unaltered.
// If you're overriding this to implement actual audio preview, remember to check
// isNonRealtime of the process context - typically preview is limited to realtime.
bool processBlock (AudioBuffer<float>& buffer,
AudioProcessor::Realtime isNonRealtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept override;
using ARARenderer::processBlock;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAEditorRenderer)
};
//==============================================================================
/** Base class for fulfilling the ARAEditorView role as described in the ARA SDK.
Instances of this class are constructed by the DocumentController. If you are subclassing
ARAEditorView, make sure to call the base class implementation of overridden functions.
@tags{ARA}
*/
class JUCE_API ARAEditorView : public ARA::PlugIn::EditorView
{
public:
using ARA::PlugIn::EditorView::EditorView;
// Shadowing templated getters to default to JUCE versions of the returned classes
template <typename RegionSequence_t = ARARegionSequence>
const std::vector<RegionSequence_t*>& getHiddenRegionSequences() const noexcept
{
return ARA::PlugIn::EditorView::getHiddenRegionSequences<RegionSequence_t>();
}
// Base class implementation must be called if overridden
void doNotifySelection (const ARA::PlugIn::ViewSelection* currentSelection) noexcept override;
// Base class implementation must be called if overridden
void doNotifyHideRegionSequences (const std::vector<ARA::PlugIn::RegionSequence*>& regionSequences) noexcept override;
/** A base class for listeners that want to know about changes to an ARAEditorView object.
Use ARAEditorView::addListener() to register your listener with an ARAEditorView.
*/
class JUCE_API Listener
{
public:
/** Destructor. */
virtual ~Listener() = default;
/** Called when the editor view's selection changes.
@param viewSelection The current selection state
*/
virtual void onNewSelection (const ARAViewSelection& viewSelection);
/** Called when region sequences are flagged as hidden in the host UI.
@param regionSequences A vector containing all hidden region sequences.
*/
virtual void onHideRegionSequences (const std::vector<ARARegionSequence*>& regionSequences);
};
/** \copydoc ARAListenableModelClass::addListener */
void addListener (Listener* l);
/** \copydoc ARAListenableModelClass::removeListener */
void removeListener (Listener* l);
private:
ListenerList<Listener> listeners;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAEditorView)
};
}

View file

@ -1,65 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#if (JucePlugin_Enable_ARA || (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU))) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)
namespace juce
{
#if ARA_ENABLE_INTERNAL_ASSERTS
JUCE_API void JUCE_CALLTYPE handleARAAssertion (const char* file, const int line, const char* diagnosis) noexcept
{
#if (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS)
DBG (diagnosis);
#endif
logAssertion (file, line);
#if (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS)
if (juce_isRunningUnderDebugger())
JUCE_BREAK_IN_DEBUGGER;
JUCE_ANALYZER_NORETURN
#endif
}
#endif
}
#endif
#if JucePlugin_Enable_ARA
#include "juce_ARADocumentControllerCommon.cpp"
#include "juce_ARADocumentController.cpp"
#include "juce_ARAModelObjects.cpp"
#include "juce_ARAPlugInInstanceRoles.cpp"
#include "juce_AudioProcessor_ARAExtensions.cpp"
ARA_SETUP_DEBUG_MESSAGE_PREFIX (JucePlugin_Name);
#endif

View file

@ -1,95 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#if JucePlugin_Enable_ARA
// Include ARA SDK headers
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments",
"-Wunused-parameter",
"-Wfloat-equal")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6387)
#include <ARA_Library/PlugIn/ARAPlug.h>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
JUCE_END_IGNORE_WARNINGS_MSVC
namespace juce
{
using ARAViewSelection = ARA::PlugIn::ViewSelection;
using ARAContentUpdateScopes = ARA::ContentUpdateScopes;
using ARARestoreObjectsFilter = ARA::PlugIn::RestoreObjectsFilter;
using ARAStoreObjectsFilter = ARA::PlugIn::StoreObjectsFilter;
/** Converts an ARA::ARAUtf8String to a JUCE String. */
inline String convertARAString (ARA::ARAUtf8String str)
{
return String (CharPointer_UTF8 (str));
}
/** Converts a potentially NULL ARA::ARAUtf8String to a JUCE String.
Returns the JUCE equivalent of the provided string if it's not nullptr, and the fallback string
otherwise.
*/
inline String convertOptionalARAString (ARA::ARAUtf8String str, const String& fallbackString = String())
{
return (str != nullptr) ? convertARAString (str) : fallbackString;
}
/** Converts an ARA::ARAColor* to a JUCE Colour. */
inline Colour convertARAColour (const ARA::ARAColor* colour)
{
return Colour::fromFloatRGBA (colour->r, colour->g, colour->b, 1.0f);
}
/** Converts a potentially NULL ARA::ARAColor* to a JUCE Colour.
Returns the JUCE equivalent of the provided colour if it's not nullptr, and the fallback colour
otherwise.
*/
inline Colour convertOptionalARAColour (const ARA::ARAColor* colour, const Colour& fallbackColour = Colour())
{
return (colour != nullptr) ? convertARAColour (colour) : fallbackColour;
}
} // namespace juce
#include "juce_ARAModelObjects.h"
#include "juce_ARADocumentController.h"
#include "juce_AudioProcessor_ARAExtensions.h"
#include "juce_ARAPlugInInstanceRoles.h"
#endif

View file

@ -1,163 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#include "juce_AudioProcessor_ARAExtensions.h"
namespace juce
{
//==============================================================================
bool AudioProcessorARAExtension::getTailLengthSecondsForARA (double& tailLength) const
{
if (! isBoundToARA())
return false;
tailLength = 0.0;
if (auto playbackRenderer = getPlaybackRenderer())
for (const auto& playbackRegion : playbackRenderer->getPlaybackRegions())
tailLength = jmax (tailLength, playbackRegion->getTailTime());
return true;
}
bool AudioProcessorARAExtension::prepareToPlayForARA (double sampleRate,
int samplesPerBlock,
int numChannels,
AudioProcessor::ProcessingPrecision precision)
{
#if ARA_VALIDATE_API_CALLS
isPrepared = true;
#endif
if (! isBoundToARA())
return false;
if (auto playbackRenderer = getPlaybackRenderer())
playbackRenderer->prepareToPlay (sampleRate, samplesPerBlock, numChannels, precision);
if (auto editorRenderer = getEditorRenderer())
editorRenderer->prepareToPlay (sampleRate, samplesPerBlock, numChannels, precision);
return true;
}
bool AudioProcessorARAExtension::releaseResourcesForARA()
{
#if ARA_VALIDATE_API_CALLS
isPrepared = false;
#endif
if (! isBoundToARA())
return false;
if (auto playbackRenderer = getPlaybackRenderer())
playbackRenderer->releaseResources();
if (auto editorRenderer = getEditorRenderer())
editorRenderer->releaseResources();
return true;
}
bool AudioProcessorARAExtension::processBlockForARA (AudioBuffer<float>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo)
{
// validate that the host has prepared us before processing
ARA_VALIDATE_API_STATE (isPrepared);
if (! isBoundToARA())
return false;
// Render our ARA playback regions for this buffer.
if (auto playbackRenderer = getPlaybackRenderer())
playbackRenderer->processBlock (buffer, realtime, positionInfo);
// Render our ARA editor regions and sequences for this buffer.
// This example does not support editor rendering and thus uses the default implementation,
// which is a no-op and could be omitted in actual plug-ins to optimize performance.
if (auto editorRenderer = getEditorRenderer())
editorRenderer->processBlock (buffer, realtime, positionInfo);
return true;
}
bool AudioProcessorARAExtension::processBlockForARA (AudioBuffer<float>& buffer,
juce::AudioProcessor::Realtime realtime,
AudioPlayHead* playhead)
{
return processBlockForARA (buffer,
realtime,
playhead != nullptr ? playhead->getPosition().orFallback (AudioPlayHead::PositionInfo{})
: AudioPlayHead::PositionInfo{});
}
//==============================================================================
void AudioProcessorARAExtension::didBindToARA() noexcept
{
// validate that the ARA binding is not established by the host while prepared to play
#if ARA_VALIDATE_API_CALLS
ARA_VALIDATE_API_STATE (! isPrepared);
if (auto playbackRenderer = getPlaybackRenderer())
playbackRenderer->araExtension = this;
#endif
#if JUCE_ASSERTIONS_ENABLED_OR_LOGGED
// validate proper subclassing of the instance role classes
if (auto playbackRenderer = getPlaybackRenderer())
jassert (dynamic_cast<ARAPlaybackRenderer*> (playbackRenderer) != nullptr);
if (auto editorRenderer = getEditorRenderer())
jassert (dynamic_cast<ARAEditorRenderer*> (editorRenderer) != nullptr);
if (auto editorView = getEditorView())
jassert (dynamic_cast<ARAEditorView*> (editorView) != nullptr);
#endif
}
//==============================================================================
AudioProcessorEditorARAExtension::AudioProcessorEditorARAExtension (AudioProcessor* audioProcessor)
: araProcessorExtension (dynamic_cast<AudioProcessorARAExtension*> (audioProcessor))
{
if (isARAEditorView())
getARAEditorView()->setEditorOpen (true);
}
AudioProcessorEditorARAExtension::~AudioProcessorEditorARAExtension()
{
if (isARAEditorView())
getARAEditorView()->setEditorOpen (false);
}
} // namespace juce

View file

@ -1,213 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
namespace juce
{
class AudioProcessor;
class ARAPlaybackRenderer;
class ARAEditorRenderer;
class ARAEditorView;
//==============================================================================
/** Extension class meant to be subclassed by the plugin's implementation of @see AudioProcessor.
Subclassing AudioProcessorARAExtension allows access to the three possible plugin instance
roles as defined by the ARA SDK. Hosts can assign any subset of roles to each plugin instance.
@tags{ARA}
*/
class JUCE_API AudioProcessorARAExtension : public ARA::PlugIn::PlugInExtension
{
public:
AudioProcessorARAExtension() = default;
//==============================================================================
/** Returns the result of ARA::PlugIn::PlugInExtension::getPlaybackRenderer() with the pointer
cast to ARAPlaybackRenderer*.
If you have overridden ARADocumentControllerSpecialisation::doCreatePlaybackRenderer(),
then you can use the template parameter to cast the pointers to your subclass of
ARAPlaybackRenderer.
*/
template <typename PlaybackRenderer_t = ARAPlaybackRenderer>
PlaybackRenderer_t* getPlaybackRenderer() const noexcept
{
return ARA::PlugIn::PlugInExtension::getPlaybackRenderer<PlaybackRenderer_t>();
}
/** Returns the result of ARA::PlugIn::PlugInExtension::getEditorRenderer() with the pointer
cast to ARAEditorRenderer*.
If you have overridden ARADocumentControllerSpecialisation::doCreateEditorRenderer(),
then you can use the template parameter to cast the pointers to your subclass of
ARAEditorRenderer.
*/
template <typename EditorRenderer_t = ARAEditorRenderer>
EditorRenderer_t* getEditorRenderer() const noexcept
{
return ARA::PlugIn::PlugInExtension::getEditorRenderer<EditorRenderer_t>();
}
/** Returns the result of ARA::PlugIn::PlugInExtension::getEditorView() with the pointer
cast to ARAEditorView*.
If you have overridden ARADocumentControllerSpecialisation::doCreateEditorView(),
then you can use the template parameter to cast the pointers to your subclass of
ARAEditorView.
*/
template <typename EditorView_t = ARAEditorView>
EditorView_t* getEditorView() const noexcept
{
return ARA::PlugIn::PlugInExtension::getEditorView<EditorView_t>();
}
//==============================================================================
/** Returns true if plugin instance fulfills the ARAPlaybackRenderer role. */
bool isPlaybackRenderer() const noexcept
{
return ARA::PlugIn::PlugInExtension::getPlaybackRenderer() != nullptr;
}
/** Returns true if plugin instance fulfills the ARAEditorRenderer role. */
bool isEditorRenderer() const noexcept
{
return ARA::PlugIn::PlugInExtension::getEditorRenderer() != nullptr;
}
/** Returns true if plugin instance fulfills the ARAEditorView role. */
bool isEditorView() const noexcept
{
return ARA::PlugIn::PlugInExtension::getEditorView() != nullptr;
}
//==============================================================================
#if ARA_VALIDATE_API_CALLS
bool isPrepared { false };
#endif
protected:
/** Implementation helper for AudioProcessor::getTailLengthSeconds().
If bound to ARA, this traverses the instance roles to retrieve the respective tail time
and returns true. Otherwise returns false and leaves tailLength unmodified.
*/
bool getTailLengthSecondsForARA (double& tailLength) const;
/** Implementation helper for AudioProcessor::prepareToPlay().
If bound to ARA, this traverses the instance roles to prepare them for play and returns
true. Otherwise returns false and does nothing.
*/
bool prepareToPlayForARA (double sampleRate,
int samplesPerBlock,
int numChannels,
AudioProcessor::ProcessingPrecision precision);
/** Implementation helper for AudioProcessor::releaseResources().
If bound to ARA, this traverses the instance roles to let them release resources and returns
true. Otherwise returns false and does nothing.
*/
bool releaseResourcesForARA();
/** Implementation helper for AudioProcessor::processBlock().
If bound to ARA, this traverses the instance roles to let them process the block and returns
true. Otherwise returns false and does nothing.
Use this overload if your rendering code already has a current positionInfo available.
*/
bool processBlockForARA (AudioBuffer<float>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo);
/** Implementation helper for AudioProcessor::processBlock().
If bound to ARA, this traverses the instance roles to let them process the block and returns
true. Otherwise returns false and does nothing.
Use this overload if your rendering code does not have a current positionInfo available.
*/
bool processBlockForARA (AudioBuffer<float>& buffer, AudioProcessor::Realtime isNonRealtime, AudioPlayHead* playhead);
//==============================================================================
/** Optional hook for derived classes to perform any additional initialization that may be needed.
If overriding this, make sure you call the base class implementation from your override.
*/
void didBindToARA() noexcept override;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorARAExtension)
};
//==============================================================================
/** Extension class meant to be subclassed by the plugin's implementation of @see AudioProcessorEditor.
Subclassing AudioProcessorARAExtension allows access to the ARAEditorView instance role as
described by the ARA SDK.
@tags{ARA}
*/
class JUCE_API AudioProcessorEditorARAExtension
{
public:
/** Constructor. */
explicit AudioProcessorEditorARAExtension (AudioProcessor* audioProcessor);
/** \copydoc AudioProcessorARAExtension::getEditorView */
template <typename EditorView_t = ARAEditorView>
EditorView_t* getARAEditorView() const noexcept
{
return (this->araProcessorExtension != nullptr) ? this->araProcessorExtension->getEditorView<EditorView_t>()
: nullptr;
}
/** \copydoc AudioProcessorARAExtension::isEditorView */
bool isARAEditorView() const noexcept { return getARAEditorView() != nullptr; }
protected:
/** Destructor. */
~AudioProcessorEditorARAExtension();
private:
AudioProcessorARAExtension* araProcessorExtension;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorEditorARAExtension)
};
} // namespace juce

View file

@ -1,308 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
class AAXPluginId
{
public:
static std::optional<AAXPluginId> create (std::array<char, 4> letters)
{
std::array<size_t, 4> indices{};
for (size_t i = 0; i < letters.size(); ++i)
{
if (const auto index = findIndexOfChar (letters[i]))
indices[i] = *index;
else
return std::nullopt;
}
return AAXPluginId { std::move (indices) };
}
std::optional<AAXPluginId> withIncrementedLetter (size_t index, size_t increment) const
{
if (indices.size() <= index)
return std::nullopt;
auto copy = *this;
copy.indices[index] += increment;
if ((size_t) std::size (validChars) <= copy.indices[index])
return std::nullopt;
return copy;
}
int32 getPluginId() const
{
int32 result = 0;
for (size_t i = 0; i < indices.size(); ++i)
result |= static_cast<int32> (validChars[indices[i]]) << (8 * (indices.size() - 1 - i));
return result;
}
static std::optional<size_t> findIndexOfChar (char c)
{
const auto ptr = std::find (std::begin (validChars), std::end (validChars), c);
return ptr != std::end (validChars) ? std::make_optional (std::distance (std::begin (validChars), ptr))
: std::nullopt;
}
private:
static inline constexpr char validChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
explicit AAXPluginId (std::array<size_t, 4> indicesIn)
: indices (std::move (indicesIn))
{}
std::array<size_t, 4> indices;
};
static const AudioChannelSet channelSets[] { AudioChannelSet::disabled(),
AudioChannelSet::mono(),
AudioChannelSet::stereo(),
AudioChannelSet::createLCR(),
AudioChannelSet::createLCRS(),
AudioChannelSet::quadraphonic(),
AudioChannelSet::create5point0(),
AudioChannelSet::create5point1(),
AudioChannelSet::create6point0(),
AudioChannelSet::create6point1(),
AudioChannelSet::create7point0(),
AudioChannelSet::create7point1(),
AudioChannelSet::create7point0SDDS(),
AudioChannelSet::create7point1SDDS(),
AudioChannelSet::create7point0point2(),
AudioChannelSet::create7point1point2(),
AudioChannelSet::ambisonic (1),
AudioChannelSet::ambisonic (2),
AudioChannelSet::ambisonic (3),
AudioChannelSet::create5point0point2(),
AudioChannelSet::create5point1point2(),
AudioChannelSet::create5point0point4(),
AudioChannelSet::create5point1point4(),
AudioChannelSet::create7point0point4(),
AudioChannelSet::create7point1point4(),
AudioChannelSet::create7point0point6(),
AudioChannelSet::create7point1point6(),
AudioChannelSet::create9point0point4(),
AudioChannelSet::create9point1point4(),
AudioChannelSet::create9point0point6(),
AudioChannelSet::create9point1point6(),
AudioChannelSet::ambisonic (4),
AudioChannelSet::ambisonic (5),
AudioChannelSet::ambisonic (6),
AudioChannelSet::ambisonic (7) };
int32 AAXClientExtensions::getPluginIDForMainBusConfig (const AudioChannelSet& mainInputLayout,
const AudioChannelSet& mainOutputLayout,
bool idForAudioSuite) const
{
auto pluginId = [&]
{
auto opt = idForAudioSuite ? AAXPluginId::create ({ 'j', 'y', 'a', 'a' })
: AAXPluginId::create ({ 'j', 'c', 'a', 'a' });
jassert (opt.has_value());
return *opt;
}();
for (const auto& [channelSet, indexToModify] : { std::tuple (&mainInputLayout, (size_t) 2),
std::tuple (&mainOutputLayout, (size_t) 3) })
{
const auto increment = (size_t) std::distance (std::begin (channelSets),
std::find (std::begin (channelSets),
std::end (channelSets),
*channelSet));
if (auto modifiedPluginIdOpt = pluginId.withIncrementedLetter (indexToModify, increment);
increment < (size_t) std::size (channelSets) && modifiedPluginIdOpt.has_value())
{
pluginId = *modifiedPluginIdOpt;
}
else
{
jassertfalse;
}
}
return pluginId.getPluginId();
}
String AAXClientExtensions::getPageFileName() const
{
#ifdef JucePlugin_AAXPageTableFile
JUCE_COMPILER_WARNING ("JucePlugin_AAXPageTableFile is deprecated, instead implement AAXClientExtensions::getPageFileName()")
return JucePlugin_AAXPageTableFile;
#else
return {};
#endif
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
static std::array<char, 4> toCharArray (int32 identifier)
{
std::array<char, 4> result;
for (size_t i = 0; i < result.size(); ++i)
result[i] = static_cast<char> ((identifier >> (i * 8)) & 0xff);
return result;
}
static bool isValidAAXPluginId (int32 pluginId)
{
const auto chars = toCharArray (pluginId);
return std::all_of (std::begin (chars),
std::end (chars),
[] (const auto& c)
{
return AAXPluginId::findIndexOfChar (c).has_value();
});
}
static int32 getPluginIDForMainBusConfigJuce705 (const AudioChannelSet& mainInputLayout,
const AudioChannelSet& mainOutputLayout,
bool idForAudioSuite)
{
int uniqueFormatId = 0;
for (int dir = 0; dir < 2; ++dir)
{
const bool isInput = (dir == 0);
auto& set = (isInput ? mainInputLayout : mainOutputLayout);
int aaxFormatIndex = 0;
const AudioChannelSet sets[]
{
AudioChannelSet::disabled(),
AudioChannelSet::mono(),
AudioChannelSet::stereo(),
AudioChannelSet::createLCR(),
AudioChannelSet::createLCRS(),
AudioChannelSet::quadraphonic(),
AudioChannelSet::create5point0(),
AudioChannelSet::create5point1(),
AudioChannelSet::create6point0(),
AudioChannelSet::create6point1(),
AudioChannelSet::create7point0(),
AudioChannelSet::create7point1(),
AudioChannelSet::create7point0SDDS(),
AudioChannelSet::create7point1SDDS(),
AudioChannelSet::create7point0point2(),
AudioChannelSet::create7point1point2(),
AudioChannelSet::ambisonic (1),
AudioChannelSet::ambisonic (2),
AudioChannelSet::ambisonic (3),
AudioChannelSet::create5point0point2(),
AudioChannelSet::create5point1point2(),
AudioChannelSet::create5point0point4(),
AudioChannelSet::create5point1point4(),
AudioChannelSet::create7point0point4(),
AudioChannelSet::create7point1point4(),
AudioChannelSet::create7point0point6(),
AudioChannelSet::create7point1point6(),
AudioChannelSet::create9point0point4(),
AudioChannelSet::create9point1point4(),
AudioChannelSet::create9point0point6(),
AudioChannelSet::create9point1point6(),
AudioChannelSet::ambisonic (4),
AudioChannelSet::ambisonic (5),
AudioChannelSet::ambisonic (6),
AudioChannelSet::ambisonic (7)
};
const auto index = (int) std::distance (std::begin (sets), std::find (std::begin (sets), std::end (sets), set));
if (index != (int) std::size (sets))
aaxFormatIndex = index;
else
jassertfalse;
uniqueFormatId = (uniqueFormatId << 8) | aaxFormatIndex;
}
return (idForAudioSuite ? 0x6a796161 /* 'jyaa' */ : 0x6a636161 /* 'jcaa' */) + uniqueFormatId;
}
class AAXClientExtensionsTests final : public UnitTest
{
public:
AAXClientExtensionsTests()
: UnitTest ("AAXClientExtensionsTests", UnitTestCategories::audioProcessors)
{}
void runTest() override
{
AAXClientExtensions extensions;
beginTest ("Previously valid PluginIds should be unchanged");
{
for (const auto& input : channelSets)
for (const auto& output : channelSets)
for (const auto idForAudioSuite : { false, true })
if (const auto oldId = getPluginIDForMainBusConfigJuce705 (input, output, idForAudioSuite); isValidAAXPluginId (oldId))
expect (extensions.getPluginIDForMainBusConfig (input, output, idForAudioSuite) == oldId);
}
beginTest ("Valid, unique PluginIds should be generated for all configurations");
{
std::set<int32> pluginIds;
for (const auto& input : channelSets)
for (const auto& output : channelSets)
for (const auto idForAudioSuite : { false, true })
pluginIds.insert (extensions.getPluginIDForMainBusConfig (input, output, idForAudioSuite));
for (auto identifier : pluginIds)
expect (isValidAAXPluginId (identifier));
expect (pluginIds.size() == square (std::size (channelSets)) * 2);
}
}
};
static AAXClientExtensionsTests aaxClientExtensionsTests;
#endif
} // namespace juce

View file

@ -1,92 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
An interface to allow an AudioProcessor to implement extended AAX-specific functionality.
To use this class, create an object that inherits from it, implement the methods, then return
a pointer to the object in your AudioProcessor `getAAXClientExtensions()` method.
@see AudioProcessor, VST2ClientExtensions, VST3ClientExtensions
@tags{Audio}
*/
struct JUCE_API AAXClientExtensions
{
virtual ~AAXClientExtensions() = default;
/** AAX plug-ins need to report a unique "plug-in id" for every audio layout
configuration that your AudioProcessor supports on the main bus. Override this
function if you want your AudioProcessor to use a custom "plug-in id" (for example
to stay backward compatible with older versions of JUCE).
The default implementation will compute a unique integer from the input and output
layout and add this value to the 4 character code 'jcaa' (for native AAX) or 'jyaa'
(for AudioSuite plug-ins).
*/
virtual int32 getPluginIDForMainBusConfig (const AudioChannelSet& mainInputLayout,
const AudioChannelSet& mainOutputLayout,
bool idForAudioSuite) const;
/** Returns an optional filename (including extension) for a page file to be used.
A page file allows an AAX plugin to specify how its parameters are displayed on
various control surfaces. For more information read the Page Table Guide in the
AAX SDK documentation.
By default this file will be searched for in `*.aaxplugin/Contents/Resources`.
@see getPageFileSearchPath
*/
virtual String getPageFileName() const;
/** Optionally returns a search path for finding a page table file.
This can be useful for specifying a location outside the plugin bundle so users can
make changes to a page table file without breaking any code signatures.
If this function returns a default-constructed File, then a default location will be used.
The AAX SDK states this location will be `*.aaxplugin/Contents/Resources`.
@note The returned path should be an absolute path to a directory.
@see getPageFileName
*/
virtual File getPageFileSearchPath() const { return {}; }
};
} // namespace juce

View file

@ -1,104 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioParameterBool::AudioParameterBool (const ParameterID& idToUse,
const String& nameToUse,
bool def,
const AudioParameterBoolAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
value (def ? 1.0f : 0.0f),
valueDefault (def),
stringFromBoolFunction (attributes.getStringFromValueFunction() != nullptr
? attributes.getStringFromValueFunction()
: [] (bool v, int) { return v ? TRANS ("On") : TRANS ("Off"); }),
boolFromStringFunction (attributes.getValueFromStringFunction() != nullptr
? attributes.getValueFromStringFunction()
: [] (const String& text)
{
static const StringArray onStrings { TRANS ("on"), TRANS ("yes"), TRANS ("true") };
static const StringArray offStrings { TRANS ("off"), TRANS ("no"), TRANS ("false") };
String lowercaseText (text.toLowerCase());
for (auto& testText : onStrings)
if (lowercaseText == testText)
return true;
for (auto& testText : offStrings)
if (lowercaseText == testText)
return false;
return text.getIntValue() != 0;
})
{
}
AudioParameterBool::~AudioParameterBool()
{
#if __cpp_lib_atomic_is_always_lock_free
static_assert (std::atomic<float>::is_always_lock_free,
"AudioParameterBool requires a lock-free std::atomic<float>");
#endif
}
float AudioParameterBool::getValue() const { return value; }
void AudioParameterBool::setValue (float newValue) { value = newValue; valueChanged (get()); }
float AudioParameterBool::getDefaultValue() const { return valueDefault; }
int AudioParameterBool::getNumSteps() const { return 2; }
bool AudioParameterBool::isDiscrete() const { return true; }
bool AudioParameterBool::isBoolean() const { return true; }
void AudioParameterBool::valueChanged (bool) {}
float AudioParameterBool::getValueForText (const String& text) const
{
return boolFromStringFunction (text) ? 1.0f : 0.0f;
}
String AudioParameterBool::getText (float v, int maximumLength) const
{
return stringFromBoolFunction (v >= 0.5f, maximumLength);
}
AudioParameterBool& AudioParameterBool::operator= (bool newValue)
{
if (get() != newValue)
setValueNotifyingHost (newValue ? 1.0f : 0.0f);
return *this;
}
} // namespace juce

View file

@ -1,149 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/** Properties of an AudioParameterBool.
@see AudioParameterBool(), RangedAudioParameterAttributes()
@tags{Audio}
*/
class AudioParameterBoolAttributes : public RangedAudioParameterAttributes<AudioParameterBoolAttributes, bool> {};
//==============================================================================
/**
Provides a class of AudioProcessorParameter that can be used as a boolean value.
@see AudioParameterFloat, AudioParameterInt, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioParameterBool : public RangedAudioParameter
{
public:
/** Creates a AudioParameterBool with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterBoolAttributes().withStringFromValueFunction ([] (auto x, auto) { return x ? "On" : "Off"; })
.withLabel ("enabled");
auto param = std::make_unique<AudioParameterBool> ("paramID", "Parameter Name", false, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param defaultValue The default value
@param attributes Optional characteristics
*/
AudioParameterBool (const ParameterID& parameterID,
const String& parameterName,
bool defaultValue,
const AudioParameterBoolAttributes& attributes = {});
/** Creates a AudioParameterBool with the specified parameters.
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param defaultValue The default value
@param parameterLabel An optional label for the parameter's value
@param stringFromBool An optional lambda function that converts a bool
value to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param boolFromString An optional lambda function that parses a string and
converts it into a bool value. Some hosts use this
to allow users to type in parameter values.
*/
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterBool (const ParameterID& parameterID,
const String& parameterName,
bool defaultValue,
const String& parameterLabel,
std::function<String (bool value, int maximumStringLength)> stringFromBool = nullptr,
std::function<bool (const String& text)> boolFromString = nullptr)
: AudioParameterBool (parameterID,
parameterName,
defaultValue,
AudioParameterBoolAttributes().withLabel (parameterLabel)
.withStringFromValueFunction (std::move (stringFromBool))
.withValueFromStringFunction (std::move (boolFromString)))
{
}
/** Destructor. */
~AudioParameterBool() override;
/** Returns the parameter's current boolean value. */
bool get() const noexcept { return value >= 0.5f; }
/** Returns the parameter's current boolean value. */
operator bool() const noexcept { return get(); }
/** Changes the parameter's current value to a new boolean. */
AudioParameterBool& operator= (bool newValue);
/** Returns the range of values that the parameter can take. */
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (bool newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
bool isDiscrete() const override;
bool isBoolean() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
const NormalisableRange<float> range { 0.0f, 1.0f, 1.0f };
std::atomic<float> value;
const float valueDefault;
std::function<String (bool, int)> stringFromBoolFunction;
std::function<bool (const String&)> boolFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterBool)
};
} // namespace juce

View file

@ -1,145 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioParameterChoice::AudioParameterChoice (const ParameterID& idToUse,
const String& nameToUse,
const StringArray& c,
int def,
const AudioParameterChoiceAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
choices (c),
range ([this]
{
NormalisableRange<float> rangeWithInterval { 0.0f, (float) choices.size() - 1.0f,
[] (float, float end, float v) { return jlimit (0.0f, end, v * end); },
[] (float, float end, float v) { return jlimit (0.0f, 1.0f, v / end); },
[] (float start, float end, float v) { return (float) roundToInt (juce::jlimit (start, end, v)); } };
rangeWithInterval.interval = 1.0f;
return rangeWithInterval;
}()),
value ((float) def),
defaultValue (convertTo0to1 ((float) def)),
stringFromIndexFunction (attributes.getStringFromValueFunction() != nullptr
? attributes.getStringFromValueFunction()
: [this] (int index, int) { return choices [index]; }),
indexFromStringFunction (attributes.getValueFromStringFunction() != nullptr
? attributes.getValueFromStringFunction()
: [this] (const String& text) { return choices.indexOf (text); })
{
jassert (choices.size() > 1); // you must supply an actual set of items to choose from!
}
AudioParameterChoice::~AudioParameterChoice()
{
#if __cpp_lib_atomic_is_always_lock_free
static_assert (std::atomic<float>::is_always_lock_free,
"AudioParameterChoice requires a lock-free std::atomic<float>");
#endif
}
float AudioParameterChoice::getValue() const { return convertTo0to1 (value); }
void AudioParameterChoice::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (getIndex()); }
float AudioParameterChoice::getDefaultValue() const { return defaultValue; }
int AudioParameterChoice::getNumSteps() const { return choices.size(); }
bool AudioParameterChoice::isDiscrete() const { return true; }
float AudioParameterChoice::getValueForText (const String& text) const { return convertTo0to1 ((float) indexFromStringFunction (text)); }
String AudioParameterChoice::getText (float v, int length) const { return stringFromIndexFunction ((int) convertFrom0to1 (v), length); }
void AudioParameterChoice::valueChanged (int) {}
AudioParameterChoice& AudioParameterChoice::operator= (int newValue)
{
if (getIndex() != newValue)
setValueNotifyingHost (convertTo0to1 ((float) newValue));
return *this;
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
struct AudioParameterChoiceTests final : public UnitTest
{
AudioParameterChoiceTests()
: UnitTest ("AudioParameterChoice", UnitTestCategories::audioProcessorParameters)
{}
void runTest() override
{
beginTest ("Three options switches at the correct points");
{
AudioParameterChoice choice ({}, {}, { "a", "b", "c" }, {});
choice.setValueNotifyingHost (0.0f);
expectEquals (choice.getIndex(), 0);
choice.setValueNotifyingHost (0.2f);
expectEquals (choice.getIndex(), 0);
choice.setValueNotifyingHost (0.3f);
expectEquals (choice.getIndex(), 1);
choice.setValueNotifyingHost (0.7f);
expectEquals (choice.getIndex(), 1);
choice.setValueNotifyingHost (0.8f);
expectEquals (choice.getIndex(), 2);
choice.setValueNotifyingHost (1.0f);
expectEquals (choice.getIndex(), 2);
}
beginTest ("Out-of-bounds input");
{
AudioParameterChoice choiceParam ({}, {}, { "a", "b", "c" }, {});
choiceParam.setValueNotifyingHost (-0.5f);
expectEquals (choiceParam.getIndex(), 0);
choiceParam.setValueNotifyingHost (1.5f);
expectEquals (choiceParam.getIndex(), 2);
}
}
};
static AudioParameterChoiceTests audioParameterChoiceTests;
#endif
} // namespace juce

View file

@ -1,162 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/** Properties of an AudioParameterChoice.
@see AudioParameterChoice(), RangedAudioParameterAttributes()
@tags{Audio}
*/
class AudioParameterChoiceAttributes : public RangedAudioParameterAttributes<AudioParameterChoiceAttributes, int> {};
//==============================================================================
/**
Provides a class of AudioProcessorParameter that can be used to select
an indexed, named choice from a list.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool
@tags{Audio}
*/
class JUCE_API AudioParameterChoice : public RangedAudioParameter
{
public:
/** Creates a AudioParameterChoice with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterChoiceAttributes().withLabel ("selected");
auto param = std::make_unique<AudioParameterChoice> ("paramID", "Parameter Name", StringArray { "a", "b", "c" }, 0, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param choices The set of choices to use
@param defaultItemIndex The index of the default choice
@param attributes Optional characteristics
*/
AudioParameterChoice (const ParameterID& parameterID,
const String& parameterName,
const StringArray& choices,
int defaultItemIndex,
const AudioParameterChoiceAttributes& attributes = {});
/** Creates a AudioParameterChoice with the specified parameters.
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param choicesToUse The set of choices to use
@param defaultItemIndex The index of the default choice
@param parameterLabel An optional label for the parameter's value
@param stringFromIndex An optional lambda function that converts a choice
index to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param indexFromString An optional lambda function that parses a string and
converts it into a choice index. Some hosts use this
to allow users to type in parameter values.
*/
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterChoice (const ParameterID& parameterID,
const String& parameterName,
const StringArray& choicesToUse,
int defaultItemIndex,
const String& parameterLabel,
std::function<String (int index, int maximumStringLength)> stringFromIndex = nullptr,
std::function<int (const String& text)> indexFromString = nullptr)
: AudioParameterChoice (parameterID,
parameterName,
choicesToUse,
defaultItemIndex,
AudioParameterChoiceAttributes().withLabel (parameterLabel)
.withStringFromValueFunction (std::move (stringFromIndex))
.withValueFromStringFunction (std::move (indexFromString)))
{
}
/** Destructor. */
~AudioParameterChoice() override;
/** Returns the current index of the selected item. */
int getIndex() const noexcept { return roundToInt (value.load()); }
/** Returns the current index of the selected item. */
operator int() const noexcept { return getIndex(); }
/** Returns the name of the currently selected item. */
String getCurrentChoiceName() const noexcept { return choices[getIndex()]; }
/** Returns the name of the currently selected item. */
operator String() const noexcept { return getCurrentChoiceName(); }
/** Changes the selected item to a new index. */
AudioParameterChoice& operator= (int newValue);
/** Returns the range of values that the parameter can take. */
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
/** Provides access to the list of choices that this parameter is working with. */
const StringArray choices;
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (int newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
bool isDiscrete() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
const NormalisableRange<float> range;
std::atomic<float> value;
const float defaultValue;
std::function<String (int, int)> stringFromIndexFunction;
std::function<int (const String&)> indexFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterChoice)
};
} // namespace juce

View file

@ -1,113 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioParameterFloat::AudioParameterFloat (const ParameterID& idToUse,
const String& nameToUse,
NormalisableRange<float> r,
float def,
const AudioParameterFloatAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
range (r),
value (def),
valueDefault (def),
stringFromValueFunction (attributes.getStringFromValueFunction()),
valueFromStringFunction (attributes.getValueFromStringFunction())
{
if (stringFromValueFunction == nullptr)
{
auto numDecimalPlacesToDisplay = [this]
{
int numDecimalPlaces = 7;
if (! approximatelyEqual (range.interval, 0.0f))
{
if (approximatelyEqual (std::abs (range.interval - std::floor (range.interval)), 0.0f))
return 0;
auto v = std::abs (roundToInt (range.interval * pow (10, numDecimalPlaces)));
while ((v % 10) == 0 && numDecimalPlaces > 0)
{
--numDecimalPlaces;
v /= 10;
}
}
return numDecimalPlaces;
}();
stringFromValueFunction = [numDecimalPlacesToDisplay] (float v, int length)
{
String asText (v, numDecimalPlacesToDisplay);
return length > 0 ? asText.substring (0, length) : asText;
};
}
if (valueFromStringFunction == nullptr)
valueFromStringFunction = [] (const String& text) { return text.getFloatValue(); };
}
AudioParameterFloat::AudioParameterFloat (const ParameterID& pid, const String& nm, float minValue, float maxValue, float def)
: AudioParameterFloat (pid, nm, { minValue, maxValue, 0.01f }, def)
{
}
AudioParameterFloat::~AudioParameterFloat()
{
#if __cpp_lib_atomic_is_always_lock_free
static_assert (std::atomic<float>::is_always_lock_free,
"AudioParameterFloat requires a lock-free std::atomic<float>");
#endif
}
float AudioParameterFloat::getValue() const { return convertTo0to1 (value); }
void AudioParameterFloat::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (get()); }
float AudioParameterFloat::getDefaultValue() const { return convertTo0to1 (valueDefault); }
int AudioParameterFloat::getNumSteps() const { return AudioProcessorParameterWithID::getNumSteps(); }
String AudioParameterFloat::getText (float v, int length) const { return stringFromValueFunction (convertFrom0to1 (v), length); }
float AudioParameterFloat::getValueForText (const String& text) const { return convertTo0to1 (valueFromStringFunction (text)); }
void AudioParameterFloat::valueChanged (float) {}
AudioParameterFloat& AudioParameterFloat::operator= (float newValue)
{
if (! approximatelyEqual ((float) value, newValue))
setValueNotifyingHost (convertTo0to1 (newValue));
return *this;
}
} // namespace juce

View file

@ -1,169 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/** Properties of an AudioParameterFloat.
@see AudioParameterFloat(), RangedAudioParameterAttributes()
@tags{Audio}
*/
class AudioParameterFloatAttributes : public RangedAudioParameterAttributes<AudioParameterFloatAttributes, float> {};
//==============================================================================
/**
A subclass of AudioProcessorParameter that provides an easy way to create a
parameter which maps onto a given NormalisableRange.
@see AudioParameterInt, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioParameterFloat : public RangedAudioParameter
{
public:
/** Creates a AudioParameterFloat with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterFloatAttributes().withStringFromValueFunction ([] (auto x, auto) { return String (x * 100); })
.withLabel ("%");
auto param = std::make_unique<AudioParameterFloat> ("paramID", "Parameter Name", NormalisableRange<float>(), 0.5f, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param normalisableRange The NormalisableRange to use
@param defaultValue The non-normalised default value
@param attributes Optional characteristics
*/
AudioParameterFloat (const ParameterID& parameterID,
const String& parameterName,
NormalisableRange<float> normalisableRange,
float defaultValue,
const AudioParameterFloatAttributes& attributes = {});
/** Creates a AudioParameterFloat with the specified parameters.
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param normalisableRange The NormalisableRange to use
@param defaultValue The non-normalised default value
@param parameterLabel An optional label for the parameter's value
@param parameterCategory An optional parameter category
@param stringFromValue An optional lambda function that converts a non-normalised
value to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param valueFromString An optional lambda function that parses a string and
converts it into a non-normalised value. Some hosts use
this to allow users to type in parameter values.
*/
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterFloat (const ParameterID& parameterID,
const String& parameterName,
NormalisableRange<float> normalisableRange,
float defaultValue,
const String& parameterLabel,
Category parameterCategory = AudioProcessorParameter::genericParameter,
std::function<String (float value, int maximumStringLength)> stringFromValue = nullptr,
std::function<float (const String& text)> valueFromString = nullptr)
: AudioParameterFloat (parameterID,
parameterName,
std::move (normalisableRange),
defaultValue,
AudioParameterFloatAttributes().withLabel (parameterLabel)
.withCategory (parameterCategory)
.withStringFromValueFunction (std::move (stringFromValue))
.withValueFromStringFunction (std::move (valueFromString)))
{
}
/** Creates a AudioParameterFloat with an ID, name, and range.
On creation, its value is set to the default value.
For control over skew factors, you can use the other
constructor and provide a NormalisableRange.
*/
AudioParameterFloat (const ParameterID& parameterID,
const String& parameterName,
float minValue,
float maxValue,
float defaultValue);
/** Destructor. */
~AudioParameterFloat() override;
/** Returns the parameter's current value. */
float get() const noexcept { return value; }
/** Returns the parameter's current value. */
operator float() const noexcept { return value; }
/** Changes the parameter's current value. */
AudioParameterFloat& operator= (float newValue);
/** Returns the range of values that the parameter can take. */
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
/** Provides access to the parameter's range. */
NormalisableRange<float> range;
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (float newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
std::atomic<float> value;
const float valueDefault;
std::function<String (float, int)> stringFromValueFunction;
std::function<float (const String&)> valueFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterFloat)
};
} // namespace juce

View file

@ -1,146 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioParameterInt::AudioParameterInt (const ParameterID& idToUse, const String& nameToUse,
int minValue, int maxValue, int def,
const AudioParameterIntAttributes& attributes)
: RangedAudioParameter (idToUse, nameToUse, attributes.getAudioProcessorParameterWithIDAttributes()),
range ([minValue, maxValue]
{
NormalisableRange<float> rangeWithInterval { (float) minValue, (float) maxValue,
[] (float start, float end, float v) { return jlimit (start, end, v * (end - start) + start); },
[] (float start, float end, float v) { return jlimit (0.0f, 1.0f, (v - start) / (end - start)); },
[] (float start, float end, float v) { return (float) roundToInt (juce::jlimit (start, end, v)); } };
rangeWithInterval.interval = 1.0f;
return rangeWithInterval;
}()),
value ((float) def),
defaultValue (convertTo0to1 ((float) def)),
stringFromIntFunction (attributes.getStringFromValueFunction() != nullptr
? attributes.getStringFromValueFunction()
: [] (int v, int) { return String (v); }),
intFromStringFunction (attributes.getValueFromStringFunction() != nullptr
? attributes.getValueFromStringFunction()
: [] (const String& text) { return text.getIntValue(); })
{
jassert (minValue < maxValue); // must have a non-zero range of values!
}
AudioParameterInt::~AudioParameterInt()
{
#if __cpp_lib_atomic_is_always_lock_free
static_assert (std::atomic<float>::is_always_lock_free,
"AudioParameterInt requires a lock-free std::atomic<float>");
#endif
}
float AudioParameterInt::getValue() const { return convertTo0to1 (value); }
void AudioParameterInt::setValue (float newValue) { value = convertFrom0to1 (newValue); valueChanged (get()); }
float AudioParameterInt::getDefaultValue() const { return defaultValue; }
int AudioParameterInt::getNumSteps() const { return ((int) getNormalisableRange().getRange().getLength()) + 1; }
float AudioParameterInt::getValueForText (const String& text) const { return convertTo0to1 ((float) intFromStringFunction (text)); }
String AudioParameterInt::getText (float v, int length) const { return stringFromIntFunction ((int) convertFrom0to1 (v), length); }
void AudioParameterInt::valueChanged (int) {}
AudioParameterInt& AudioParameterInt::operator= (int newValue)
{
if (get() != newValue)
setValueNotifyingHost (convertTo0to1 ((float) newValue));
return *this;
}
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
struct AudioParameterIntTests final : public UnitTest
{
AudioParameterIntTests()
: UnitTest ("AudioParameterInt", UnitTestCategories::audioProcessorParameters)
{}
void runTest() override
{
beginTest ("Three options switches at the correct points");
{
AudioParameterInt intParam ({}, {}, 1, 3, 1);
intParam.setValueNotifyingHost (0.0f);
expectEquals (intParam.get(), 1);
intParam.setValueNotifyingHost (0.2f);
expectEquals (intParam.get(), 1);
intParam.setValueNotifyingHost (0.3f);
expectEquals (intParam.get(), 2);
intParam.setValueNotifyingHost (0.7f);
expectEquals (intParam.get(), 2);
intParam.setValueNotifyingHost (0.8f);
expectEquals (intParam.get(), 3);
intParam.setValueNotifyingHost (1.0f);
expectEquals (intParam.get(), 3);
}
beginTest ("Out-of-bounds input");
{
AudioParameterInt intParam ({}, {}, -1, 2, 0);
intParam.setValueNotifyingHost (-0.5f);
expectEquals (intParam.get(), -1);
intParam.setValueNotifyingHost (1.5f);
expectEquals (intParam.get(), 2);
intParam = -5;
expectEquals (intParam.get(), -1);
intParam = 5;
expectEquals (intParam.get(), 2);
}
}
};
static AudioParameterIntTests audioParameterIntTests;
#endif
} // namespace juce

View file

@ -1,163 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/** Properties of an AudioParameterInt.
@see AudioParameterInt(), RangedAudioParameterAttributes()
@tags{Audio}
*/
class AudioParameterIntAttributes : public RangedAudioParameterAttributes<AudioParameterIntAttributes, int> {};
//==============================================================================
/**
Provides a class of AudioProcessorParameter that can be used as an
integer value with a given range.
@see AudioParameterFloat, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioParameterInt : public RangedAudioParameter
{
public:
/** Creates a AudioParameterInt with the specified parameters.
Note that the attributes argument is optional and only needs to be
supplied if you want to change options from their default values.
Example usage:
@code
auto attributes = AudioParameterIntAttributes().withStringFromValueFunction ([] (auto x, auto) { return String (x); })
.withLabel ("things");
auto param = std::make_unique<AudioParameterInt> ("paramID", "Parameter Name", 0, 100, 50, attributes);
@endcode
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param minValue The minimum parameter value
@param maxValue The maximum parameter value
@param defaultValue The default value
@param attributes Optional characteristics
*/
AudioParameterInt (const ParameterID& parameterID,
const String& parameterName,
int minValue,
int maxValue,
int defaultValue,
const AudioParameterIntAttributes& attributes = {});
/** Creates a AudioParameterInt with the specified parameters.
@param parameterID The parameter ID to use
@param parameterName The parameter name to use
@param minValue The minimum parameter value
@param maxValue The maximum parameter value
@param defaultValueIn The default value
@param parameterLabel An optional label for the parameter's value
@param stringFromInt An optional lambda function that converts an int
value to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param intFromString An optional lambda function that parses a string
and converts it into an int. Some hosts use this
to allow users to type in parameter values.
*/
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioParameterInt (const ParameterID& parameterID,
const String& parameterName,
int minValue,
int maxValue,
int defaultValueIn,
const String& parameterLabel,
std::function<String (int value, int maximumStringLength)> stringFromInt = nullptr,
std::function<int (const String& text)> intFromString = nullptr)
: AudioParameterInt (parameterID,
parameterName,
minValue,
maxValue,
defaultValueIn,
AudioParameterIntAttributes().withLabel (parameterLabel)
.withStringFromValueFunction (std::move (stringFromInt))
.withValueFromStringFunction (std::move (intFromString)))
{
}
/** Destructor. */
~AudioParameterInt() override;
/** Returns the parameter's current value as an integer. */
int get() const noexcept { return roundToInt (value.load()); }
/** Returns the parameter's current value as an integer. */
operator int() const noexcept { return get(); }
/** Changes the parameter's current value to a new integer.
The value passed in will be snapped to the permitted range before being used.
*/
AudioParameterInt& operator= (int newValue);
/** Returns the parameter's range. */
Range<int> getRange() const noexcept { return { (int) getNormalisableRange().start, (int) getNormalisableRange().end }; }
/** Returns the range of values that the parameter can take. */
const NormalisableRange<float>& getNormalisableRange() const override { return range; }
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (int newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
const NormalisableRange<float> range;
std::atomic<float> value;
const float defaultValue;
std::function<String (int, int)> stringFromIntFunction;
std::function<int (const String&)> intFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterInt)
};
} // namespace juce

View file

@ -1,56 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
AudioProcessorParameterWithID::AudioProcessorParameterWithID (const ParameterID& idToUse,
const String& nameToUse,
const AudioProcessorParameterWithIDAttributes& attributes)
: HostedAudioProcessorParameter (idToUse.getVersionHint()),
paramID (idToUse.getParamID()),
name (nameToUse),
label (attributes.getLabel()),
category (attributes.getCategory()),
meta (attributes.getMeta()),
automatable (attributes.getAutomatable()),
inverted (attributes.getInverted())
{
}
String AudioProcessorParameterWithID::getName (int maximumStringLength) const { return name.substring (0, maximumStringLength); }
String AudioProcessorParameterWithID::getLabel() const { return label; }
AudioProcessorParameter::Category AudioProcessorParameterWithID::getCategory() const { return category; }
} // namespace juce

View file

@ -1,200 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Combines a parameter ID and a version hint.
@tags{Audio}
*/
class ParameterID
{
public:
ParameterID() = default;
/** Constructs an instance.
Note that this constructor implicitly converts from Strings and string-like types.
@param identifier A string that uniquely identifies a single parameter
@param versionHint Influences parameter ordering in Audio Unit plugins.
Used to provide backwards compatibility of Audio Unit plugins in
Logic and GarageBand.
@see AudioProcessorParameter (int)
*/
template <typename StringLike, typename = DisableIfSameOrDerived<ParameterID, StringLike>>
ParameterID (StringLike&& identifier, int versionHint = 0)
: paramID (std::forward<StringLike> (identifier)), version (versionHint) {}
/** @see AudioProcessorParameterWithID::paramID */
auto getParamID() const { return paramID; }
/** @see AudioProcessorParameter (int) */
auto getVersionHint() const { return version; }
private:
String paramID;
int version = 0;
};
/**
An instance of this class may be passed to the constructor of an AudioProcessorParameterWithID
to set optional characteristics of that parameter.
@tags{Audio}
*/
class AudioProcessorParameterWithIDAttributes
{
using This = AudioProcessorParameterWithIDAttributes;
public:
using Category = AudioProcessorParameter::Category;
/** An optional label for the parameter's value */
[[nodiscard]] auto withLabel (String x) const { return withMember (*this, &This::label, std::move (x)); }
/** The semantics of this parameter */
[[nodiscard]] auto withCategory (Category x) const { return withMember (*this, &This::category, std::move (x)); }
/** @see AudioProcessorParameter::isMetaParameter() */
[[nodiscard]] auto withMeta (bool x) const { return withMember (*this, &This::meta, std::move (x)); }
/** @see AudioProcessorParameter::isAutomatable() */
[[nodiscard]] auto withAutomatable (bool x) const { return withMember (*this, &This::automatable, std::move (x)); }
/** @see AudioProcessorParameter::isOrientationInverted() */
[[nodiscard]] auto withInverted (bool x) const { return withMember (*this, &This::inverted, std::move (x)); }
/** An optional label for the parameter's value */
[[nodiscard]] auto getLabel() const { return label; }
/** The semantics of this parameter */
[[nodiscard]] auto getCategory() const { return category; }
/** @see AudioProcessorParameter::isMetaParameter() */
[[nodiscard]] auto getMeta() const { return meta; }
/** @see AudioProcessorParameter::isAutomatable() */
[[nodiscard]] auto getAutomatable() const { return automatable; }
/** @see AudioProcessorParameter::isOrientationInverted() */
[[nodiscard]] auto getInverted() const { return inverted; }
private:
String label;
Category category = AudioProcessorParameter::genericParameter;
bool meta = false, automatable = true, inverted = false;
};
//==============================================================================
/**
This abstract base class is used by some AudioProcessorParameter helper classes.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioProcessorParameterWithID : public HostedAudioProcessorParameter
{
public:
/** The creation of this object requires providing a name and ID which will be constant for its lifetime.
Given that AudioProcessorParameterWithID is abstract, you'll probably call this constructor
from a derived class constructor, e.g.
@code
MyParameterType (String paramID, String name, String label, bool automatable)
: AudioProcessorParameterWithID (paramID, name, AudioProcessorParameterWithIDAttributes().withLabel (label)
.withAutomatable (automatable))
{
}
@endcode
@param parameterID Specifies the identifier, and optionally the parameter's version hint.
@param parameterName The user-facing parameter name.
@param attributes Other parameter properties.
*/
AudioProcessorParameterWithID (const ParameterID& parameterID,
const String& parameterName,
const AudioProcessorParameterWithIDAttributes& attributes = {});
/** The creation of this object requires providing a name and ID which will be
constant for its lifetime.
@param parameterID Used to uniquely identify the parameter
@param parameterName The user-facing name of the parameter
@param parameterLabel An optional label for the parameter's value
@param parameterCategory The semantics of this parameter
*/
[[deprecated ("Prefer the signature taking an Attributes argument")]]
AudioProcessorParameterWithID (const ParameterID& parameterID,
const String& parameterName,
const String& parameterLabel,
Category parameterCategory = AudioProcessorParameter::genericParameter)
: AudioProcessorParameterWithID (parameterID,
parameterName,
AudioProcessorParameterWithIDAttributes().withLabel (parameterLabel)
.withCategory (parameterCategory))
{
}
/** Provides access to the parameter's ID string. */
const String paramID;
/** Provides access to the parameter's name. */
const String name;
/** Provides access to the parameter's label. */
const String label;
/** Provides access to the parameter's category. */
const Category category;
String getName (int) const override;
String getLabel() const override;
Category getCategory() const override;
String getParameterID() const override { return paramID; }
bool isMetaParameter() const override { return meta; }
bool isAutomatable() const override { return automatable; }
bool isOrientationInverted() const override { return inverted; }
private:
bool meta = false, automatable = true, inverted = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterWithID)
};
} // namespace juce

View file

@ -1,155 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
/** @cond */
// Forward declarations to avoid leaking implementation details.
namespace Steinberg::Vst
{
class IComponent;
} // namespace Steinberg::Vst
/** @endcond */
//==============================================================================
#if TARGET_OS_IPHONE
struct OpaqueAudioComponentInstance;
typedef struct OpaqueAudioComponentInstance* AudioComponentInstance;
#else
struct ComponentInstanceRecord;
typedef struct ComponentInstanceRecord* AudioComponentInstance;
#endif
typedef AudioComponentInstance AudioUnit;
//==============================================================================
/* If you are including the VST headers inside a namespace this forward
declaration may cause a collision with the contents of `aeffect.h`.
If that is the case you can avoid the collision by placing a `struct AEffect;`
forward declaration inside the namespace and before the inclusion of the VST
headers, e.g. @code
namespace Vst2
{
struct AEffect;
#include <pluginterfaces/vst2.x/aeffect.h>
#include <pluginterfaces/vst2.x/aeffectx.h>
}
@endcode
*/
struct AEffect;
//==============================================================================
namespace juce
{
//==============================================================================
/** Create a derived implementation of this class and pass it to
AudioPluginInstance::getExtensions() to retrieve format-specific
information about a plugin instance.
Note that the references passed to the visit member functions are only
guaranteed to live for the duration of the function call, so don't
store pointers to these objects! If you need to store and reuse
format-specific information, it is recommended to copy the result
of the function calls that you care about. For example, you should
store the result of VST::getAEffectPtr() rather than storing a pointer
to the VST instance.
@tags{Audio}
*/
struct ExtensionsVisitor
{
/** Indicates that there is no platform specific information available. */
struct Unknown {};
/** Can be used to retrieve information about a VST3 that is wrapped by an AudioProcessor. */
struct VST3Client
{
virtual ~VST3Client() = default;
virtual Steinberg::Vst::IComponent* getIComponentPtr() const noexcept = 0;
virtual MemoryBlock getPreset() const = 0;
virtual bool setPreset (const MemoryBlock&) const = 0;
};
/** Can be used to retrieve information about an AudioUnit that is wrapped by an AudioProcessor. */
struct AudioUnitClient
{
virtual ~AudioUnitClient() = default;
virtual AudioUnit getAudioUnitHandle() const noexcept = 0;
};
/** Can be used to retrieve information about a VST that is wrapped by an AudioProcessor. */
struct VSTClient
{
virtual ~VSTClient() = default;
virtual AEffect* getAEffectPtr() const noexcept = 0;
};
/** Can be used to retrieve information about a plugin that provides ARA extensions. */
struct ARAClient
{
virtual ~ARAClient() = default;
virtual void createARAFactoryAsync (std::function<void (ARAFactoryWrapper)>) const = 0;
};
ExtensionsVisitor() = default;
ExtensionsVisitor (const ExtensionsVisitor&) = default;
ExtensionsVisitor (ExtensionsVisitor&&) = default;
ExtensionsVisitor& operator= (const ExtensionsVisitor&) = default;
ExtensionsVisitor& operator= (ExtensionsVisitor&&) = default;
virtual ~ExtensionsVisitor() = default;
/** Will be called if there is no platform specific information available. */
virtual void visitUnknown (const Unknown&) {}
/** Called with VST3-specific information. */
virtual void visitVST3Client (const VST3Client&) {}
/** Called with VST-specific information. */
virtual void visitVSTClient (const VSTClient&) {}
/** Called with AU-specific information. */
virtual void visitAudioUnitClient (const AudioUnitClient&) {}
/** Called with ARA-specific information. */
virtual void visitARAClient (const ARAClient&) {}
};
} // namespace juce

View file

@ -1,189 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
/** @cond */
namespace juce
{
template <size_t requiredFlagBitsPerItem>
class FlagCache
{
using FlagType = uint32_t;
public:
FlagCache() = default;
explicit FlagCache (size_t items)
: flags (divCeil (items, groupsPerWord))
{
std::fill (flags.begin(), flags.end(), 0);
}
void set (size_t index, FlagType bits)
{
const auto flagIndex = index / groupsPerWord;
jassert (flagIndex < flags.size());
const auto groupIndex = index - (flagIndex * groupsPerWord);
flags[flagIndex].fetch_or (moveToGroupPosition (bits, groupIndex), std::memory_order_acq_rel);
}
/* Calls the supplied callback for any entries with non-zero flags, and
sets all flags to zero.
*/
template <typename Callback>
void ifSet (Callback&& callback)
{
for (size_t flagIndex = 0; flagIndex < flags.size(); ++flagIndex)
{
const auto prevFlags = flags[flagIndex].exchange (0, std::memory_order_acq_rel);
for (size_t group = 0; group < groupsPerWord; ++group)
{
const auto masked = moveFromGroupPosition (prevFlags, group);
if (masked != 0)
callback ((flagIndex * groupsPerWord) + group, masked);
}
}
}
void clear()
{
std::fill (flags.begin(), flags.end(), 0);
}
private:
/* Given the flags for a single item, and a group index, shifts the flags
so that they are positioned at the appropriate location for that group
index.
e.g. If the flag type is a uint32_t, and there are 2 flags per item,
then each uint32_t will hold flags for 16 items. The flags for item 0
are the least significant two bits; the flags for item 15 are the most
significant two bits.
*/
static constexpr FlagType moveToGroupPosition (FlagType ungrouped, size_t groupIndex)
{
return (ungrouped & groupMask) << (groupIndex * bitsPerFlagGroup);
}
/* Given a set of grouped flags for multiple items, and a group index,
extracts the flags set for an item at that group index.
e.g. If the flag type is a uint32_t, and there are 2 flags per item,
then each uint32_t will hold flags for 16 items. Asking for groupIndex
0 will return the least significant two bits; asking for groupIndex 15
will return the most significant two bits.
*/
static constexpr FlagType moveFromGroupPosition (FlagType grouped, size_t groupIndex)
{
return (grouped >> (groupIndex * bitsPerFlagGroup)) & groupMask;
}
static constexpr size_t findNextPowerOfTwoImpl (size_t n, size_t shift)
{
return shift == 32 ? n : findNextPowerOfTwoImpl (n | (n >> shift), shift * 2);
}
static constexpr size_t findNextPowerOfTwo (size_t value)
{
return findNextPowerOfTwoImpl (value - 1, 1) + 1;
}
static constexpr size_t divCeil (size_t a, size_t b)
{
return (a / b) + ((a % b) != 0);
}
static constexpr size_t bitsPerFlagGroup = findNextPowerOfTwo (requiredFlagBitsPerItem);
static constexpr size_t groupsPerWord = (8 * sizeof (FlagType)) / bitsPerFlagGroup;
static constexpr FlagType groupMask = ((FlagType) 1 << requiredFlagBitsPerItem) - 1;
std::vector<std::atomic<FlagType>> flags;
};
template <size_t requiredFlagBitsPerItem>
class FlaggedFloatCache
{
public:
FlaggedFloatCache() = default;
explicit FlaggedFloatCache (size_t sizeIn)
: values (sizeIn),
flags (sizeIn)
{
std::fill (values.begin(), values.end(), 0.0f);
}
size_t size() const noexcept { return values.size(); }
float exchangeValue (size_t index, float value)
{
jassert (index < size());
return values[index].exchange (value, std::memory_order_relaxed);
}
void setBits (size_t index, uint32_t bits) { flags.set (index, bits); }
void setValueAndBits (size_t index, float value, uint32_t bits)
{
exchangeValue (index, value);
setBits (index, bits);
}
float get (size_t index) const noexcept
{
jassert (index < size());
return values[index].load (std::memory_order_relaxed);
}
/* Calls the supplied callback for any entries which have been modified
since the last call to this function.
*/
template <typename Callback>
void ifSet (Callback&& callback)
{
flags.ifSet ([this, &callback] (size_t groupIndex, uint32_t bits)
{
callback (groupIndex, values[groupIndex].load (std::memory_order_relaxed), bits);
});
}
private:
std::vector<std::atomic<float>> values;
FlagCache<requiredFlagBitsPerItem> flags;
};
} // namespace juce
/** @endcond */

View file

@ -1,60 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
int RangedAudioParameter::getNumSteps() const
{
const auto& range = getNormalisableRange();
if (range.interval > 0)
return (static_cast<int> ((range.end - range.start) / range.interval) + 1);
return getDefaultNumParameterSteps();
}
float RangedAudioParameter::convertTo0to1 (float v) const noexcept
{
const auto& range = getNormalisableRange();
return range.convertTo0to1 (range.snapToLegalValue (v));
}
float RangedAudioParameter::convertFrom0to1 (float v) const noexcept
{
const auto& range = getNormalisableRange();
return range.snapToLegalValue (range.convertFrom0to1 (jlimit (0.0f, 1.0f, v)));
}
} // namespace juce

View file

@ -1,129 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
@internal
Holds common attributes of audio parameters.
CRTP is used here because we want the Attributes types for each parameter
(Float, Bool, Choice, Int) to be distinct and extensible in the future.
i.e. the identifiers AudioParameterFloatAttributes and RangedAudioParameterAttributes<float>
should not be interchangable because we might need to add float-specific attributes in
the future. Users should not refer directly to RangedAudioParameterAttributes.
@tags{Audio}
*/
template <typename Derived, typename Value>
class RangedAudioParameterAttributes
{
using This = RangedAudioParameterAttributes;
public:
using Category = AudioProcessorParameter::Category;
using StringFromValue = std::function<String (Value, int)>;
using ValueFromString = std::function<Value (const String&)>;
/** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */
[[nodiscard]] auto withStringFromValueFunction (StringFromValue x) const { return withMember (asDerived(), &Derived::stringFromValue, std::move (x)); }
/** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */
[[nodiscard]] auto withValueFromStringFunction (ValueFromString x) const { return withMember (asDerived(), &Derived::valueFromString, std::move (x)); }
/** See AudioProcessorParameterWithIDAttributes::withLabel() */
[[nodiscard]] auto withLabel (String x) const { return withMember (asDerived(), &Derived::attributes, attributes.withLabel (std::move (x))); }
/** See AudioProcessorParameterWithIDAttributes::withCategory() */
[[nodiscard]] auto withCategory (Category x) const { return withMember (asDerived(), &Derived::attributes, attributes.withCategory (std::move (x))); }
/** See AudioProcessorParameter::isMetaParameter() */
[[nodiscard]] auto withMeta (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withMeta (std::move (x))); }
/** See AudioProcessorParameter::isAutomatable() */
[[nodiscard]] auto withAutomatable (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withAutomatable (std::move (x))); }
/** See AudioProcessorParameter::isOrientationInverted() */
[[nodiscard]] auto withInverted (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withInverted (std::move (x))); }
/** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */
[[nodiscard]] const auto& getStringFromValueFunction() const { return stringFromValue; }
/** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */
[[nodiscard]] const auto& getValueFromStringFunction() const { return valueFromString; }
/** Gets attributes that would also apply to an AudioProcessorParameterWithID */
[[nodiscard]] const auto& getAudioProcessorParameterWithIDAttributes() const { return attributes; }
private:
auto& asDerived() const { return *static_cast<const Derived*> (this); }
AudioProcessorParameterWithIDAttributes attributes;
StringFromValue stringFromValue;
ValueFromString valueFromString;
};
//==============================================================================
/**
This abstract base class is used by some AudioProcessorParameter helper classes.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API RangedAudioParameter : public AudioProcessorParameterWithID
{
public:
using AudioProcessorParameterWithID::AudioProcessorParameterWithID;
/** Returns the range of values that the parameter can take. */
virtual const NormalisableRange<float>& getNormalisableRange() const = 0;
/** Returns the number of steps for this parameter based on the normalisable range's interval.
If you are using lambda functions to define the normalisable range's snapping behaviour
then you should override this function so that it returns the number of snapping points.
*/
int getNumSteps() const override;
/** Normalises and snaps a value based on the normalisable range. */
float convertTo0to1 (float v) const noexcept;
/** Denormalises and snaps a value based on the normalisable range. */
float convertFrom0to1 (float v) const noexcept;
};
} // namespace juce

View file

@ -1,48 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
pointer_sized_int VST2ClientExtensions::handleVstPluginCanDo ([[maybe_unused]] int32 index,
[[maybe_unused]] pointer_sized_int value,
[[maybe_unused]] void* ptr,
[[maybe_unused]] float opt)
{
return 0;
}
void VST2ClientExtensions::handleVstHostCallbackAvailable ([[maybe_unused]] std::function<VstHostCallbackType>&& callback) {}
} // namespace juce

View file

@ -1,83 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
An interface to allow an AudioProcessor to implement extended VST2-specific functionality.
To use this class, create an object that inherits from it, implement the methods, then return
a pointer to the object in your AudioProcessor::getVST2ClientExtensions() method.
@see AudioProcessor, AAXClientExtensions, VST3ClientExtensions
@tags{Audio}
*/
struct VST2ClientExtensions
{
virtual ~VST2ClientExtensions() = default;
/** This is called by the VST plug-in wrapper when it receives unhandled
plug-in "can do" calls from the host.
*/
virtual pointer_sized_int handleVstPluginCanDo (int32 index,
pointer_sized_int value,
void* ptr,
float opt);
/** This is called by the VST plug-in wrapper when it receives unhandled
vendor specific calls from the host.
*/
virtual pointer_sized_int handleVstManufacturerSpecific (int32 index,
pointer_sized_int value,
void* ptr,
float opt) = 0;
/** The host callback function type. */
using VstHostCallbackType = pointer_sized_int (int32 opcode,
int32 index,
pointer_sized_int value,
void* ptr,
float opt);
/** This is called once by the VST plug-in wrapper after its constructor.
You can use the supplied function to query the VST host.
*/
virtual void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& callback);
};
using VSTCallbackHandler [[deprecated ("replace with VST2ClientExtensions")]] = VST2ClientExtensions;
} // namespace juce

View file

@ -1,53 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
namespace juce
{
std::map<uint32_t, String> VST3ClientExtensions::getCompatibleParameterIds (const VST3Interface::Id&) const
{
return {};
}
uint32_t VST3ClientExtensions::convertJuceParameterId (const String& parameterId, bool studioOneCompatible)
{
auto hash = (uint32_t) (parameterId.hashCode());
if (studioOneCompatible)
hash &= 0x7fffffff;
return hash;
}
} // namespace juce

View file

@ -1,273 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
/** @cond */
// Forward declaration to avoid leaking implementation details.
namespace Steinberg
{
class FUnknown;
using TUID = char[16];
} // namespace Steinberg
/** @endcond */
namespace juce
{
/**
An interface to allow an AudioProcessor to implement extended VST3-specific functionality.
To use this class, create an object that inherits from it, implement the methods, then return
a pointer to the object in your AudioProcessor::getVST3ClientExtensions() method.
@see AudioProcessor, AAXClientExtensions, VST2ClientExtensions
@tags{Audio}
*/
struct VST3ClientExtensions
{
virtual ~VST3ClientExtensions() = default;
/** This function may be used by implementations of queryInterface()
in the VST3's implementation of IEditController to return
additional supported interfaces.
*/
virtual int32_t queryIEditController (const Steinberg::TUID, void** obj)
{
*obj = nullptr;
return -1;
}
/** This function may be used by implementations of queryInterface()
in the VST3's implementation of IAudioProcessor to return
additional supported interfaces.
*/
virtual int32_t queryIAudioProcessor (const Steinberg::TUID, void** obj)
{
*obj = nullptr;
return -1;
}
/** This may be called by the VST3 wrapper when the host sets an
IComponentHandler for the plugin to use.
You should not make any assumptions about how and when this will be
called - this function may not be called at all!
*/
virtual void setIComponentHandler (Steinberg::FUnknown*) {}
/** This may be called shortly after the AudioProcessor is constructed
with the current IHostApplication.
You should not make any assumptions about how and when this will be
called - this function may not be called at all!
*/
virtual void setIHostApplication (Steinberg::FUnknown*) {}
/** This function will be called to check whether the first input bus
should be designated as "kMain" or "kAux". Return true if the
first bus should be kMain, or false if the bus should be kAux.
All other input buses will always be designated kAux.
*/
virtual bool getPluginHasMainInput() const { return true; }
/** This function should return a map of VST3 parameter IDs and the JUCE
parameters they map to.
This information is used to implement the IRemapParamID interface.
Hosts can use this to preserve automation data when a session was saved
using a compatible plugin that has different parameter IDs.
Not all hosts will take this information into account. Therefore,
parameter IDs should be maintained between plugin versions. For JUCE
plugins migrating from VST2 to VST3 the best method for achieving this
is enabling JUCE_FORCE_LEGACY_PARAM_IDS. However, if a plugin has
already been released without enabling this flag, this method offers an
alternative approach that won't cause any further compatibility issues.
The key in the map is an integer which may represent a VST3 parameter
identifier (Vst::ParamID) or VST2 parameter index.
You should include a map entry for every parameter ID in the compatible
plugin.
For VST2 or JUCE plugins these IDs can be determined in the following ways.
- Use the parameter index if any of the following apply:
- the InterfaceId argument refers to a compatible VST2 plugin, or
- the InterfaceId argument refers to a JUCE VST3 plugin with
JUCE_FORCE_LEGACY_PARAM_IDS enabled, or
- the InterfaceId argument refers to a JUCE plugin, but the parameter
in the compatible plugin doesn't inherit from
HostedAudioProcessorParameter (this case is unlikely).
- Otherwise, use convertJuceParameterId() for JUCE VST3 plugins where
JUCE_FORCE_LEGACY_PARAM_IDS is disabled, and where the compatible
parameter derives from HostedAudioProcessorParameter.
- For non-JUCE VST3s, use the Vst::ParamIDs exported by the compatible
VST3.
The value in the map is the JUCE parameter ID for the parameter to map
to, or an empty string to indicate that there is no parameter to map to.
If a parameter doesn't inherit from HostedAudioProcessorParameter its ID
will be the parameter index as a string, for example "1". Otherwise,
always use the actual parameter ID (even if JUCE_FORCE_LEGACY_PARAM_IDS
is enabled).
In the unlikely event that two plugins share the same plugin ID, and
both have a different parameters that share the same parameter ID, it
may be possible to determine which version of the plugin is being loaded
during setStateInformation(). This method will always be called after
setStateInformation(), so that the map with the correct mapping can be
provided when queried.
Below is an example of how you might implement this function for a JUCE
VST3 plugin where JUCE_VST3_CAN_REPLACE_VST2 is enabled, but
JUCE_FORCE_LEGACY_PARAM_IDS is disabled.
@code
std::map<uint32_t, String> getCompatibleParameterIds (const InterfaceId&) const override
{
return { { 0, "Frequency" },
{ 1, "CutOff" },
{ 2, "Gain" },
{ 3, "Bypass" } };
}
@endcode
@param compatibleClass A plugin identifier, either for the current
plugin or one listed in JUCE_VST3_COMPATIBLE_CLASSES.
This parameter allows the implementation to
return a different parameter map for each
compatible class. Use VST3Interface::jucePluginId()
and VST3Interface::vst2PluginId() to determine
the class IDs used by JUCE plugins. When
JUCE_VST3_CAN_REPLACE_VST2 is set, the ID
denoting the VST2 version of the plugin will
match the ID of the VST3 that replaces it. In
this case, assuming there are no collisions
between the VST2 parameter indices and the VST3
ParamIDs you should only include the VST2
mappings in the returned map. In the unlikely
event of a collision you should inspect the
state that was most recently passed to
setStateInformation() to determine whether the
host is loading a VST2 state that requires
parameter remapping. If you determine that no
remapping is necessary, you can indicate this by
returning an empty map.
@returns A map where each key is a VST3 parameter ID in the compatible
plugin, and the value is the unique JUCE parameter ID in the
current plugin that it should be mapped to.
@see JUCE_VST3_COMPATIBLE_CLASSES, VST3Interface::jucePluginId, VST3Interface::vst2PluginId, VST3Interface::hexStringToId
*/
virtual std::map<uint32_t, String> getCompatibleParameterIds (const VST3Interface::Id& compatibleClass) const;
/** Returns the VST3 compatible parameter ID reported for a given JUCE
parameter.
Internally JUCE will use this method to determine the Vst::ParamID for
a HostedAudioProcessorParameter, unless JUCE_FORCE_LEGACY_PARAM_IDS is
enabled, in which case it will use the parameter index.
@see getCompatibleParameterIds
*/
static uint32_t convertJuceParameterId (const String& parameterId,
bool studioOneCompatible = true);
private:
/** Instead of overriding this function you should define the preprocessor
definition JUCE_VST3_COMPATIBLE_CLASSES as described in the docs.
@see JUCE_VST3_COMPATIBLE_CLASSES
*/
virtual std::vector<VST3Interface::Id> getCompatibleClasses() const final
{
return {};
}
};
#if DOXYGEN
/** An optional user defined preprocessor definition for declaring a comma
separated list of VST2 and VST3 plugin identifiers that this VST3 plugin
can replace in a DAW session.
The definition of this preprocessor must be defined at the project
level, normally in your CMake or Projucer project files.
This information will be used to implement the IPluginCompatibility
interface.
If JUCE_VST3_CAN_REPLACE_VST2 is enabled, the VST3 plugin will have the
same identifier as the VST2 plugin and therefore you don't need to
implement this preprocessor definition.
This preprocessor definition can contain code that depends on any class
or function defined as part of the VST3Interface struct but should avoid
any other dependencies!
Each compatible class is a 16-byte array that corresponds to the VST3
interface identifier as reported by a plugins IComponent interface.
For VST2 or JUCE plugins these identifiers can be determined in the
following ways:
- Use VST3Interface::vst2PluginId() for any VST2 plugins or JUCE VST3
plugin with JUCE_VST3_CAN_REPLACE_VST3 enabled
- Use VST3Interface::jucePluginId() for any other JUCE VST3 plugins
Examples
@code
// Defines a VST2 plugin this VST3 can replace
JUCE_VST3_COMPATIBLE_CLASSES=VST3Interface::vst2PluginId ('Plug', "Plugin Name")
// Defines a VST3 plugin this VST3 can replace
JUCE_VST3_COMPATIBLE_CLASSES=VST3Interface::jucePluginId ('Manu', 'Plug')
// Defines both a VST2 and a VST3 plugin this VST3 can replace
JUCE_VST3_COMPATIBLE_CLASSES=VST3Interface::vst2PluginId ('Plug', "Plugin Name"), VST3Interface::jucePluginId ('Manu', 'Plug')
// Defines a non-JUCE VST3 plugin this VST3 can replace
JUCE_VST3_COMPATIBLE_CLASSES=VST3Interface::hexStringToId ("0F1E2D3C4B5A69788796A5B4C3D2E1F0")
@endcode
If the parameter IDs between compatible versions differ
VST3ClientExtensions::getCompatibleParameterIds() should also be overridden.
@see VST3Interface VST3ClientExtensions::getCompatibleParameterIds()
*/
#define JUCE_VST3_COMPATIBLE_CLASSES
#endif // DOXYGEN
} // namespace juce

View file

@ -1,248 +0,0 @@
/*
==============================================================================
This file is part of the JUCE framework.
Copyright (c) Raw Material Software Limited
JUCE is an open source framework subject to commercial or open source
licensing.
By downloading, installing, or using the JUCE framework, or combining the
JUCE framework with any other source code, object code, content or any other
copyrightable work, you agree to the terms of the JUCE End User Licence
Agreement, and all incorporated terms including the JUCE Privacy Policy and
the JUCE Website Terms of Service, as applicable, which will bind you. If you
do not agree to the terms of these agreements, we will not license the JUCE
framework to you, and you must discontinue the installation or download
process and cease use of the JUCE framework.
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
Or:
You may also use this code under the terms of the AGPLv3:
https://www.gnu.org/licenses/agpl-3.0.en.html
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
==============================================================================
*/
#pragma once
namespace juce
{
/** Useful functions and classes for defining VST3 Interface Ids.
The classes and functions in this struct are intentionally lightweight,
requiring almost no JUCE or Steinberg VST3 SDK dependencies.
@tags{Audio}
*/
struct VST3Interface
{
/** An enum indicating the various VST3 interface types.
In most cases users shouldn't need to concern themselves with any interfaces
other than the component, which is used to report the actual audio effect.
*/
enum class Type
{
ara,
controller,
compatibility,
component,
processor
};
/** A type storing the byte values for a unique VST3 interface identifier. */
using Id = std::array<std::byte, 16>;
/** Returns a 16-byte array indicating the VST3 interface ID used for a given
VST2 plugin.
Internally JUCE will use this method to assign an ID for the component and
controller interfaces when JUCE_VST3_CAN_REPLACE_VST2 is enabled.
@see jucePluginId, hexStringToId
*/
static Id vst2PluginId (uint32_t pluginCode,
const char* pluginName,
Type interfaceType = Type::component)
{
Id iid{};
iid[0] = (std::byte) 'V';
iid[1] = (std::byte) 'S';
iid[2] = (std::byte) std::invoke ([&]
{
switch (interfaceType)
{
case Type::controller: return 'E';
case Type::component: return 'T';
case Type::ara: [[fallthrough]];
case Type::compatibility: [[fallthrough]];
case Type::processor: break;
}
// A VST2 plugin only has two possible interfaces
// - component (the audio effect)
// - controller (the editor/UI)
jassertfalse;
return '\0';
});
iid[3] = (std::byte) (pluginCode >> 24);
iid[4] = (std::byte) (pluginCode >> 16);
iid[5] = (std::byte) (pluginCode >> 8);
iid[6] = (std::byte) pluginCode;
for (size_t index = 7; index < iid.size() && *pluginName != 0; ++index)
{
iid[index] = (std::byte) std::tolower (*pluginName);
++pluginName;
}
#if JUCE_WINDOWS
std::swap (iid[0], iid[3]);
std::swap (iid[1], iid[2]);
std::swap (iid[4], iid[5]);
std::swap (iid[6], iid[7]);
#endif
return iid;
}
/** Returns a 16-byte array indicating the VST3 interface ID used for a given
JUCE VST3 plugin.
Internally this is what JUCE will use to assign an ID to each VST3 interface,
unless JUCE_VST3_CAN_REPLACE_VST2 is enabled.
@see vst2PluginId, hexStringToId
*/
static inline Id jucePluginId (uint32_t manufacturerCode,
uint32_t pluginCode,
Type interfaceType = Type::component)
{
const auto word0 = std::invoke ([&]() -> uint32_t
{
switch (interfaceType)
{
case Type::ara: [[fallthrough]];
case Type::controller: [[fallthrough]];
case Type::compatibility: [[fallthrough]];
case Type::component: return 0xABCDEF01;
case Type::processor: return 0x0101ABAB;
}
jassertfalse;
return 0;
});
const auto word1 = std::invoke ([&]() -> uint32_t
{
switch (interfaceType)
{
case Type::ara: return 0xA1B2C3D4;
case Type::controller: return 0x1234ABCD;
case Type::compatibility: return 0xC0DEF00D;
case Type::component: return 0x9182FAEB;
case Type::processor: return 0xABCDEF01;
}
jassertfalse;
return 0;
});
constexpr auto getByteFromLSB = [] (uint32_t word, int byteIndex)
{
jassert (0 <= byteIndex && byteIndex <= 3);
return (std::byte) ((word >> (byteIndex * 8)) & 0xff);
};
#if JUCE_WINDOWS
constexpr auto isWindows = true;
#else
constexpr auto isWindows = false;
#endif
return {
getByteFromLSB (word0, isWindows ? 0 : 3),
getByteFromLSB (word0, isWindows ? 1 : 2),
getByteFromLSB (word0, isWindows ? 2 : 1),
getByteFromLSB (word0, isWindows ? 3 : 0),
getByteFromLSB (word1, isWindows ? 2 : 3),
getByteFromLSB (word1, isWindows ? 3 : 2),
getByteFromLSB (word1, isWindows ? 0 : 1),
getByteFromLSB (word1, isWindows ? 1 : 0),
getByteFromLSB (manufacturerCode, 3),
getByteFromLSB (manufacturerCode, 2),
getByteFromLSB (manufacturerCode, 1),
getByteFromLSB (manufacturerCode, 0),
getByteFromLSB (pluginCode, 3),
getByteFromLSB (pluginCode, 2),
getByteFromLSB (pluginCode, 1),
getByteFromLSB (pluginCode, 0)
};
}
/** Converts a 32-character hex notation string to a VST3 interface ID.
@see jucePluginId, vst2PluginId
*/
static inline Id hexStringToId (const char* hex)
{
jassert (std::strlen (hex) == 32);
const auto getByteValue = [](const char* str)
{
const auto getCharacterValue = [](const char c)
{
if (c >= '0' && c <= '9')
return (std::byte) (c - '0');
if (c >= 'A' && c <= 'F')
return (std::byte) (c - 'A' + 10);
if (c >= 'a' && c <= 'f')
return (std::byte) (c - 'a' + 10);
// Invalid hex character!
jassertfalse;
return std::byte{};
};
return getCharacterValue (str[0]) << 4
| getCharacterValue (str[1]);
};
return { getByteValue (hex),
getByteValue (hex + 2),
getByteValue (hex + 4),
getByteValue (hex + 6),
getByteValue (hex + 8),
getByteValue (hex + 10),
getByteValue (hex + 12),
getByteValue (hex + 14),
getByteValue (hex + 16),
getByteValue (hex + 18),
getByteValue (hex + 20),
getByteValue (hex + 22),
getByteValue (hex + 24),
getByteValue (hex + 26),
getByteValue (hex + 28),
getByteValue (hex + 30) };
}
VST3Interface() = delete;
};
} // namespace juce