@@ -1088,6 +1088,7 @@ void AudioDeviceManager::setDefaultMidiOutputDevice (const String& identifier) | |||||
{ | { | ||||
if (defaultMidiOutputDeviceInfo.identifier != identifier) | if (defaultMidiOutputDeviceInfo.identifier != identifier) | ||||
{ | { | ||||
std::unique_ptr<MidiOutput> oldMidiPort; | |||||
Array<AudioIODeviceCallback*> oldCallbacks; | Array<AudioIODeviceCallback*> oldCallbacks; | ||||
{ | { | ||||
@@ -1099,7 +1100,7 @@ void AudioDeviceManager::setDefaultMidiOutputDevice (const String& identifier) | |||||
for (int i = oldCallbacks.size(); --i >= 0;) | for (int i = oldCallbacks.size(); --i >= 0;) | ||||
oldCallbacks.getUnchecked (i)->audioDeviceStopped(); | oldCallbacks.getUnchecked (i)->audioDeviceStopped(); | ||||
defaultMidiOutput.reset(); | |||||
std::swap (oldMidiPort, defaultMidiOutput); | |||||
if (identifier.isNotEmpty()) | if (identifier.isNotEmpty()) | ||||
defaultMidiOutput = MidiOutput::openDevice (identifier); | defaultMidiOutput = MidiOutput::openDevice (identifier); | ||||
@@ -1119,7 +1120,7 @@ void AudioDeviceManager::setDefaultMidiOutputDevice (const String& identifier) | |||||
} | } | ||||
updateXml(); | updateXml(); | ||||
sendChangeMessage(); | |||||
sendSynchronousChangeMessage(); | |||||
} | } | ||||
} | } | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -133,6 +140,18 @@ public: | |||||
/** Returns true if instantiation of this plugin type must be done from a non-message thread. */ | /** Returns true if instantiation of this plugin type must be done from a non-message thread. */ | ||||
virtual bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const = 0; | 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: | protected: | ||||
//============================================================================== | //============================================================================== | ||||
friend class AudioPluginFormatManager; | friend class AudioPluginFormatManager; | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -129,6 +136,22 @@ std::unique_ptr<AudioPluginInstance> AudioPluginFormatManager::createPluginInsta | |||||
return {}; | return {}; | ||||
} | } | ||||
void AudioPluginFormatManager::createARAFactoryAsync (const PluginDescription& description, | |||||
AudioPluginFormat::ARAFactoryCreationCallback callback) const | |||||
{ | |||||
String errorMessage; | |||||
if (auto* format = findFormatForDescription (description, errorMessage)) | |||||
{ | |||||
format->createARAFactoryAsync (description, callback); | |||||
} | |||||
else | |||||
{ | |||||
errorMessage = NEEDS_TRANS ("Couldn't find format for the provided description"); | |||||
callback ({ {}, std::move (errorMessage) }); | |||||
} | |||||
} | |||||
void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description, | void AudioPluginFormatManager::createPluginInstanceAsync (const PluginDescription& description, | ||||
double initialSampleRate, int initialBufferSize, | double initialSampleRate, int initialBufferSize, | ||||
AudioPluginFormat::PluginCreationCallback callback) | AudioPluginFormat::PluginCreationCallback callback) | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -102,6 +109,22 @@ public: | |||||
double initialSampleRate, int initialBufferSize, | double initialSampleRate, int initialBufferSize, | ||||
AudioPluginFormat::PluginCreationCallback callback); | AudioPluginFormat::PluginCreationCallback callback); | ||||
/** 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. | |||||
The operation may fail, in which case the callback will be called with | |||||
with a result object where ARAFactoryResult::araFactory.get() will return | |||||
a nullptr. | |||||
In case of success the returned ::ARAFactoryWrapper will ensure that | |||||
modules required for the correct functioning of the ARAFactory will remain | |||||
loaded for the lifetime of the object. | |||||
*/ | |||||
void createARAFactoryAsync (const PluginDescription& description, | |||||
AudioPluginFormat::ARAFactoryCreationCallback callback) const; | |||||
/** Checks that the file or component for this plugin actually still exists. | /** Checks that the file or component for this plugin actually still exists. | ||||
(This won't try to load the plugin) | (This won't try to load the plugin) | ||||
*/ | */ | ||||
@@ -6,10 +6,10 @@ | |||||
# JUCE is an open source library subject to commercial or open-source | # JUCE is an open source library subject to commercial or open-source | ||||
# licensing. | # licensing. | ||||
# | # | ||||
# By using JUCE, you agree to the terms of both the JUCE 6 End-User License | |||||
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). | |||||
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
# Agreement and JUCE Privacy Policy. | |||||
# | # | ||||
# End User License Agreement: www.juce.com/juce-6-licence | |||||
# End User License Agreement: www.juce.com/juce-7-licence | |||||
# Privacy Policy: www.juce.com/juce-privacy-policy | # Privacy Policy: www.juce.com/juce-privacy-policy | ||||
# | # | ||||
# Or: You may also use this code under the terms of the GPL v3 (see | # Or: You may also use this code under the terms of the GPL v3 (see | ||||
@@ -57,10 +57,10 @@ FUNCTION_TEMPLATE = """/* | |||||
JUCE is an open source library subject to commercial or open-source | JUCE is an open source library subject to commercial or open-source | ||||
licensing. | licensing. | ||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License | |||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-6-licence | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | Privacy Policy: www.juce.com/juce-privacy-policy | ||||
Or: You may also use this code under the terms of the GPL v3 (see | Or: You may also use this code under the terms of the GPL v3 (see | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -0,0 +1,76 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#if (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU) && (JUCE_MAC || JUCE_WINDOWS)) | |||||
#include <ARA_Library/Debug/ARADebug.h> | |||||
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); | |||||
} | |||||
static std::shared_ptr<const ARA::ARAFactory> getOrCreateARAFactory (const ARA::ARAFactory* ptr, | |||||
std::function<void (const ARA::ARAFactory*)> 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()) | |||||
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 (factory); | |||||
}); | |||||
cachePtr = obj; | |||||
return obj; | |||||
} | |||||
} | |||||
#endif |
@@ -0,0 +1,85 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#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; | |||||
}; | |||||
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)... }; | |||||
} | |||||
} // namespace juce |
@@ -0,0 +1,458 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#if (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU) && (JUCE_MAC || JUCE_WINDOWS)) | |||||
#include "juce_ARAHosting.h" | |||||
#include <ARA_Library/Debug/ARADebug.h> | |||||
#include <ARA_Library/Dispatch/ARAHostDispatch.cpp> | |||||
namespace juce | |||||
{ | |||||
struct ARAEditGuardState | |||||
{ | |||||
public: | |||||
/* Returns true if this controller wasn't previously present. */ | |||||
bool add (ARA::Host::DocumentController& dc) | |||||
{ | |||||
const std::lock_guard<std::mutex> lock (mutex); | |||||
return ++counts[&dc] == 1; | |||||
} | |||||
/* Returns true if this controller is no longer present. */ | |||||
bool remove (ARA::Host::DocumentController& dc) | |||||
{ | |||||
const std::lock_guard<std::mutex> lock (mutex); | |||||
return --counts[&dc] == 0; | |||||
} | |||||
private: | |||||
std::map<ARA::Host::DocumentController*, int> counts; | |||||
std::mutex mutex; | |||||
}; | |||||
static ARAEditGuardState editGuardState; | |||||
ARAEditGuard::ARAEditGuard (ARA::Host::DocumentController& dcIn) : dc (dcIn) | |||||
{ | |||||
if (editGuardState.add (dc)) | |||||
dc.beginEditing(); | |||||
} | |||||
ARAEditGuard::~ARAEditGuard() | |||||
{ | |||||
if (editGuardState.remove (dc)) | |||||
dc.endEditing(); | |||||
} | |||||
//============================================================================== | |||||
namespace ARAHostModel | |||||
{ | |||||
//============================================================================== | |||||
AudioSource::AudioSource (ARA::ARAAudioSourceHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
const ARA::ARAAudioSourceProperties& props) | |||||
: ManagedARAHandle (dc, [&] | |||||
{ | |||||
const ARAEditGuard guard (dc); | |||||
return dc.createAudioSource (hostRef, &props); | |||||
}()) | |||||
{ | |||||
} | |||||
void AudioSource::update (const ARA::ARAAudioSourceProperties& props) | |||||
{ | |||||
const ARAEditGuard guard (getDocumentController()); | |||||
getDocumentController().updateAudioSourceProperties (getPluginRef(), &props); | |||||
} | |||||
void AudioSource::enableAudioSourceSamplesAccess (bool x) | |||||
{ | |||||
const ARAEditGuard guard (getDocumentController()); | |||||
getDocumentController().enableAudioSourceSamplesAccess (getPluginRef(), x); | |||||
} | |||||
void AudioSource::destroy (ARA::Host::DocumentController& dc, Ptr ptr) | |||||
{ | |||||
dc.destroyAudioSource (ptr); | |||||
} | |||||
//============================================================================== | |||||
AudioModification::AudioModification (ARA::ARAAudioModificationHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
AudioSource& s, | |||||
const ARA::ARAAudioModificationProperties& props) | |||||
: ManagedARAHandle (dc, [&] | |||||
{ | |||||
const ARAEditGuard guard (dc); | |||||
return dc.createAudioModification (s.getPluginRef(), hostRef, &props); | |||||
}()), | |||||
source (s) | |||||
{ | |||||
} | |||||
void AudioModification::update (const ARA::ARAAudioModificationProperties& props) | |||||
{ | |||||
const ARAEditGuard guard (getDocumentController()); | |||||
getDocumentController().updateAudioModificationProperties (getPluginRef(), &props); | |||||
} | |||||
void AudioModification::destroy (ARA::Host::DocumentController& dc, Ptr ptr) | |||||
{ | |||||
dc.destroyAudioModification (ptr); | |||||
} | |||||
//============================================================================== | |||||
class PlaybackRegion::Impl : public ManagedARAHandle<Impl, ARA::ARAPlaybackRegionRef>, | |||||
public DeletionListener | |||||
{ | |||||
public: | |||||
Impl (ARA::ARAPlaybackRegionHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
AudioModification& m, | |||||
const ARA::ARAPlaybackRegionProperties& props); | |||||
~Impl() override | |||||
{ | |||||
for (const auto& l : listeners) | |||||
l->removeListener (*this); | |||||
} | |||||
/* Updates the state of the corresponding %ARA model object. | |||||
Places the DocumentController in editable state. | |||||
You can use getEmptyProperties() to acquire a properties struct where the `structSize` | |||||
field has already been correctly set. | |||||
*/ | |||||
void update (const ARA::ARAPlaybackRegionProperties& props); | |||||
auto& getAudioModification() const { return modification; } | |||||
static void destroy (ARA::Host::DocumentController&, Ptr); | |||||
void addListener (DeletionListener& l) { listeners.insert (&l); } | |||||
void removeListener (DeletionListener& l) noexcept override { listeners.erase (&l); } | |||||
private: | |||||
AudioModification* modification = nullptr; | |||||
std::unordered_set<DeletionListener*> listeners; | |||||
}; | |||||
PlaybackRegion::Impl::Impl (ARA::ARAPlaybackRegionHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
AudioModification& m, | |||||
const ARA::ARAPlaybackRegionProperties& props) | |||||
: ManagedARAHandle (dc, [&] | |||||
{ | |||||
const ARAEditGuard guard (dc); | |||||
return dc.createPlaybackRegion (m.getPluginRef(), hostRef, &props); | |||||
}()), | |||||
modification (&m) | |||||
{ | |||||
} | |||||
PlaybackRegion::~PlaybackRegion() = default; | |||||
void PlaybackRegion::Impl::update (const ARA::ARAPlaybackRegionProperties& props) | |||||
{ | |||||
const ARAEditGuard guard (getDocumentController()); | |||||
getDocumentController().updatePlaybackRegionProperties (getPluginRef(), &props); | |||||
} | |||||
void PlaybackRegion::Impl::destroy (ARA::Host::DocumentController& dc, Ptr ptr) | |||||
{ | |||||
dc.destroyPlaybackRegion (ptr); | |||||
} | |||||
PlaybackRegion::PlaybackRegion (ARA::ARAPlaybackRegionHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
AudioModification& m, | |||||
const ARA::ARAPlaybackRegionProperties& props) | |||||
: impl (std::make_unique<Impl> (hostRef, dc, m, props)) | |||||
{ | |||||
} | |||||
void PlaybackRegion::update (const ARA::ARAPlaybackRegionProperties& props) { impl->update (props); } | |||||
void PlaybackRegion::addListener (DeletionListener& x) { impl->addListener (x); } | |||||
auto& PlaybackRegion::getAudioModification() const { return impl->getAudioModification(); } | |||||
ARA::ARAPlaybackRegionRef PlaybackRegion::getPluginRef() const noexcept { return impl->getPluginRef(); } | |||||
DeletionListener& PlaybackRegion::getDeletionListener() const noexcept { return *impl.get(); } | |||||
//============================================================================== | |||||
MusicalContext::MusicalContext (ARA::ARAMusicalContextHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
const ARA::ARAMusicalContextProperties& props) | |||||
: ManagedARAHandle (dc, [&] | |||||
{ | |||||
const ARAEditGuard guard (dc); | |||||
return dc.createMusicalContext (hostRef, &props); | |||||
}()) | |||||
{ | |||||
} | |||||
void MusicalContext::update (const ARA::ARAMusicalContextProperties& props) | |||||
{ | |||||
const ARAEditGuard guard (getDocumentController()); | |||||
return getDocumentController().updateMusicalContextProperties (getPluginRef(), &props); | |||||
} | |||||
void MusicalContext::destroy (ARA::Host::DocumentController& dc, Ptr ptr) | |||||
{ | |||||
dc.destroyMusicalContext (ptr); | |||||
} | |||||
//============================================================================== | |||||
RegionSequence::RegionSequence (ARA::ARARegionSequenceHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
const ARA::ARARegionSequenceProperties& props) | |||||
: ManagedARAHandle (dc, [&] | |||||
{ | |||||
const ARAEditGuard guard (dc); | |||||
return dc.createRegionSequence (hostRef, &props); | |||||
}()) | |||||
{ | |||||
} | |||||
void RegionSequence::update (const ARA::ARARegionSequenceProperties& props) | |||||
{ | |||||
const ARAEditGuard guard (getDocumentController()); | |||||
return getDocumentController().updateRegionSequenceProperties (getPluginRef(), &props); | |||||
} | |||||
void RegionSequence::destroy (ARA::Host::DocumentController& dc, Ptr ptr) | |||||
{ | |||||
dc.destroyRegionSequence (ptr); | |||||
} | |||||
//============================================================================== | |||||
PlaybackRendererInterface PlugInExtensionInstance::getPlaybackRendererInterface() const | |||||
{ | |||||
if (instance != nullptr) | |||||
return PlaybackRendererInterface (instance->playbackRendererRef, instance->playbackRendererInterface); | |||||
return {}; | |||||
} | |||||
EditorRendererInterface PlugInExtensionInstance::getEditorRendererInterface() const | |||||
{ | |||||
if (instance != nullptr) | |||||
return EditorRendererInterface (instance->editorRendererRef, instance->editorRendererInterface); | |||||
return {}; | |||||
} | |||||
} // namespace ARAHostModel | |||||
//============================================================================== | |||||
class ARAHostDocumentController::Impl | |||||
{ | |||||
public: | |||||
Impl (ARAFactoryWrapper araFactoryIn, | |||||
std::unique_ptr<ARA::Host::DocumentControllerHostInstance>&& dcHostInstanceIn, | |||||
const ARA::ARADocumentControllerInstance* documentControllerInstance) | |||||
: araFactory (std::move (araFactoryIn)), | |||||
dcHostInstance (std::move (dcHostInstanceIn)), | |||||
documentController (documentControllerInstance) | |||||
{ | |||||
} | |||||
~Impl() | |||||
{ | |||||
documentController.destroyDocumentController(); | |||||
} | |||||
static std::unique_ptr<Impl> | |||||
createImpl (ARAFactoryWrapper araFactory, | |||||
const String& documentName, | |||||
std::unique_ptr<ARA::Host::AudioAccessControllerInterface>&& audioAccessController, | |||||
std::unique_ptr<ARA::Host::ArchivingControllerInterface>&& archivingController, | |||||
std::unique_ptr<ARA::Host::ContentAccessControllerInterface>&& contentAccessController, | |||||
std::unique_ptr<ARA::Host::ModelUpdateControllerInterface>&& modelUpdateController, | |||||
std::unique_ptr<ARA::Host::PlaybackControllerInterface>&& playbackController) | |||||
{ | |||||
std::unique_ptr<ARA::Host::DocumentControllerHostInstance> dcHostInstance = | |||||
std::make_unique<ARA::Host::DocumentControllerHostInstance> (audioAccessController.release(), | |||||
archivingController.release(), | |||||
contentAccessController.release(), | |||||
modelUpdateController.release(), | |||||
playbackController.release()); | |||||
const auto documentProperties = makeARASizedStruct (&ARA::ARADocumentProperties::name, documentName.toRawUTF8()); | |||||
if (auto* dci = araFactory.get()->createDocumentControllerWithDocument (dcHostInstance.get(), &documentProperties)) | |||||
return std::make_unique<Impl> (std::move (araFactory), std::move (dcHostInstance), dci); | |||||
return {}; | |||||
} | |||||
ARAHostModel::PlugInExtensionInstance bindDocumentToPluginInstance (AudioPluginInstance& instance, | |||||
ARA::ARAPlugInInstanceRoleFlags knownRoles, | |||||
ARA::ARAPlugInInstanceRoleFlags assignedRoles) | |||||
{ | |||||
const auto makeVisitor = [] (auto vst3Fn, auto auFn) | |||||
{ | |||||
using Vst3Fn = decltype (vst3Fn); | |||||
using AuFn = decltype (auFn); | |||||
struct Visitor : ExtensionsVisitor, Vst3Fn, AuFn | |||||
{ | |||||
explicit Visitor (Vst3Fn vst3Fn, AuFn auFn) : Vst3Fn (std::move (vst3Fn)), AuFn (std::move (auFn)) {} | |||||
void visitVST3Client (const VST3Client& x) override { Vst3Fn::operator() (x); } | |||||
void visitAudioUnitClient (const AudioUnitClient& x) override { AuFn::operator() (x); } | |||||
}; | |||||
return Visitor { std::move (vst3Fn), std::move (auFn) }; | |||||
}; | |||||
const ARA::ARAPlugInExtensionInstance* pei = nullptr; | |||||
auto visitor = makeVisitor ([this, &pei, knownRoles, assignedRoles] (const ExtensionsVisitor::VST3Client& vst3Client) | |||||
{ | |||||
auto* iComponentPtr = vst3Client.getIComponentPtr(); | |||||
VSTComSmartPtr<ARA::IPlugInEntryPoint2> araEntryPoint; | |||||
if (araEntryPoint.loadFrom (iComponentPtr)) | |||||
pei = araEntryPoint->bindToDocumentControllerWithRoles (documentController.getRef(), knownRoles, assignedRoles); | |||||
}, | |||||
#if JUCE_PLUGINHOST_AU && JUCE_MAC | |||||
[this, &pei, knownRoles, assignedRoles] (const ExtensionsVisitor::AudioUnitClient& auClient) | |||||
{ | |||||
auto audioUnit = auClient.getAudioUnitHandle(); | |||||
auto propertySize = (UInt32) sizeof (ARA::ARAAudioUnitPlugInExtensionBinding); | |||||
const auto expectedPropertySize = propertySize; | |||||
ARA::ARAAudioUnitPlugInExtensionBinding audioUnitBinding { ARA::kARAAudioUnitMagic, | |||||
documentController.getRef(), | |||||
nullptr, | |||||
knownRoles, | |||||
assignedRoles }; | |||||
auto status = AudioUnitGetProperty (audioUnit, | |||||
ARA::kAudioUnitProperty_ARAPlugInExtensionBindingWithRoles, | |||||
kAudioUnitScope_Global, | |||||
0, | |||||
&audioUnitBinding, | |||||
&propertySize); | |||||
if (status == noErr | |||||
&& propertySize == expectedPropertySize | |||||
&& audioUnitBinding.inOutMagicNumber == ARA::kARAAudioUnitMagic | |||||
&& audioUnitBinding.inDocumentControllerRef == documentController.getRef() | |||||
&& audioUnitBinding.outPlugInExtension != nullptr) | |||||
{ | |||||
pei = audioUnitBinding.outPlugInExtension; | |||||
} | |||||
else | |||||
jassertfalse; | |||||
} | |||||
#else | |||||
[] (const auto&) {} | |||||
#endif | |||||
); | |||||
instance.getExtensions (visitor); | |||||
return ARAHostModel::PlugInExtensionInstance { pei }; | |||||
} | |||||
auto& getDocumentController() { return documentController; } | |||||
private: | |||||
ARAFactoryWrapper araFactory; | |||||
std::unique_ptr<ARA::Host::DocumentControllerHostInstance> dcHostInstance; | |||||
ARA::Host::DocumentController documentController; | |||||
}; | |||||
ARAHostDocumentController::ARAHostDocumentController (std::unique_ptr<Impl>&& implIn) | |||||
: impl { std::move (implIn) } | |||||
{} | |||||
std::unique_ptr<ARAHostDocumentController> ARAHostDocumentController::create (ARAFactoryWrapper factory, | |||||
const String& documentName, | |||||
std::unique_ptr<ARA::Host::AudioAccessControllerInterface> audioAccessController, | |||||
std::unique_ptr<ARA::Host::ArchivingControllerInterface> archivingController, | |||||
std::unique_ptr<ARA::Host::ContentAccessControllerInterface> contentAccessController, | |||||
std::unique_ptr<ARA::Host::ModelUpdateControllerInterface> modelUpdateController, | |||||
std::unique_ptr<ARA::Host::PlaybackControllerInterface> playbackController) | |||||
{ | |||||
if (auto impl = Impl::createImpl (std::move (factory), | |||||
documentName, | |||||
std::move (audioAccessController), | |||||
std::move (archivingController), | |||||
std::move (contentAccessController), | |||||
std::move (modelUpdateController), | |||||
std::move (playbackController))) | |||||
{ | |||||
return rawToUniquePtr (new ARAHostDocumentController (std::move (impl))); | |||||
} | |||||
return {}; | |||||
} | |||||
ARAHostDocumentController::~ARAHostDocumentController() = default; | |||||
ARA::Host::DocumentController& ARAHostDocumentController::getDocumentController() const | |||||
{ | |||||
return impl->getDocumentController(); | |||||
} | |||||
ARAHostModel::PlugInExtensionInstance ARAHostDocumentController::bindDocumentToPluginInstance (AudioPluginInstance& instance, | |||||
ARA::ARAPlugInInstanceRoleFlags knownRoles, | |||||
ARA::ARAPlugInInstanceRoleFlags assignedRoles) | |||||
{ | |||||
return impl->bindDocumentToPluginInstance (instance, knownRoles, assignedRoles); | |||||
} | |||||
void createARAFactoryAsync (AudioPluginInstance& instance, std::function<void (ARAFactoryWrapper)> cb) | |||||
{ | |||||
if (! instance.getPluginDescription().hasARAExtension) | |||||
cb (ARAFactoryWrapper{}); | |||||
struct Extensions : public ExtensionsVisitor | |||||
{ | |||||
Extensions (std::function<void (ARAFactoryWrapper)> callbackIn) | |||||
: callback (std::move (callbackIn)) | |||||
{} | |||||
void visitARAClient (const ARAClient& araClient) override | |||||
{ | |||||
araClient.createARAFactoryAsync (std::move (callback)); | |||||
} | |||||
std::function<void (ARAFactoryWrapper)> callback; | |||||
}; | |||||
Extensions extensions { std::move(cb) }; | |||||
instance.getExtensions (extensions); | |||||
} | |||||
} // namespace juce | |||||
#endif |
@@ -0,0 +1,740 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#pragma once | |||||
#if (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU) && (JUCE_MAC || JUCE_WINDOWS)) || DOXYGEN | |||||
// Include ARA SDK headers | |||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments") | |||||
#include <ARA_API/ARAInterface.h> | |||||
#include <ARA_Library/Dispatch/ARAHostDispatch.h> | |||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE | |||||
//============================================================================== | |||||
namespace juce | |||||
{ | |||||
/** Reference counting helper class to ensure that the DocumentController is in editable state. | |||||
When adding, removing or modifying %ARA model objects the enclosing DocumentController must be | |||||
in editable state. | |||||
You can achieve this by using the %ARA Library calls | |||||
ARA::Host::DocumentController::beginEditing() and ARA::Host::DocumentController::endEditing(). | |||||
However, putting the DocumentController in and out of editable state is a potentially costly | |||||
operation, thus it makes sense to group multiple modifications together and change the editable | |||||
state only once. | |||||
ARAEditGuard keeps track of all scopes that want to edit a particular DocumentController and | |||||
will trigger beginEditing() and endEditing() only for the outermost scope. This allows you to | |||||
merge multiple editing operations into one by putting ARAEditGuard in their enclosing scope. | |||||
@tags{ARA} | |||||
*/ | |||||
class ARAEditGuard | |||||
{ | |||||
public: | |||||
explicit ARAEditGuard (ARA::Host::DocumentController& dcIn); | |||||
~ARAEditGuard(); | |||||
private: | |||||
ARA::Host::DocumentController& dc; | |||||
}; | |||||
namespace ARAHostModel | |||||
{ | |||||
//============================================================================== | |||||
/** Allows converting, without warnings, between pointers of two unrelated types. | |||||
This is a bit like ARA_MAP_HOST_REF, but not macro-based. | |||||
To use it, add a line like this to a type that needs to deal in host references: | |||||
@code | |||||
using Converter = ConversionFunctions<ThisType*, ARAHostRef>; | |||||
@endcode | |||||
Now, you can convert back and forth with host references by calling | |||||
Converter::toHostRef() and Converter::fromHostRef(). | |||||
@tags{ARA} | |||||
*/ | |||||
template <typename A, typename B> | |||||
struct ConversionFunctions | |||||
{ | |||||
static_assert (sizeof (A) <= sizeof (B), | |||||
"It is only possible to convert between types of the same size"); | |||||
static B toHostRef (A value) | |||||
{ | |||||
return readUnaligned<B> (&value); | |||||
} | |||||
static A fromHostRef (B value) | |||||
{ | |||||
return readUnaligned<A> (&value); | |||||
} | |||||
}; | |||||
//============================================================================== | |||||
template <typename Base, typename PtrIn> | |||||
class ManagedARAHandle | |||||
{ | |||||
public: | |||||
using Ptr = PtrIn; | |||||
ManagedARAHandle (ARA::Host::DocumentController& dc, Ptr ptr) noexcept | |||||
: handle (ptr, Deleter { dc }) {} | |||||
auto& getDocumentController() const { return handle.get_deleter().documentController; } | |||||
Ptr getPluginRef() const { return handle.get(); } | |||||
private: | |||||
struct Deleter | |||||
{ | |||||
void operator() (Ptr ptr) const noexcept | |||||
{ | |||||
const ARAEditGuard guard (documentController); | |||||
Base::destroy (documentController, ptr); | |||||
} | |||||
ARA::Host::DocumentController& documentController; | |||||
}; | |||||
std::unique_ptr<std::remove_pointer_t<Ptr>, Deleter> handle; | |||||
}; | |||||
//============================================================================== | |||||
/** Helper class for the host side implementation of the %ARA %AudioSource model object. | |||||
Its intended use is to add a member variable of this type to your host side %AudioSource | |||||
implementation. Then it provides a RAII approach to managing the lifetime of the corresponding | |||||
objects created inside the DocumentController. When the host side object is instantiated an ARA | |||||
model object is also created in the DocumentController. When the host side object is deleted it | |||||
will be removed from the DocumentController as well. | |||||
The class will automatically put the DocumentController into editable state for operations that | |||||
mandate this e.g. creation, deletion or updating. | |||||
You can encapsulate multiple such operations into a scope with an ARAEditGuard in order to invoke | |||||
the editable state of the DocumentController only once. | |||||
@tags{ARA} | |||||
*/ | |||||
class AudioSource : public ManagedARAHandle<AudioSource, ARA::ARAAudioSourceRef> | |||||
{ | |||||
public: | |||||
/** Returns an %ARA versioned struct with the `structSize` correctly set for the currently | |||||
used SDK version. | |||||
You should leave `structSize` unchanged, and fill out the rest of the fields appropriately | |||||
for the host implementation of the %ARA model object. | |||||
*/ | |||||
static constexpr auto getEmptyProperties() { return makeARASizedStruct (&ARA::ARAAudioSourceProperties::merits64BitSamples); } | |||||
/** Creates an AudioSource object. During construction it registers an %ARA %AudioSource model | |||||
object with the DocumentController that refers to the provided hostRef. When this object | |||||
is deleted the corresponding DocumentController model object will also be deregistered. | |||||
You can acquire a correctly versioned `ARA::ARAAudioSourceProperties` struct by calling | |||||
getEmptyProperties(). | |||||
Places the DocumentController in editable state. | |||||
@see ARAEditGuard | |||||
*/ | |||||
AudioSource (ARA::ARAAudioSourceHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
const ARA::ARAAudioSourceProperties& props); | |||||
/** Destructor. Temporarily places the DocumentController in an editable state. */ | |||||
~AudioSource() = default; | |||||
/** Updates the state of the corresponding %ARA model object. | |||||
Places the DocumentController in editable state. | |||||
You can use getEmptyProperties() to acquire a properties struct where the `structSize` | |||||
field has already been correctly set. | |||||
*/ | |||||
void update (const ARA::ARAAudioSourceProperties& props); | |||||
/** Changes the plugin's access to the %AudioSource samples through the DocumentController. | |||||
Places the DocumentController in editable state. | |||||
*/ | |||||
void enableAudioSourceSamplesAccess (bool); | |||||
/** Called by ManagedARAHandle to deregister the model object during the destruction of | |||||
AudioSource. | |||||
You shouldn't call this function manually. | |||||
*/ | |||||
static void destroy (ARA::Host::DocumentController&, Ptr); | |||||
}; | |||||
/** Helper class for the host side implementation of the %ARA %AudioModification model object. | |||||
Its intended use is to add a member variable of this type to your host side %AudioModification | |||||
implementation. Then it provides a RAII approach to managing the lifetime of the corresponding | |||||
objects created inside the DocumentController. When the host side object is instantiated an ARA | |||||
model object is also created in the DocumentController. When the host side object is deleted it | |||||
will be removed from the DocumentController as well. | |||||
The class will automatically put the DocumentController into editable state for operations that | |||||
mandate this e.g. creation, deletion or updating. | |||||
You can encapsulate multiple such operations into a scope with an ARAEditGuard in order to invoke | |||||
the editable state of the DocumentController only once. | |||||
@tags{ARA} | |||||
*/ | |||||
class AudioModification : public ManagedARAHandle<AudioModification, ARA::ARAAudioModificationRef> | |||||
{ | |||||
public: | |||||
/** Returns an %ARA versioned struct with the `structSize` correctly set for the currently | |||||
used SDK version. | |||||
You should leave `structSize` unchanged, and fill out the rest of the fields appropriately | |||||
for the host implementation of the %ARA model object. | |||||
*/ | |||||
static constexpr auto getEmptyProperties() | |||||
{ | |||||
return makeARASizedStruct (&ARA::ARAAudioModificationProperties::persistentID); | |||||
} | |||||
/** Creates an AudioModification object. During construction it registers an %ARA %AudioModification model | |||||
object with the DocumentController that refers to the provided hostRef. When this object | |||||
is deleted the corresponding DocumentController model object will also be deregistered. | |||||
You can acquire a correctly versioned `ARA::ARAAudioModificationProperties` struct by calling | |||||
getEmptyProperties(). | |||||
Places the DocumentController in editable state. | |||||
@see ARAEditGuard | |||||
*/ | |||||
AudioModification (ARA::ARAAudioModificationHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
AudioSource& s, | |||||
const ARA::ARAAudioModificationProperties& props); | |||||
/** Updates the state of the corresponding %ARA model object. | |||||
Places the DocumentController in editable state. | |||||
You can use getEmptyProperties() to acquire a properties struct where the `structSize` | |||||
field has already been correctly set. | |||||
*/ | |||||
void update (const ARA::ARAAudioModificationProperties& props); | |||||
/** Returns the AudioSource containing this AudioModification. */ | |||||
auto& getAudioSource() const { return source; } | |||||
/** Called by ManagedARAHandle to deregister the model object during the destruction of | |||||
AudioModification. | |||||
You shouldn't call this function manually. | |||||
*/ | |||||
static void destroy (ARA::Host::DocumentController&, Ptr); | |||||
private: | |||||
AudioSource& source; | |||||
}; | |||||
struct DeletionListener | |||||
{ | |||||
virtual ~DeletionListener() = default; | |||||
virtual void removeListener (DeletionListener& other) noexcept = 0; | |||||
}; | |||||
struct PlaybackRegion | |||||
{ | |||||
public: | |||||
/** Returns an %ARA versioned struct with the `structSize` correctly set for the currently | |||||
used SDK version. | |||||
You should leave `structSize` unchanged, and fill out the rest of the fields appropriately | |||||
for the host implementation of the %ARA model object. | |||||
*/ | |||||
static constexpr auto getEmptyProperties() | |||||
{ | |||||
return makeARASizedStruct (&ARA::ARAPlaybackRegionProperties::color); | |||||
} | |||||
PlaybackRegion (ARA::ARAPlaybackRegionHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
AudioModification& m, | |||||
const ARA::ARAPlaybackRegionProperties& props); | |||||
~PlaybackRegion(); | |||||
/** Updates the state of the corresponding %ARA model object. | |||||
Places the DocumentController in editable state. | |||||
You can use getEmptyProperties() to acquire a properties struct where the `structSize` | |||||
field has already been correctly set. | |||||
*/ | |||||
void update (const ARA::ARAPlaybackRegionProperties& props); | |||||
/** Adds a DeletionListener object that will be notified when the PlaybackRegion object | |||||
is deleted. | |||||
Used by the PlaybackRegionRegistry. | |||||
@see PlaybackRendererInterface, EditorRendererInterface | |||||
*/ | |||||
void addListener (DeletionListener& x); | |||||
/** Returns the AudioModification containing this PlaybackRegion. */ | |||||
auto& getAudioModification() const; | |||||
/** Returns the plugin side reference to the PlaybackRegion */ | |||||
ARA::ARAPlaybackRegionRef getPluginRef() const noexcept; | |||||
DeletionListener& getDeletionListener() const noexcept; | |||||
private: | |||||
class Impl; | |||||
std::unique_ptr<Impl> impl; | |||||
}; | |||||
/** Helper class for the host side implementation of the %ARA %MusicalContext model object. | |||||
Its intended use is to add a member variable of this type to your host side %MusicalContext | |||||
implementation. Then it provides a RAII approach to managing the lifetime of the corresponding | |||||
objects created inside the DocumentController. When the host side object is instantiated an ARA | |||||
model object is also created in the DocumentController. When the host side object is deleted it | |||||
will be removed from the DocumentController as well. | |||||
The class will automatically put the DocumentController into editable state for operations that | |||||
mandate this e.g. creation, deletion or updating. | |||||
You can encapsulate multiple such operations into a scope with an ARAEditGuard in order to invoke | |||||
the editable state of the DocumentController only once. | |||||
@tags{ARA} | |||||
*/ | |||||
class MusicalContext : public ManagedARAHandle<MusicalContext, ARA::ARAMusicalContextRef> | |||||
{ | |||||
public: | |||||
/** Returns an %ARA versioned struct with the `structSize` correctly set for the currently | |||||
used SDK version. | |||||
You should leave `structSize` unchanged, and fill out the rest of the fields appropriately | |||||
for the host implementation of the %ARA model object. | |||||
*/ | |||||
static constexpr auto getEmptyProperties() | |||||
{ | |||||
return makeARASizedStruct (&ARA::ARAMusicalContextProperties::color); | |||||
} | |||||
/** Creates a MusicalContext object. During construction it registers an %ARA %MusicalContext model | |||||
object with the DocumentController that refers to the provided hostRef. When this object | |||||
is deleted the corresponding DocumentController model object will also be deregistered. | |||||
You can acquire a correctly versioned `ARA::ARAMusicalContextProperties` struct by calling | |||||
getEmptyProperties(). | |||||
Places the DocumentController in editable state. | |||||
@see ARAEditGuard | |||||
*/ | |||||
MusicalContext (ARA::ARAMusicalContextHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
const ARA::ARAMusicalContextProperties& props); | |||||
/** Updates the state of the corresponding %ARA model object. | |||||
Places the DocumentController in editable state. | |||||
You can use getEmptyProperties() to acquire a properties struct where the `structSize` | |||||
field has already been correctly set. | |||||
*/ | |||||
void update (const ARA::ARAMusicalContextProperties& props); | |||||
/** Called by ManagedARAHandle to deregister the model object during the destruction of | |||||
AudioModification. | |||||
You shouldn't call this function manually. | |||||
*/ | |||||
static void destroy (ARA::Host::DocumentController&, Ptr); | |||||
}; | |||||
/** Helper class for the host side implementation of the %ARA %RegionSequence model object. | |||||
Its intended use is to add a member variable of this type to your host side %RegionSequence | |||||
implementation. Then it provides a RAII approach to managing the lifetime of the corresponding | |||||
objects created inside the DocumentController. When the host side object is instantiated an ARA | |||||
model object is also created in the DocumentController. When the host side object is deleted it | |||||
will be removed from the DocumentController as well. | |||||
The class will automatically put the DocumentController into editable state for operations that | |||||
mandate this e.g. creation, deletion or updating. | |||||
You can encapsulate multiple such operations into a scope with an ARAEditGuard in order to invoke | |||||
the editable state of the DocumentController only once. | |||||
@tags{ARA} | |||||
*/ | |||||
class RegionSequence : public ManagedARAHandle<RegionSequence, ARA::ARARegionSequenceRef> | |||||
{ | |||||
public: | |||||
/** Returns an %ARA versioned struct with the `structSize` correctly set for the currently | |||||
used SDK version. | |||||
You should leave `structSize` unchanged, and fill out the rest of the fields appropriately | |||||
for the host implementation of the %ARA model object. | |||||
*/ | |||||
static constexpr auto getEmptyProperties() | |||||
{ | |||||
return makeARASizedStruct (&ARA::ARARegionSequenceProperties::color); | |||||
} | |||||
/** Creates a RegionSequence object. During construction it registers an %ARA %RegionSequence model | |||||
object with the DocumentController that refers to the provided hostRef. When this object | |||||
is deleted the corresponding DocumentController model object will also be deregistered. | |||||
You can acquire a correctly versioned `ARA::ARARegionSequenceProperties` struct by calling | |||||
getEmptyProperties(). | |||||
Places the DocumentController in editable state. | |||||
@see ARAEditGuard | |||||
*/ | |||||
RegionSequence (ARA::ARARegionSequenceHostRef hostRef, | |||||
ARA::Host::DocumentController& dc, | |||||
const ARA::ARARegionSequenceProperties& props); | |||||
/** Updates the state of the corresponding %ARA model object. | |||||
Places the DocumentController in editable state. | |||||
You can use getEmptyProperties() to acquire a properties struct where the `structSize` | |||||
field has already been correctly set. | |||||
*/ | |||||
void update (const ARA::ARARegionSequenceProperties& props); | |||||
/** Called by ManagedARAHandle to deregister the model object during the destruction of | |||||
AudioModification. | |||||
You shouldn't call this function manually. | |||||
*/ | |||||
static void destroy (ARA::Host::DocumentController&, Ptr); | |||||
}; | |||||
//============================================================================== | |||||
/** Base class used by the ::PlaybackRendererInterface and ::EditorRendererInterface | |||||
plugin extension interfaces. | |||||
Hosts will want to create one or typically more %ARA plugin extension instances per plugin for | |||||
the purpose of playback and editor rendering. The PlaybackRegions created by the host then have | |||||
to be assigned to these instances through the appropriate interfaces. | |||||
Whether a PlaybackRegion or an assigned RendererInterface is deleted first depends on the host | |||||
implementation and exact use case. | |||||
By using these helper classes you can ensure that the %ARA DocumentController remains in a | |||||
valid state in both situations. In order to use them acquire an object from | |||||
PlugInExtensionInstance::getPlaybackRendererInterface() or | |||||
PlugInExtensionInstance::getEditorRendererInterface(). | |||||
Then call add() to register a PlaybackRegion with that particular PlugInExtensionInstance's | |||||
interface. | |||||
Now when you delete that PlaybackRegion it will be deregistered from that extension instance. | |||||
If however you want to delete the plugin extension instance before the PlaybackRegion, you can | |||||
delete the PlaybackRegionRegistry instance before deleting the plugin extension instance, which | |||||
takes care of deregistering all PlaybackRegions. | |||||
When adding or removing PlaybackRegions the plugin instance must be in an unprepared state i.e. | |||||
before AudioProcessor::prepareToPlay() or after AudioProcessor::releaseResources(). | |||||
@code | |||||
auto playbackRenderer = std::make_unique<PlaybackRendererInterface> (plugInExtensionInstance.getPlaybackRendererInterface()); | |||||
auto playbackRegion = std::make_unique<PlaybackRegion> (documentController, regionSequence, audioModification, audioSource); | |||||
// Either of the following three code variations are valid | |||||
// (1) =================================================== | |||||
playbackRenderer.add (playbackRegion); | |||||
playbackRenderer.remove (playbackRegion); | |||||
// (2) =================================================== | |||||
playbackRenderer.add (playbackRegion); | |||||
playbackRegion.reset(); | |||||
// (3) =================================================== | |||||
playbackRenderer.add (playbackRegion); | |||||
playbackRenderer.reset(); | |||||
@endcode | |||||
@see PluginExtensionInstance | |||||
@tags{ARA} | |||||
*/ | |||||
template <typename RendererRef, typename Interface> | |||||
class PlaybackRegionRegistry | |||||
{ | |||||
public: | |||||
PlaybackRegionRegistry() = default; | |||||
PlaybackRegionRegistry (RendererRef rendererRefIn, const Interface* interfaceIn) | |||||
: registry (std::make_unique<Registry> (rendererRefIn, interfaceIn)) | |||||
{ | |||||
} | |||||
/** Adds a PlaybackRegion to the corresponding ::PlaybackRendererInterface or ::EditorRendererInterface. | |||||
The plugin instance must be in an unprepared state i.e. before AudioProcessor::prepareToPlay() or | |||||
after AudioProcessor::releaseResources(). | |||||
*/ | |||||
void add (PlaybackRegion& region) { registry->add (region); } | |||||
/** Removes a PlaybackRegion from the corresponding ::PlaybackRendererInterface or ::EditorRendererInterface. | |||||
The plugin instance must be in an unprepared state i.e. before AudioProcessor::prepareToPlay() or | |||||
after AudioProcessor::releaseResources(). | |||||
*/ | |||||
void remove (PlaybackRegion& region) { registry->remove (region); } | |||||
/** Returns true if the underlying %ARA plugin extension instance fulfills the corresponding role. */ | |||||
bool isValid() { return registry->isValid(); } | |||||
private: | |||||
class Registry : private DeletionListener | |||||
{ | |||||
public: | |||||
Registry (RendererRef rendererRefIn, const Interface* interfaceIn) | |||||
: rendererRef (rendererRefIn), rendererInterface (interfaceIn) | |||||
{ | |||||
} | |||||
Registry (const Registry&) = delete; | |||||
Registry (Registry&&) noexcept = delete; | |||||
Registry& operator= (const Registry&) = delete; | |||||
Registry& operator= (Registry&&) noexcept = delete; | |||||
~Registry() override | |||||
{ | |||||
for (const auto& region : regions) | |||||
doRemoveListener (*region.first); | |||||
} | |||||
bool isValid() { return rendererRef != nullptr && rendererInterface != nullptr; } | |||||
void add (PlaybackRegion& region) | |||||
{ | |||||
if (isValid()) | |||||
rendererInterface->addPlaybackRegion (rendererRef, region.getPluginRef()); | |||||
regions.emplace (®ion.getDeletionListener(), region.getPluginRef()); | |||||
region.addListener (*this); | |||||
} | |||||
void remove (PlaybackRegion& region) | |||||
{ | |||||
doRemoveListener (region.getDeletionListener()); | |||||
} | |||||
private: | |||||
void doRemoveListener (DeletionListener& listener) noexcept | |||||
{ | |||||
listener.removeListener (*this); | |||||
removeListener (listener); | |||||
} | |||||
void removeListener (DeletionListener& listener) noexcept override | |||||
{ | |||||
const auto it = regions.find (&listener); | |||||
if (it == regions.end()) | |||||
{ | |||||
jassertfalse; | |||||
return; | |||||
} | |||||
if (isValid()) | |||||
rendererInterface->removePlaybackRegion (rendererRef, it->second); | |||||
regions.erase (it); | |||||
} | |||||
RendererRef rendererRef = nullptr; | |||||
const Interface* rendererInterface = nullptr; | |||||
std::map<DeletionListener*, ARA::ARAPlaybackRegionRef> regions; | |||||
}; | |||||
std::unique_ptr<Registry> registry; | |||||
}; | |||||
//============================================================================== | |||||
/** Helper class for managing the lifetimes of %ARA plugin extension instances and PlaybackRegions. | |||||
You can read more about its usage at PlaybackRegionRegistry. | |||||
@see PlaybackRegion, PlaybackRegionRegistry | |||||
@tags{ARA} | |||||
*/ | |||||
using PlaybackRendererInterface = PlaybackRegionRegistry<ARA::ARAPlaybackRendererRef, ARA::ARAPlaybackRendererInterface>; | |||||
//============================================================================== | |||||
/** Helper class for managing the lifetimes of %ARA plugin extension instances and PlaybackRegions. | |||||
You can read more about its usage at PlaybackRegionRegistry. | |||||
@see PlaybackRegion, PlaybackRegionRegistry | |||||
@tags{ARA} | |||||
*/ | |||||
using EditorRendererInterface = PlaybackRegionRegistry<ARA::ARAEditorRendererRef, ARA::ARAEditorRendererInterface>; | |||||
//============================================================================== | |||||
/** Wrapper class for `ARA::ARAPlugInExtensionInstance*`. | |||||
Returned by ARAHostDocumentController::bindDocumentToPluginInstance(). The corresponding | |||||
ARAHostDocumentController must remain valid as long as the plugin extension is in use. | |||||
*/ | |||||
class PlugInExtensionInstance final | |||||
{ | |||||
public: | |||||
/** Creates an empty PlugInExtensionInstance object. | |||||
Calling isValid() on such an object will return false. | |||||
*/ | |||||
PlugInExtensionInstance() = default; | |||||
/** Creates a PlugInExtensionInstance object that wraps a `const ARA::ARAPlugInExtensionInstance*`. | |||||
The intended way to obtain a PlugInExtensionInstance object is to call | |||||
ARAHostDocumentController::bindDocumentToPluginInstance(), which is using this constructor. | |||||
*/ | |||||
explicit PlugInExtensionInstance (const ARA::ARAPlugInExtensionInstance* instanceIn) | |||||
: instance (instanceIn) | |||||
{ | |||||
} | |||||
/** Returns the PlaybackRendererInterface for the extension instance. | |||||
Depending on what roles were passed into | |||||
ARAHostDocumentController::bindDocumentToPluginInstance() one particular instance may not | |||||
fulfill a given role. You can use PlaybackRendererInterface::isValid() to see if this | |||||
interface was provided by the instance. | |||||
*/ | |||||
PlaybackRendererInterface getPlaybackRendererInterface() const; | |||||
/** Returns the EditorRendererInterface for the extension instance. | |||||
Depending on what roles were passed into | |||||
ARAHostDocumentController::bindDocumentToPluginInstance() one particular instance may not | |||||
fulfill a given role. You can use EditorRendererInterface::isValid() to see if this | |||||
interface was provided by the instance. | |||||
*/ | |||||
EditorRendererInterface getEditorRendererInterface() const; | |||||
/** Returns false if the PlugInExtensionInstance was default constructed and represents | |||||
no binding to an ARAHostDocumentController. | |||||
*/ | |||||
bool isValid() const noexcept { return instance != nullptr; } | |||||
private: | |||||
const ARA::ARAPlugInExtensionInstance* instance = nullptr; | |||||
}; | |||||
} // namespace ARAHostModel | |||||
//============================================================================== | |||||
/** Wrapper class for `ARA::Host::DocumentController`. | |||||
In order to create an ARAHostDocumentController from an ARAFactoryWrapper you must | |||||
provide at least two mandatory host side interfaces. You can create these implementations | |||||
by inheriting from the base classes in the `ARA::Host` namespace. | |||||
@tags{ARA} | |||||
*/ | |||||
class ARAHostDocumentController final | |||||
{ | |||||
public: | |||||
/** Factory function. | |||||
You must check if the returned pointer is valid. | |||||
*/ | |||||
static std::unique_ptr<ARAHostDocumentController> | |||||
create (ARAFactoryWrapper factory, | |||||
const String& documentName, | |||||
std::unique_ptr<ARA::Host::AudioAccessControllerInterface> audioAccessController, | |||||
std::unique_ptr<ARA::Host::ArchivingControllerInterface> archivingController, | |||||
std::unique_ptr<ARA::Host::ContentAccessControllerInterface> contentAccessController = nullptr, | |||||
std::unique_ptr<ARA::Host::ModelUpdateControllerInterface> modelUpdateController = nullptr, | |||||
std::unique_ptr<ARA::Host::PlaybackControllerInterface> playbackController = nullptr); | |||||
~ARAHostDocumentController(); | |||||
/** Returns the underlying ARA::Host::DocumentController reference. */ | |||||
ARA::Host::DocumentController& getDocumentController() const; | |||||
/** Binds the ARAHostDocumentController and its enclosed document to a plugin instance. | |||||
The resulting ARAHostModel::PlugInExtensionInstance is responsible for fulfilling the | |||||
ARA specific roles of the plugin. | |||||
A single DocumentController can be bound to multiple plugin instances, which is a typical | |||||
practice among hosts. | |||||
*/ | |||||
ARAHostModel::PlugInExtensionInstance bindDocumentToPluginInstance (AudioPluginInstance& instance, | |||||
ARA::ARAPlugInInstanceRoleFlags knownRoles, | |||||
ARA::ARAPlugInInstanceRoleFlags assignedRoles); | |||||
private: | |||||
class Impl; | |||||
std::unique_ptr<Impl> impl; | |||||
explicit ARAHostDocumentController (std::unique_ptr<Impl>&& implIn); | |||||
}; | |||||
/** Calls the provided callback with an ARAFactoryWrapper object obtained from the provided | |||||
AudioPluginInstance. | |||||
If the provided AudioPluginInstance has no ARA extensions, the callback will be called with an | |||||
ARAFactoryWrapper that wraps a nullptr. | |||||
The object passed to the callback must be checked even if the plugin instance reports having | |||||
ARA extensions. | |||||
*/ | |||||
void createARAFactoryAsync (AudioPluginInstance& instance, std::function<void (ARAFactoryWrapper)> cb); | |||||
} // namespace juce | |||||
//============================================================================== | |||||
#undef ARA_REF | |||||
#undef ARA_HOST_REF | |||||
#endif |
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -47,6 +54,7 @@ public: | |||||
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override; | StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override; | ||||
bool doesPluginStillExist (const PluginDescription&) override; | bool doesPluginStillExist (const PluginDescription&) override; | ||||
FileSearchPath getDefaultLocationsToSearch() override; | FileSearchPath getDefaultLocationsToSearch() override; | ||||
void createARAFactoryAsync (const PluginDescription&, ARAFactoryCreationCallback callback) override; | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -24,14 +31,15 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations") | |||||
#include <AudioUnit/AUCocoaUIView.h> | #include <AudioUnit/AUCocoaUIView.h> | ||||
#include <CoreAudioKit/AUGenericView.h> | #include <CoreAudioKit/AUGenericView.h> | ||||
#include <AudioToolbox/AudioUnitUtilities.h> | #include <AudioToolbox/AudioUnitUtilities.h> | ||||
#endif | |||||
#include <CoreMIDI/MIDIServices.h> | |||||
#if JUCE_PLUGINHOST_ARA | |||||
#include <ARA_API/ARAAudioUnit.h> | |||||
#endif | |||||
#if JUCE_SUPPORT_CARBON | |||||
#include <AudioUnit/AudioUnitCarbonView.h> | |||||
#endif | #endif | ||||
#include <CoreMIDI/MIDIServices.h> | |||||
#include <CoreAudioKit/AUViewController.h> | #include <CoreAudioKit/AUViewController.h> | ||||
#include <juce_audio_basics/native/juce_mac_CoreAudioTimeConversions.h> | #include <juce_audio_basics/native/juce_mac_CoreAudioTimeConversions.h> | ||||
@@ -426,8 +434,198 @@ namespace AudioUnitFormatHelpers | |||||
} | } | ||||
} | } | ||||
static bool hasARAExtension (AudioUnit audioUnit) | |||||
{ | |||||
#if JUCE_PLUGINHOST_ARA | |||||
UInt32 propertySize = sizeof (ARA::ARAAudioUnitFactory); | |||||
Boolean isWriteable = FALSE; | |||||
OSStatus status = AudioUnitGetPropertyInfo (audioUnit, | |||||
ARA::kAudioUnitProperty_ARAFactory, | |||||
kAudioUnitScope_Global, | |||||
0, | |||||
&propertySize, | |||||
&isWriteable); | |||||
if ((status == noErr) && (propertySize == sizeof (ARA::ARAAudioUnitFactory)) && ! isWriteable) | |||||
return true; | |||||
#else | |||||
ignoreUnused (audioUnit); | |||||
#endif | |||||
return false; | |||||
} | |||||
struct AudioUnitDeleter | |||||
{ | |||||
void operator() (AudioUnit au) const { AudioComponentInstanceDispose (au); } | |||||
}; | |||||
using AudioUnitUniquePtr = std::unique_ptr<std::remove_pointer_t<AudioUnit>, AudioUnitDeleter>; | |||||
using AudioUnitSharedPtr = std::shared_ptr<std::remove_pointer_t<AudioUnit>>; | |||||
using AudioUnitWeakPtr = std::weak_ptr<std::remove_pointer_t<AudioUnit>>; | |||||
static std::shared_ptr<const ARA::ARAFactory> getARAFactory (AudioUnitSharedPtr audioUnit) | |||||
{ | |||||
#if JUCE_PLUGINHOST_ARA | |||||
jassert (audioUnit != nullptr); | |||||
UInt32 propertySize = sizeof (ARA::ARAAudioUnitFactory); | |||||
ARA::ARAAudioUnitFactory audioUnitFactory { ARA::kARAAudioUnitMagic, nullptr }; | |||||
if (hasARAExtension (audioUnit.get())) | |||||
{ | |||||
OSStatus status = AudioUnitGetProperty (audioUnit.get(), | |||||
ARA::kAudioUnitProperty_ARAFactory, | |||||
kAudioUnitScope_Global, | |||||
0, | |||||
&audioUnitFactory, | |||||
&propertySize); | |||||
if ((status == noErr) | |||||
&& (propertySize == sizeof (ARA::ARAAudioUnitFactory)) | |||||
&& (audioUnitFactory.inOutMagicNumber == ARA::kARAAudioUnitMagic)) | |||||
{ | |||||
jassert (audioUnitFactory.outFactory != nullptr); | |||||
return getOrCreateARAFactory (audioUnitFactory.outFactory, | |||||
[owningAuPtr = std::move (audioUnit)] (const ARA::ARAFactory*) {}); | |||||
} | |||||
} | |||||
#else | |||||
ignoreUnused (audioUnit); | |||||
#endif | |||||
return {}; | |||||
} | |||||
struct VersionedAudioComponent | |||||
{ | |||||
AudioComponent audioComponent = nullptr; | |||||
bool isAUv3 = false; | |||||
bool operator< (const VersionedAudioComponent& other) const { return audioComponent < other.audioComponent; } | |||||
}; | |||||
using AudioUnitCreationCallback = std::function<void (AudioUnit, OSStatus)>; | |||||
static void createAudioUnit (VersionedAudioComponent versionedComponent, AudioUnitCreationCallback callback) | |||||
{ | |||||
struct AUAsyncInitializationCallback | |||||
{ | |||||
typedef void (^AUCompletionCallbackBlock)(AudioComponentInstance, OSStatus); | |||||
explicit AUAsyncInitializationCallback (AudioUnitCreationCallback inOriginalCallback) | |||||
: originalCallback (std::move (inOriginalCallback)) | |||||
{ | |||||
block = CreateObjCBlock (this, &AUAsyncInitializationCallback::completion); | |||||
} | |||||
AUCompletionCallbackBlock getBlock() noexcept { return block; } | |||||
void completion (AudioComponentInstance audioUnit, OSStatus err) | |||||
{ | |||||
originalCallback (audioUnit, err); | |||||
delete this; | |||||
} | |||||
double sampleRate; | |||||
int framesPerBuffer; | |||||
AudioUnitCreationCallback originalCallback; | |||||
ObjCBlock<AUCompletionCallbackBlock> block; | |||||
}; | |||||
auto callbackBlock = new AUAsyncInitializationCallback (std::move (callback)); | |||||
if (versionedComponent.isAUv3) | |||||
{ | |||||
if (@available (macOS 10.11, *)) | |||||
{ | |||||
AudioComponentInstantiate (versionedComponent.audioComponent, kAudioComponentInstantiation_LoadOutOfProcess, | |||||
callbackBlock->getBlock()); | |||||
return; | |||||
} | |||||
} | |||||
AudioComponentInstance audioUnit; | |||||
auto err = AudioComponentInstanceNew (versionedComponent.audioComponent, &audioUnit); | |||||
callbackBlock->completion (err != noErr ? nullptr : audioUnit, err); | |||||
} | |||||
struct AudioComponentResult | |||||
{ | |||||
explicit AudioComponentResult (String error) : errorMessage (std::move (error)) {} | |||||
explicit AudioComponentResult (VersionedAudioComponent auComponent) : component (std::move (auComponent)) {} | |||||
bool isValid() const { return component.audioComponent != nullptr; } | |||||
VersionedAudioComponent component; | |||||
String errorMessage; | |||||
}; | |||||
static AudioComponentResult getAudioComponent (AudioUnitPluginFormat& format, const PluginDescription& desc) | |||||
{ | |||||
using namespace AudioUnitFormatHelpers; | |||||
AudioUnitPluginFormat audioUnitPluginFormat; | |||||
if (! format.fileMightContainThisPluginType (desc.fileOrIdentifier)) | |||||
return AudioComponentResult { NEEDS_TRANS ("Plug-in description is not an AudioUnit plug-in") }; | |||||
String pluginName, version, manufacturer; | |||||
AudioComponentDescription componentDesc; | |||||
AudioComponent auComponent; | |||||
String errMessage = NEEDS_TRANS ("Cannot find AudioUnit from description"); | |||||
if (! getComponentDescFromIdentifier (desc.fileOrIdentifier, componentDesc, pluginName, version, manufacturer) | |||||
&& ! getComponentDescFromFile (desc.fileOrIdentifier, componentDesc, pluginName, version, manufacturer)) | |||||
{ | |||||
return AudioComponentResult { errMessage }; | |||||
} | |||||
if ((auComponent = AudioComponentFindNext (nullptr, &componentDesc)) == nullptr) | |||||
{ | |||||
return AudioComponentResult { errMessage }; | |||||
} | |||||
if (AudioComponentGetDescription (auComponent, &componentDesc) != noErr) | |||||
{ | |||||
return AudioComponentResult { errMessage }; | |||||
} | |||||
const bool isAUv3 = AudioUnitFormatHelpers::isPluginAUv3 (componentDesc); | |||||
return AudioComponentResult { { auComponent, isAUv3 } }; | |||||
} | |||||
static void getOrCreateARAAudioUnit (VersionedAudioComponent auComponent, std::function<void (AudioUnitSharedPtr)> callback) | |||||
{ | |||||
static std::map<VersionedAudioComponent, AudioUnitWeakPtr> audioUnitARACache; | |||||
if (auto audioUnit = audioUnitARACache[auComponent].lock()) | |||||
{ | |||||
callback (std::move (audioUnit)); | |||||
return; | |||||
} | |||||
createAudioUnit (auComponent, [auComponent, cb = std::move (callback)] (AudioUnit audioUnit, OSStatus err) | |||||
{ | |||||
cb ([auComponent, audioUnit, err]() -> AudioUnitSharedPtr | |||||
{ | |||||
if (err != noErr) | |||||
return nullptr; | |||||
AudioUnitSharedPtr auPtr { AudioUnitUniquePtr { audioUnit } }; | |||||
audioUnitARACache[auComponent] = auPtr; | |||||
return auPtr; | |||||
}()); | |||||
}); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
class AudioUnitPluginWindowCarbon; | |||||
class AudioUnitPluginWindowCocoa; | class AudioUnitPluginWindowCocoa; | ||||
//============================================================================== | //============================================================================== | ||||
@@ -979,6 +1177,23 @@ public: | |||||
desc.numInputChannels = getTotalNumInputChannels(); | desc.numInputChannels = getTotalNumInputChannels(); | ||||
desc.numOutputChannels = getTotalNumOutputChannels(); | desc.numOutputChannels = getTotalNumOutputChannels(); | ||||
desc.isInstrument = (componentDesc.componentType == kAudioUnitType_MusicDevice); | desc.isInstrument = (componentDesc.componentType == kAudioUnitType_MusicDevice); | ||||
#if JUCE_PLUGINHOST_ARA | |||||
desc.hasARAExtension = [&] | |||||
{ | |||||
UInt32 propertySize = sizeof (ARA::ARAAudioUnitFactory); | |||||
Boolean isWriteable = FALSE; | |||||
OSStatus status = AudioUnitGetPropertyInfo (audioUnit, | |||||
ARA::kAudioUnitProperty_ARAFactory, | |||||
kAudioUnitScope_Global, | |||||
0, | |||||
&propertySize, | |||||
&isWriteable); | |||||
return (status == noErr) && (propertySize == sizeof (ARA::ARAAudioUnitFactory)) && ! isWriteable; | |||||
}(); | |||||
#endif | |||||
} | } | ||||
void getExtensions (ExtensionsVisitor& visitor) const override | void getExtensions (ExtensionsVisitor& visitor) const override | ||||
@@ -993,6 +1208,33 @@ public: | |||||
}; | }; | ||||
visitor.visitAudioUnitClient (Extensions { this }); | visitor.visitAudioUnitClient (Extensions { this }); | ||||
#ifdef JUCE_PLUGINHOST_ARA | |||||
struct ARAExtensions : public ExtensionsVisitor::ARAClient | |||||
{ | |||||
explicit ARAExtensions (const AudioUnitPluginInstance* instanceIn) : instance (instanceIn) {} | |||||
void createARAFactoryAsync (std::function<void (ARAFactoryWrapper)> cb) const override | |||||
{ | |||||
getOrCreateARAAudioUnit ({ instance->auComponent, instance->isAUv3 }, | |||||
[origCb = std::move (cb)] (auto dylibKeepAliveAudioUnit) | |||||
{ | |||||
origCb ([&]() -> ARAFactoryWrapper | |||||
{ | |||||
if (dylibKeepAliveAudioUnit != nullptr) | |||||
return ARAFactoryWrapper { ::juce::getARAFactory (std::move (dylibKeepAliveAudioUnit)) }; | |||||
return ARAFactoryWrapper { nullptr }; | |||||
}()); | |||||
}); | |||||
} | |||||
const AudioUnitPluginInstance* instance = nullptr; | |||||
}; | |||||
if (hasARAExtension (audioUnit)) | |||||
visitor.visitARAClient (ARAExtensions (this)); | |||||
#endif | |||||
} | } | ||||
void* getPlatformSpecificData() override { return audioUnit; } | void* getPlatformSpecificData() override { return audioUnit; } | ||||
@@ -1124,9 +1366,9 @@ public: | |||||
{ | { | ||||
if (prepared) | if (prepared) | ||||
{ | { | ||||
AudioUnitUninitialize (audioUnit); | |||||
resetBuses(); | resetBuses(); | ||||
AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); | AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); | ||||
AudioUnitUninitialize (audioUnit); | |||||
outputBufferList.clear(); | outputBufferList.clear(); | ||||
prepared = false; | prepared = false; | ||||
@@ -1615,7 +1857,6 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
friend class AudioUnitPluginWindowCarbon; | |||||
friend class AudioUnitPluginWindowCocoa; | friend class AudioUnitPluginWindowCocoa; | ||||
friend class AudioUnitPluginFormat; | friend class AudioUnitPluginFormat; | ||||
@@ -2594,162 +2835,12 @@ private: | |||||
} | } | ||||
}; | }; | ||||
#if JUCE_SUPPORT_CARBON | |||||
//============================================================================== | |||||
class AudioUnitPluginWindowCarbon : public AudioProcessorEditor | |||||
{ | |||||
public: | |||||
AudioUnitPluginWindowCarbon (AudioUnitPluginInstance& p) | |||||
: AudioProcessorEditor (&p), | |||||
plugin (p), | |||||
audioComponent (nullptr), | |||||
viewComponent (nullptr) | |||||
{ | |||||
innerWrapper.reset (new InnerWrapperComponent (*this)); | |||||
addAndMakeVisible (innerWrapper.get()); | |||||
setOpaque (true); | |||||
setVisible (true); | |||||
setSize (400, 300); | |||||
UInt32 propertySize; | |||||
if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, | |||||
kAudioUnitScope_Global, 0, &propertySize, NULL) == noErr | |||||
&& propertySize > 0) | |||||
{ | |||||
HeapBlock<AudioComponentDescription> views (propertySize / sizeof (AudioComponentDescription)); | |||||
if (AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, | |||||
kAudioUnitScope_Global, 0, &views[0], &propertySize) == noErr) | |||||
{ | |||||
audioComponent = AudioComponentFindNext (nullptr, &views[0]); | |||||
} | |||||
} | |||||
} | |||||
~AudioUnitPluginWindowCarbon() | |||||
{ | |||||
innerWrapper = nullptr; | |||||
if (isValid()) | |||||
plugin.editorBeingDeleted (this); | |||||
} | |||||
bool isValid() const noexcept { return audioComponent != nullptr; } | |||||
//============================================================================== | |||||
void paint (Graphics& g) override | |||||
{ | |||||
g.fillAll (Colours::black); | |||||
} | |||||
void resized() override | |||||
{ | |||||
if (innerWrapper != nullptr) | |||||
innerWrapper->setSize (getWidth(), getHeight()); | |||||
} | |||||
//============================================================================== | |||||
bool keyStateChanged (bool) override { return false; } | |||||
bool keyPressed (const KeyPress&) override { return false; } | |||||
//============================================================================== | |||||
AudioUnit getAudioUnit() const { return plugin.audioUnit; } | |||||
AudioUnitCarbonView getViewComponent() | |||||
{ | |||||
if (viewComponent == nullptr && audioComponent != nullptr) | |||||
AudioComponentInstanceNew (audioComponent, &viewComponent); | |||||
return viewComponent; | |||||
} | |||||
void closeViewComponent() | |||||
{ | |||||
if (viewComponent != nullptr) | |||||
{ | |||||
JUCE_AU_LOG ("Closing AU GUI: " + plugin.getName()); | |||||
AudioComponentInstanceDispose (viewComponent); | |||||
viewComponent = nullptr; | |||||
} | |||||
} | |||||
private: | |||||
//============================================================================== | |||||
AudioUnitPluginInstance& plugin; | |||||
AudioComponent audioComponent; | |||||
AudioUnitCarbonView viewComponent; | |||||
//============================================================================== | |||||
class InnerWrapperComponent : public CarbonViewWrapperComponent | |||||
{ | |||||
public: | |||||
InnerWrapperComponent (AudioUnitPluginWindowCarbon& w) : owner (w) {} | |||||
~InnerWrapperComponent() | |||||
{ | |||||
deleteWindow(); | |||||
} | |||||
HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) override | |||||
{ | |||||
JUCE_AU_LOG ("Opening AU GUI: " + owner.plugin.getName()); | |||||
AudioUnitCarbonView carbonView = owner.getViewComponent(); | |||||
if (carbonView == 0) | |||||
return 0; | |||||
Float32Point pos = { 0, 0 }; | |||||
Float32Point size = { 250, 200 }; | |||||
HIViewRef pluginView = 0; | |||||
AudioUnitCarbonViewCreate (carbonView, owner.getAudioUnit(), windowRef, rootView, | |||||
&pos, &size, (ControlRef*) &pluginView); | |||||
return pluginView; | |||||
} | |||||
void removeView (HIViewRef) override | |||||
{ | |||||
owner.closeViewComponent(); | |||||
} | |||||
private: | |||||
AudioUnitPluginWindowCarbon& owner; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InnerWrapperComponent) | |||||
}; | |||||
friend class InnerWrapperComponent; | |||||
std::unique_ptr<InnerWrapperComponent> innerWrapper; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioUnitPluginWindowCarbon) | |||||
}; | |||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
AudioProcessorEditor* AudioUnitPluginInstance::createEditor() | AudioProcessorEditor* AudioUnitPluginInstance::createEditor() | ||||
{ | { | ||||
std::unique_ptr<AudioProcessorEditor> w (new AudioUnitPluginWindowCocoa (*this, false)); | std::unique_ptr<AudioProcessorEditor> w (new AudioUnitPluginWindowCocoa (*this, false)); | ||||
if (! static_cast<AudioUnitPluginWindowCocoa*> (w.get())->isValid()) | if (! static_cast<AudioUnitPluginWindowCocoa*> (w.get())->isValid()) | ||||
w.reset(); | |||||
#if JUCE_SUPPORT_CARBON | |||||
if (w == nullptr) | |||||
{ | |||||
w.reset (new AudioUnitPluginWindowCarbon (*this)); | |||||
if (! static_cast<AudioUnitPluginWindowCarbon*> (w.get())->isValid()) | |||||
w.reset(); | |||||
} | |||||
#endif | |||||
if (w == nullptr) | |||||
w.reset (new AudioUnitPluginWindowCocoa (*this, true)); // use AUGenericView as a fallback | w.reset (new AudioUnitPluginWindowCocoa (*this, true)); // use AUGenericView as a fallback | ||||
return w.release(); | return w.release(); | ||||
@@ -2795,95 +2886,54 @@ void AudioUnitPluginFormat::createPluginInstance (const PluginDescription& desc, | |||||
double rate, int blockSize, | double rate, int blockSize, | ||||
PluginCreationCallback callback) | PluginCreationCallback callback) | ||||
{ | { | ||||
using namespace AudioUnitFormatHelpers; | |||||
auto auComponentResult = getAudioComponent (*this, desc); | |||||
if (fileMightContainThisPluginType (desc.fileOrIdentifier)) | |||||
if (! auComponentResult.isValid()) | |||||
{ | { | ||||
String pluginName, version, manufacturer; | |||||
AudioComponentDescription componentDesc; | |||||
AudioComponent auComponent; | |||||
String errMessage = NEEDS_TRANS ("Cannot find AudioUnit from description"); | |||||
if ((! getComponentDescFromIdentifier (desc.fileOrIdentifier, componentDesc, pluginName, version, manufacturer)) | |||||
&& (! getComponentDescFromFile (desc.fileOrIdentifier, componentDesc, pluginName, version, manufacturer))) | |||||
{ | |||||
callback (nullptr, errMessage); | |||||
return; | |||||
} | |||||
if ((auComponent = AudioComponentFindNext (nullptr, &componentDesc)) == nullptr) | |||||
{ | |||||
callback (nullptr, errMessage); | |||||
return; | |||||
} | |||||
if (AudioComponentGetDescription (auComponent, &componentDesc) != noErr) | |||||
{ | |||||
callback (nullptr, errMessage); | |||||
return; | |||||
} | |||||
struct AUAsyncInitializationCallback | |||||
{ | |||||
typedef void (^AUCompletionCallbackBlock)(AudioComponentInstance, OSStatus); | |||||
AUAsyncInitializationCallback (double inSampleRate, int inFramesPerBuffer, | |||||
PluginCreationCallback inOriginalCallback) | |||||
: sampleRate (inSampleRate), framesPerBuffer (inFramesPerBuffer), | |||||
originalCallback (std::move (inOriginalCallback)) | |||||
{ | |||||
block = CreateObjCBlock (this, &AUAsyncInitializationCallback::completion); | |||||
} | |||||
AUCompletionCallbackBlock getBlock() noexcept { return block; } | |||||
void completion (AudioComponentInstance audioUnit, OSStatus err) | |||||
{ | |||||
if (err == noErr) | |||||
{ | |||||
std::unique_ptr<AudioUnitPluginInstance> instance (new AudioUnitPluginInstance (audioUnit)); | |||||
callback (nullptr, std::move (auComponentResult.errorMessage)); | |||||
return; | |||||
} | |||||
if (instance->initialise (sampleRate, framesPerBuffer)) | |||||
originalCallback (std::move (instance), {}); | |||||
else | |||||
originalCallback (nullptr, NEEDS_TRANS ("Unable to initialise the AudioUnit plug-in")); | |||||
} | |||||
else | |||||
{ | |||||
auto errMsg = TRANS ("An OS error occurred during initialisation of the plug-in (XXX)"); | |||||
originalCallback (nullptr, errMsg.replace ("XXX", String (err))); | |||||
} | |||||
createAudioUnit (auComponentResult.component, | |||||
[rate, blockSize, origCallback = std::move (callback)] (AudioUnit audioUnit, OSStatus err) | |||||
{ | |||||
if (err == noErr) | |||||
{ | |||||
auto instance = std::make_unique<AudioUnitPluginInstance> (audioUnit); | |||||
delete this; | |||||
} | |||||
if (instance->initialise (rate, blockSize)) | |||||
origCallback (std::move (instance), {}); | |||||
else | |||||
origCallback (nullptr, NEEDS_TRANS ("Unable to initialise the AudioUnit plug-in")); | |||||
} | |||||
else | |||||
{ | |||||
auto errMsg = TRANS ("An OS error occurred during initialisation of the plug-in (XXX)"); | |||||
origCallback (nullptr, errMsg.replace ("XXX", String (err))); | |||||
} | |||||
}); | |||||
} | |||||
double sampleRate; | |||||
int framesPerBuffer; | |||||
PluginCreationCallback originalCallback; | |||||
ObjCBlock<AUCompletionCallbackBlock> block; | |||||
}; | |||||
void AudioUnitPluginFormat::createARAFactoryAsync (const PluginDescription& desc, ARAFactoryCreationCallback callback) | |||||
{ | |||||
auto auComponentResult = getAudioComponent (*this, desc); | |||||
auto callbackBlock = new AUAsyncInitializationCallback (rate, blockSize, std::move (callback)); | |||||
if (! auComponentResult.isValid()) | |||||
{ | |||||
callback ({ {}, "Failed to create AudioComponent for " + desc.descriptiveName }); | |||||
return; | |||||
} | |||||
if (AudioUnitFormatHelpers::isPluginAUv3 (componentDesc)) | |||||
{ | |||||
if (@available (macOS 10.11, *)) | |||||
getOrCreateARAAudioUnit (auComponentResult.component, [cb = std::move (callback)] (auto dylibKeepAliveAudioUnit) | |||||
{ | |||||
cb ([&]() -> ARAFactoryResult | |||||
{ | { | ||||
AudioComponentInstantiate (auComponent, kAudioComponentInstantiation_LoadOutOfProcess, | |||||
callbackBlock->getBlock()); | |||||
if (dylibKeepAliveAudioUnit != nullptr) | |||||
return { ARAFactoryWrapper { ::juce::getARAFactory (std::move (dylibKeepAliveAudioUnit)) }, "" }; | |||||
return; | |||||
} | |||||
} | |||||
AudioComponentInstance audioUnit; | |||||
auto err = AudioComponentInstanceNew(auComponent, &audioUnit); | |||||
callbackBlock->completion (err != noErr ? nullptr : audioUnit, err); | |||||
} | |||||
else | |||||
{ | |||||
callback (nullptr, NEEDS_TRANS ("Plug-in description is not an AudioUnit plug-in")); | |||||
} | |||||
return { {}, "Failed to create ARAFactory from the provided AudioUnit" }; | |||||
}()); | |||||
}); | |||||
} | } | ||||
bool AudioUnitPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription& desc) const | bool AudioUnitPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription& desc) const | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -19,6 +26,7 @@ | |||||
#pragma once | #pragma once | ||||
#include "juce_lv2_config.h" | #include "juce_lv2_config.h" | ||||
#include "juce_core/containers/juce_Optional.h" | |||||
#ifdef Bool | #ifdef Bool | ||||
#undef Bool // previously defined in X11/Xlib.h | #undef Bool // previously defined in X11/Xlib.h | ||||
@@ -127,61 +135,61 @@ struct ObjectTraits { static constexpr auto construct = lv2_atom_forge_object; | |||||
using SequenceFrame = ScopedFrame<SequenceTraits>; | using SequenceFrame = ScopedFrame<SequenceTraits>; | ||||
using ObjectFrame = ScopedFrame<ObjectTraits>; | using ObjectFrame = ScopedFrame<ObjectTraits>; | ||||
template <typename Value, typename Callback> | |||||
bool withValue (const Optional<Value>& opt, Callback&& callback) | |||||
{ | |||||
if (! opt.hasValue()) | |||||
return false; | |||||
callback (*opt); | |||||
return true; | |||||
} | |||||
struct NumericAtomParser | struct NumericAtomParser | ||||
{ | { | ||||
explicit NumericAtomParser (LV2_URID_Map mapFeatureIn) | explicit NumericAtomParser (LV2_URID_Map mapFeatureIn) | ||||
: mapFeature (mapFeatureIn) {} | : mapFeature (mapFeatureIn) {} | ||||
template <typename Type> | |||||
struct ParseResult | |||||
{ | |||||
ParseResult (Type type) : value (type), successful (true) {} | |||||
ParseResult() : value(), successful (false) {} | |||||
template <typename Fn> | |||||
ParseResult andThen (Fn&& fn) const | |||||
{ | |||||
if (successful) | |||||
fn (value); | |||||
template <typename T> struct Tag { LV2_URID urid; }; | |||||
return *this; | |||||
} | |||||
template <typename Target, typename... Types> | |||||
static Optional<Target> tryParse (const LV2_Atom&, const void*) | |||||
{ | |||||
return {}; | |||||
} | |||||
operator bool() const noexcept { return successful; } | |||||
template <typename Target, typename Head, typename... Tail> | |||||
static Optional<Target> tryParse (const LV2_Atom& atom, const void* data, Tag<Head> head, Tag<Tail>... tail) | |||||
{ | |||||
if (atom.type == head.urid && atom.size == sizeof (Head)) | |||||
return static_cast<Target> (*reinterpret_cast<const Head*> (data)); | |||||
Type value; | |||||
bool successful; | |||||
}; | |||||
return tryParse<Target> (atom, data, tail...); | |||||
} | |||||
template <typename Target> | template <typename Target> | ||||
ParseResult<Target> parseNumericAtom (const LV2_Atom* atom, const void* data) const | |||||
Optional<Target> parseNumericAtom (const LV2_Atom* atom, const void* data) const | |||||
{ | { | ||||
if (atom == nullptr) | if (atom == nullptr) | ||||
return {}; | return {}; | ||||
if (atom->type == mLV2_ATOM__Int && atom->size == sizeof (int32_t)) | |||||
return { static_cast<Target> (*static_cast<const int32_t*> (data)) }; | |||||
if (atom->type == mLV2_ATOM__Long && atom->size == sizeof (int64_t)) | |||||
return { static_cast<Target> (*static_cast<const int64_t*> (data)) }; | |||||
if (atom->type == mLV2_ATOM__Float && atom->size == sizeof (float)) | |||||
return { static_cast<Target> (*static_cast<const float*> (data)) }; | |||||
if (atom->type == mLV2_ATOM__Double && atom->size == sizeof (double)) | |||||
return { static_cast<Target> (*static_cast<const double*> (data)) }; | |||||
return {}; | |||||
return tryParse<Target> (*atom, | |||||
data, | |||||
Tag<int32_t> { mLV2_ATOM__Bool }, | |||||
Tag<int32_t> { mLV2_ATOM__Int }, | |||||
Tag<int64_t> { mLV2_ATOM__Long }, | |||||
Tag<float> { mLV2_ATOM__Float }, | |||||
Tag<double> { mLV2_ATOM__Double }); | |||||
} | } | ||||
template <typename Target> | template <typename Target> | ||||
ParseResult<Target> parseNumericAtom (const LV2_Atom* atom) const | |||||
Optional<Target> parseNumericAtom (const LV2_Atom* atom) const | |||||
{ | { | ||||
return parseNumericAtom<Target> (atom, atom + 1); | return parseNumericAtom<Target> (atom, atom + 1); | ||||
} | } | ||||
template <typename Target> | template <typename Target> | ||||
ParseResult<Target> parseNumericOption (const LV2_Options_Option* option) const | |||||
Optional<Target> parseNumericOption (const LV2_Options_Option* option) const | |||||
{ | { | ||||
if (option != nullptr) | if (option != nullptr) | ||||
{ | { | ||||
@@ -240,8 +248,10 @@ struct PatchSetHelper | |||||
lv2_atom_object_query (object, query); | lv2_atom_object_query (object, query); | ||||
if (isPlugin (subject)) | |||||
setPluginProperty (property, value, std::forward<Callback> (callback)); | |||||
if (! isPlugin (subject)) | |||||
return; | |||||
setPluginProperty (property, value, std::forward<Callback> (callback)); | |||||
} | } | ||||
template <typename Callback> | template <typename Callback> | ||||
@@ -270,14 +280,14 @@ struct PatchSetHelper | |||||
const auto parseResult = parser.parseNumericAtom<float> (value); | const auto parseResult = parser.parseNumericAtom<float> (value); | ||||
if (! parseResult.successful) | |||||
if (! parseResult.hasValue()) | |||||
{ | { | ||||
// Didn't understand the type of this atom. | // Didn't understand the type of this atom. | ||||
jassertfalse; | jassertfalse; | ||||
return; | return; | ||||
} | } | ||||
callback.setParameter (reinterpret_cast<const LV2_Atom_URID*> (property)->body, parseResult.value); | |||||
callback.setParameter (reinterpret_cast<const LV2_Atom_URID*> (property)->body, *parseResult); | |||||
} | } | ||||
NumericAtomParser parser; | NumericAtomParser parser; | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -30,12 +37,11 @@ namespace juce | |||||
namespace lv2_host | namespace lv2_host | ||||
{ | { | ||||
template <typename Struct, typename Member, typename Value> | |||||
auto with (Struct&& s, Member&& member, Value&& value) noexcept | |||||
template <typename Struct, typename Value> | |||||
auto with (Struct s, Value Struct::* member, Value value) noexcept | |||||
{ | { | ||||
auto copy = std::forward<Struct> (s); | |||||
copy.*member = std::forward<Value> (value); | |||||
return copy; | |||||
s.*member = std::move (value); | |||||
return s; | |||||
} | } | ||||
/* Converts a void* to an LV2_Atom* if the buffer looks like it holds a well-formed Atom, or | /* Converts a void* to an LV2_Atom* if the buffer looks like it holds a well-formed Atom, or | ||||
@@ -1682,7 +1688,7 @@ private: | |||||
template <size_t Alignment> | template <size_t Alignment> | ||||
static SingleSizeAlignedStorage<Alignment> grow (SingleSizeAlignedStorage<Alignment> storage, size_t size) | static SingleSizeAlignedStorage<Alignment> grow (SingleSizeAlignedStorage<Alignment> storage, size_t size) | ||||
{ | { | ||||
if (storage.size() <= size) | |||||
if (size <= storage.size()) | |||||
return storage; | return storage; | ||||
SingleSizeAlignedStorage<Alignment> newStorage { jmax (size, (storage.size() * 3) / 2) }; | SingleSizeAlignedStorage<Alignment> newStorage { jmax (size, (storage.size() * 3) / 2) }; | ||||
@@ -2122,6 +2128,8 @@ private: | |||||
JUCE_LEAK_DETECTOR (PortMap) | JUCE_LEAK_DETECTOR (PortMap) | ||||
}; | }; | ||||
struct FreeString { void operator() (void* ptr) const noexcept { lilv_free (ptr); } }; | |||||
class PluginState | class PluginState | ||||
{ | { | ||||
public: | public: | ||||
@@ -2140,7 +2148,6 @@ public: | |||||
std::string toString (LilvWorld* world, LV2_URID_Map* map, LV2_URID_Unmap* unmap, const char* uri) const | std::string toString (LilvWorld* world, LV2_URID_Map* map, LV2_URID_Unmap* unmap, const char* uri) const | ||||
{ | { | ||||
struct FreeString { void operator() (void* ptr) const noexcept { lilv_free (ptr); } }; | |||||
std::unique_ptr<char, FreeString> result { lilv_state_to_string (world, | std::unique_ptr<char, FreeString> result { lilv_state_to_string (world, | ||||
map, | map, | ||||
unmap, | unmap, | ||||
@@ -2256,17 +2263,16 @@ struct UiDescriptorLibrary | |||||
class UiDescriptorArgs | class UiDescriptorArgs | ||||
{ | { | ||||
public: | public: | ||||
const char* libraryPath = nullptr; | |||||
const char* uiUri = nullptr; | |||||
String libraryPath; | |||||
String uiUri; | |||||
auto withLibraryPath (const char* v) const noexcept { return with (&UiDescriptorArgs::libraryPath, v); } | |||||
auto withUiUri (const char* v) const noexcept { return with (&UiDescriptorArgs::uiUri, v); } | |||||
auto withLibraryPath (String v) const noexcept { return with (&UiDescriptorArgs::libraryPath, v); } | |||||
auto withUiUri (String v) const noexcept { return with (&UiDescriptorArgs::uiUri, v); } | |||||
private: | private: | ||||
template <typename Member> | |||||
UiDescriptorArgs with (Member&& member, const char* value) const noexcept | |||||
UiDescriptorArgs with (String UiDescriptorArgs::* member, String value) const noexcept | |||||
{ | { | ||||
return juce::lv2_host::with (*this, std::forward<Member> (member), value); | |||||
return juce::lv2_host::with (*this, member, std::move (value)); | |||||
} | } | ||||
}; | }; | ||||
@@ -2280,7 +2286,7 @@ public: | |||||
explicit UiDescriptor (const UiDescriptorArgs& args) | explicit UiDescriptor (const UiDescriptorArgs& args) | ||||
: library (args.libraryPath), | : library (args.libraryPath), | ||||
descriptor (extractUiDescriptor (library, args.uiUri)) | |||||
descriptor (extractUiDescriptor (library, args.uiUri.toRawUTF8())) | |||||
{} | {} | ||||
void portEvent (LV2UI_Handle ui, | void portEvent (LV2UI_Handle ui, | ||||
@@ -2342,8 +2348,7 @@ private: | |||||
JUCE_LEAK_DETECTOR (UiDescriptor) | JUCE_LEAK_DETECTOR (UiDescriptor) | ||||
}; | }; | ||||
enum class UpdateUi { no, yes }; | |||||
enum class UpdateProcessor { no, yes }; | |||||
enum class Update { no, yes }; | |||||
/* A bit like the FlaggedFloatCache used by the VST3 host/client. | /* A bit like the FlaggedFloatCache used by the VST3 host/client. | ||||
@@ -2366,12 +2371,12 @@ public: | |||||
size_t size() const noexcept { return values.size(); } | size_t size() const noexcept { return values.size(); } | ||||
void set (size_t index, float value, UpdateUi updateUi, UpdateProcessor updateProcessor) | |||||
void set (size_t index, float value, Update update) | |||||
{ | { | ||||
jassert (index < size()); | jassert (index < size()); | ||||
values[index].store (value, std::memory_order_relaxed); | values[index].store (value, std::memory_order_relaxed); | ||||
needsUiUpdate .set (index, updateUi == UpdateUi::yes ? 1 : 0); | |||||
needsProcessorUpdate.set (index, updateProcessor == UpdateProcessor::yes ? 1 : 0); | |||||
needsUiUpdate .set (index, update == Update::yes ? 1 : 0); | |||||
needsProcessorUpdate.set (index, update == Update::yes ? 1 : 0); | |||||
} | } | ||||
float get (size_t index) const noexcept | float get (size_t index) const noexcept | ||||
@@ -2431,18 +2436,18 @@ public: | |||||
void setValue (float f) override | void setValue (float f) override | ||||
{ | { | ||||
cache.set ((size_t) getParameterIndex(), range.convertFrom0to1 (f), UpdateUi::yes, UpdateProcessor::yes); | |||||
cache.set ((size_t) getParameterIndex(), range.convertFrom0to1 (f), Update::yes); | |||||
} | } | ||||
void setDenormalisedValueFromUi (float denormalised) | |||||
void setDenormalisedValue (float denormalised) | |||||
{ | { | ||||
cache.set ((size_t) getParameterIndex(), denormalised, UpdateUi::no, UpdateProcessor::yes); | |||||
cache.set ((size_t) getParameterIndex(), denormalised, Update::yes); | |||||
sendValueChangedMessageToListeners (range.convertTo0to1 (denormalised)); | sendValueChangedMessageToListeners (range.convertTo0to1 (denormalised)); | ||||
} | } | ||||
void setDenormalisedValueWithoutTriggeringUpdate (float denormalised) | void setDenormalisedValueWithoutTriggeringUpdate (float denormalised) | ||||
{ | { | ||||
cache.set ((size_t) getParameterIndex(), denormalised, UpdateUi::no, UpdateProcessor::no); | |||||
cache.set ((size_t) getParameterIndex(), denormalised, Update::no); | |||||
sendValueChangedMessageToListeners (range.convertTo0to1 (denormalised)); | sendValueChangedMessageToListeners (range.convertTo0to1 (denormalised)); | ||||
} | } | ||||
@@ -2564,20 +2569,25 @@ private: | |||||
class UiInstanceArgs | class UiInstanceArgs | ||||
{ | { | ||||
public: | public: | ||||
const char* bundlePath = nullptr; | |||||
const char* pluginUri = nullptr; | |||||
File bundlePath; | |||||
URL pluginUri; | |||||
auto withBundlePath (const char* v) const noexcept { return with (&UiInstanceArgs::bundlePath, v); } | |||||
auto withPluginUri (const char* v) const noexcept { return with (&UiInstanceArgs::pluginUri, v); } | |||||
auto withBundlePath (File v) const noexcept { return with (&UiInstanceArgs::bundlePath, std::move (v)); } | |||||
auto withPluginUri (URL v) const noexcept { return with (&UiInstanceArgs::pluginUri, std::move (v)); } | |||||
private: | private: | ||||
template <typename Member> | template <typename Member> | ||||
UiInstanceArgs with (Member&& member, const char* value) const noexcept | |||||
UiInstanceArgs with (Member UiInstanceArgs::* member, Member value) const noexcept | |||||
{ | { | ||||
return juce::lv2_host::with (*this, std::forward<Member> (member), value); | |||||
return juce::lv2_host::with (*this, member, std::move (value)); | |||||
} | } | ||||
}; | }; | ||||
static File bundlePathFromUri (const char* uri) | |||||
{ | |||||
return File { std::unique_ptr<char, FreeString> { lilv_file_uri_parse (uri, nullptr) }.get() }; | |||||
} | |||||
/* | /* | ||||
Creates and holds a UI instance for a plugin with a specific URI, using the provided descriptor. | Creates and holds a UI instance for a plugin with a specific URI, using the provided descriptor. | ||||
*/ | */ | ||||
@@ -2665,14 +2675,14 @@ private: | |||||
using Instance = std::unique_ptr<void, void (*) (LV2UI_Handle)>; | using Instance = std::unique_ptr<void, void (*) (LV2UI_Handle)>; | ||||
using Idle = int (*) (LV2UI_Handle); | using Idle = int (*) (LV2UI_Handle); | ||||
Instance makeInstance (const char* pluginUri, const char* bundlePath, const LV2_Feature* const* features) | |||||
Instance makeInstance (const URL& pluginUri, const File& bundlePath, const LV2_Feature* const* features) | |||||
{ | { | ||||
if (descriptor->get() == nullptr) | if (descriptor->get() == nullptr) | ||||
return { nullptr, [] (LV2UI_Handle) {} }; | return { nullptr, [] (LV2UI_Handle) {} }; | ||||
return Instance { descriptor->get()->instantiate (descriptor->get(), | return Instance { descriptor->get()->instantiate (descriptor->get(), | ||||
pluginUri, | |||||
bundlePath, | |||||
pluginUri.toString (false).toRawUTF8(), | |||||
File::addTrailingSeparator (bundlePath.getFullPathName()).toRawUTF8(), | |||||
writeFunction, | writeFunction, | ||||
this, | this, | ||||
&widget, | &widget, | ||||
@@ -2752,10 +2762,9 @@ public: | |||||
auto withSampleRate (float v) const { return with (&UiFeaturesDataOptions::sampleRate, v); } | auto withSampleRate (float v) const { return with (&UiFeaturesDataOptions::sampleRate, v); } | ||||
private: | private: | ||||
template <typename Member, typename Value> | |||||
UiFeaturesDataOptions with (Member&& member, Value&& value) const | |||||
UiFeaturesDataOptions with (float UiFeaturesDataOptions::* member, float value) const | |||||
{ | { | ||||
return juce::lv2_host::with (*this, std::forward<Member> (member), std::forward<Value> (value)); | |||||
return juce::lv2_host::with (*this, member, value); | |||||
} | } | ||||
}; | }; | ||||
@@ -3034,8 +3043,8 @@ public: | |||||
*this, | *this, | ||||
touchListener, | touchListener, | ||||
&uiDescriptor, | &uiDescriptor, | ||||
UiInstanceArgs{}.withBundlePath (uiBundleUri.toRawUTF8()) | |||||
.withPluginUri (instance.instance.getUri()), | |||||
UiInstanceArgs{}.withBundlePath (bundlePathFromUri (uiBundleUri.toRawUTF8())) | |||||
.withPluginUri (URL (instance.instance.getUri())), | |||||
viewComponent.getWidget(), | viewComponent.getWidget(), | ||||
instance, | instance, | ||||
opts)), | opts)), | ||||
@@ -3168,14 +3177,6 @@ private: | |||||
float getEffectiveScale() const { return nativeScaleFactor * userScaleFactor; } | float getEffectiveScale() const { return nativeScaleFactor * userScaleFactor; } | ||||
float getTopLevelDesktopScale() const | |||||
{ | |||||
if (auto* comp = getTopLevelComponent()) | |||||
return comp->getDesktopScaleFactor(); | |||||
return 1.0f; | |||||
} | |||||
// If possible, try to keep platform-specific handing restricted to the implementation of | // If possible, try to keep platform-specific handing restricted to the implementation of | ||||
// ViewComponent. Keep the interface of ViewComponent consistent on all platforms. | // ViewComponent. Keep the interface of ViewComponent consistent on all platforms. | ||||
#if JUCE_LINUX || JUCE_BSD | #if JUCE_LINUX || JUCE_BSD | ||||
@@ -4107,11 +4108,14 @@ static SupportedParameter getInfoForPatchParameter (World& worldIn, | |||||
jassertfalse; // A ScalePoint must have both a rdfs:label and a rdf:value | jassertfalse; // A ScalePoint must have both a rdfs:label and a rdf:value | ||||
} | } | ||||
const auto minimum = getValue (LV2_CORE__minimum, 0.0f); | |||||
const auto maximum = getValue (LV2_CORE__maximum, 1.0f); | |||||
return { { std::move (parsedScalePoints), | return { { std::move (parsedScalePoints), | ||||
"des:" + String::fromUTF8 (property.getTyped()), | "des:" + String::fromUTF8 (property.getTyped()), | ||||
getValue (LV2_CORE__default, 0.0f), | |||||
getValue (LV2_CORE__minimum, 0.0f), | |||||
getValue (LV2_CORE__maximum, 1.0f), | |||||
getValue (LV2_CORE__default, (minimum + maximum) * 0.5f), | |||||
minimum, | |||||
maximum, | |||||
typeUrid == urids.mLV2_ATOM__Bool || hasPortProperty (LV2_CORE__toggled), | typeUrid == urids.mLV2_ATOM__Bool || hasPortProperty (LV2_CORE__toggled), | ||||
typeUrid == urids.mLV2_ATOM__Int || typeUrid == urids.mLV2_ATOM__Long, | typeUrid == urids.mLV2_ATOM__Int || typeUrid == urids.mLV2_ATOM__Long, | ||||
hasPortProperty (LV2_CORE__enumeration) }, | hasPortProperty (LV2_CORE__enumeration) }, | ||||
@@ -4402,7 +4406,8 @@ public: | |||||
numSamples, | numSamples, | ||||
sampleRate); | sampleRate); | ||||
setStateInformation (mb.getData(), (int) mb.getSize()); | |||||
// prepareToPlay is *guaranteed* not to be called concurrently with processBlock | |||||
setStateInformationImpl (mb.getData(), (int) mb.getSize(), ConcurrentWithAudioCallback::no); | |||||
jassert (numSamples == instance->features.getMaxBlockSize()); | jassert (numSamples == instance->features.getMaxBlockSize()); | ||||
@@ -4487,7 +4492,8 @@ public: | |||||
return; | return; | ||||
lastAppliedPreset = newProgram; | lastAppliedPreset = newProgram; | ||||
applyStateWithAppropriateLocking (loadStateWithUri (presetUris[(size_t) newProgram])); | |||||
applyStateWithAppropriateLocking (loadStateWithUri (presetUris[(size_t) newProgram]), | |||||
ConcurrentWithAudioCallback::yes); | |||||
} | } | ||||
const String getProgramName (int program) override | const String getProgramName (int program) override | ||||
@@ -4524,16 +4530,7 @@ public: | |||||
void setStateInformation (const void* data, int size) override | void setStateInformation (const void* data, int size) override | ||||
{ | { | ||||
JUCE_ASSERT_MESSAGE_THREAD; | |||||
if (data == nullptr || size == 0) | |||||
return; | |||||
auto begin = static_cast<const char*> (data); | |||||
std::vector<char> copy (begin, begin + size); | |||||
copy.push_back (0); | |||||
auto mapFeature = instance->symap->getMapFeature(); | |||||
applyStateWithAppropriateLocking (PluginState { lilv_state_new_from_string (world->get(), &mapFeature, copy.data()) }); | |||||
setStateInformationImpl (data, size, ConcurrentWithAudioCallback::yes); | |||||
} | } | ||||
void setNonRealtime (bool newValue) noexcept override | void setNonRealtime (bool newValue) noexcept override | ||||
@@ -4573,6 +4570,8 @@ public: | |||||
AudioProcessorParameter* getBypassParameter() const override { return bypassParam; } | AudioProcessorParameter* getBypassParameter() const override { return bypassParam; } | ||||
private: | private: | ||||
enum class ConcurrentWithAudioCallback { no, yes }; | |||||
LV2AudioPluginInstance (std::shared_ptr<World> worldIn, | LV2AudioPluginInstance (std::shared_ptr<World> worldIn, | ||||
const Plugin& pluginIn, | const Plugin& pluginIn, | ||||
std::unique_ptr<InstanceWithSupports>&& in, | std::unique_ptr<InstanceWithSupports>&& in, | ||||
@@ -4593,7 +4592,22 @@ private: | |||||
std::move (uiDescriptorIn), | std::move (uiDescriptorIn), | ||||
[this] { postChangedParametersToUi(); }) | [this] { postChangedParametersToUi(); }) | ||||
{ | { | ||||
applyStateWithAppropriateLocking (std::move (stateToApply)); | |||||
applyStateWithAppropriateLocking (std::move (stateToApply), ConcurrentWithAudioCallback::no); | |||||
} | |||||
void setStateInformationImpl (const void* data, int size, ConcurrentWithAudioCallback concurrent) | |||||
{ | |||||
JUCE_ASSERT_MESSAGE_THREAD; | |||||
if (data == nullptr || size == 0) | |||||
return; | |||||
auto begin = static_cast<const char*> (data); | |||||
std::vector<char> copy (begin, begin + size); | |||||
copy.push_back (0); | |||||
auto mapFeature = instance->symap->getMapFeature(); | |||||
applyStateWithAppropriateLocking (PluginState { lilv_state_new_from_string (world->get(), &mapFeature, copy.data()) }, | |||||
concurrent); | |||||
} | } | ||||
// This does *not* destroy the editor component. | // This does *not* destroy the editor component. | ||||
@@ -4691,13 +4705,13 @@ private: | |||||
return instance.get(); | return instance.get(); | ||||
} | } | ||||
void applyStateWithAppropriateLocking (PluginState&& state) | |||||
void applyStateWithAppropriateLocking (PluginState&& state, ConcurrentWithAudioCallback concurrent) | |||||
{ | { | ||||
PortMap portStateManager (instance->ports); | PortMap portStateManager (instance->ports); | ||||
// If a plugin supports threadSafeRestore, its restore method is thread-safe | // If a plugin supports threadSafeRestore, its restore method is thread-safe | ||||
// and may be called concurrently with audio class functions. | // and may be called concurrently with audio class functions. | ||||
if (hasThreadSafeRestore) | |||||
if (hasThreadSafeRestore || concurrent == ConcurrentWithAudioCallback::no) | |||||
{ | { | ||||
state.restore (*instance, portStateManager); | state.restore (*instance, portStateManager); | ||||
} | } | ||||
@@ -4841,7 +4855,7 @@ private: | |||||
if (auto* param = parameterValues.getParamByPortIndex (header.portIndex)) | if (auto* param = parameterValues.getParamByPortIndex (header.portIndex)) | ||||
{ | { | ||||
param->setDenormalisedValueFromUi (value); | |||||
param->setDenormalisedValue (value); | |||||
} | } | ||||
else if (auto* port = controlPortStructure.getControlPortByIndex (header.portIndex)) | else if (auto* port = controlPortStructure.getControlPortByIndex (header.portIndex)) | ||||
{ | { | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1040,24 +1047,18 @@ public: | |||||
} | } | ||||
} | } | ||||
static void hostToPluginEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer, | |||||
Steinberg::Vst::IParameterChanges* parameterChanges, | |||||
const StoredMidiMapping& midiMapping) | |||||
template <typename Callback> | |||||
static void hostToPluginEventList (Steinberg::Vst::IEventList& result, | |||||
MidiBuffer& midiBuffer, | |||||
StoredMidiMapping& mapping, | |||||
Callback&& callback) | |||||
{ | { | ||||
toEventList (result, | |||||
midiBuffer, | |||||
parameterChanges, | |||||
&midiMapping, | |||||
EventConversionKind::hostToPlugin); | |||||
toEventList (result, midiBuffer, &mapping, callback); | |||||
} | } | ||||
static void pluginToHostEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer) | static void pluginToHostEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer) | ||||
{ | { | ||||
toEventList (result, | |||||
midiBuffer, | |||||
nullptr, | |||||
nullptr, | |||||
EventConversionKind::pluginToHost); | |||||
toEventList (result, midiBuffer, nullptr, [] (auto&&...) {}); | |||||
} | } | ||||
private: | private: | ||||
@@ -1073,48 +1074,70 @@ private: | |||||
pluginToHost | pluginToHost | ||||
}; | }; | ||||
static void toEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer, | |||||
Steinberg::Vst::IParameterChanges* parameterChanges, | |||||
const StoredMidiMapping* midiMapping, | |||||
EventConversionKind kind) | |||||
template <typename Callback> | |||||
static bool sendMappedParameter (const MidiMessage& msg, | |||||
StoredMidiMapping* midiMapping, | |||||
Callback&& callback) | |||||
{ | { | ||||
enum { maxNumEvents = 2048 }; // Steinberg's Host Checker states that no more than 2048 events are allowed at once | |||||
int numEvents = 0; | |||||
if (midiMapping == nullptr) | |||||
return false; | |||||
for (const auto metadata : midiBuffer) | |||||
{ | |||||
if (++numEvents > maxNumEvents) | |||||
break; | |||||
const auto controlEvent = toVst3ControlEvent (msg); | |||||
auto msg = metadata.getMessage(); | |||||
if (! controlEvent.hasValue()) | |||||
return false; | |||||
if (midiMapping != nullptr && parameterChanges != nullptr) | |||||
{ | |||||
Vst3MidiControlEvent controlEvent; | |||||
const auto controlParamID = midiMapping->getMapping (createSafeChannel (msg.getChannel()), | |||||
controlEvent->controllerNumber); | |||||
if (toVst3ControlEvent (msg, controlEvent)) | |||||
{ | |||||
const auto controlParamID = midiMapping->getMapping (createSafeChannel (msg.getChannel()), | |||||
controlEvent.controllerNumber); | |||||
if (controlParamID != Steinberg::Vst::kNoParamId) | |||||
callback (controlParamID, controlEvent->paramValue); | |||||
if (controlParamID != Steinberg::Vst::kNoParamId) | |||||
{ | |||||
Steinberg::int32 ignore; | |||||
return true; | |||||
} | |||||
if (auto* queue = parameterChanges->addParameterData (controlParamID, ignore)) | |||||
queue->addPoint (metadata.samplePosition, controlEvent.paramValue, ignore); | |||||
} | |||||
template <typename Callback> | |||||
static void processMidiMessage (Steinberg::Vst::IEventList& result, | |||||
const MidiMessageMetadata metadata, | |||||
StoredMidiMapping* midiMapping, | |||||
Callback&& callback) | |||||
{ | |||||
const auto msg = metadata.getMessage(); | |||||
continue; | |||||
} | |||||
} | |||||
if (sendMappedParameter (msg, midiMapping, std::forward<Callback> (callback))) | |||||
return; | |||||
if (auto maybeEvent = createVstEvent (msg, metadata.data, kind)) | |||||
{ | |||||
maybeEvent->busIndex = 0; | |||||
maybeEvent->sampleOffset = metadata.samplePosition; | |||||
result.addEvent (*maybeEvent); | |||||
} | |||||
const auto kind = midiMapping != nullptr ? EventConversionKind::hostToPlugin | |||||
: EventConversionKind::pluginToHost; | |||||
auto maybeEvent = createVstEvent (msg, metadata.data, kind); | |||||
if (! maybeEvent.hasValue()) | |||||
return; | |||||
maybeEvent->busIndex = 0; | |||||
maybeEvent->sampleOffset = metadata.samplePosition; | |||||
result.addEvent (*maybeEvent); | |||||
} | |||||
/* If mapping is non-null, the conversion is assumed to be host-to-plugin, or otherwise | |||||
plugin-to-host. | |||||
*/ | |||||
template <typename Callback> | |||||
static void toEventList (Steinberg::Vst::IEventList& result, | |||||
MidiBuffer& midiBuffer, | |||||
StoredMidiMapping* midiMapping, | |||||
Callback&& callback) | |||||
{ | |||||
enum { maxNumEvents = 2048 }; // Steinberg's Host Checker states that no more than 2048 events are allowed at once | |||||
int numEvents = 0; | |||||
for (const auto metadata : midiBuffer) | |||||
{ | |||||
if (++numEvents > maxNumEvents) | |||||
break; | |||||
processMidiMessage (result, metadata, midiMapping, std::forward<Callback> (callback)); | |||||
} | } | ||||
} | } | ||||
@@ -1361,28 +1384,18 @@ private: | |||||
Steinberg::Vst::ParamValue paramValue; | Steinberg::Vst::ParamValue paramValue; | ||||
}; | }; | ||||
static bool toVst3ControlEvent (const MidiMessage& msg, Vst3MidiControlEvent& result) | |||||
static Optional<Vst3MidiControlEvent> toVst3ControlEvent (const MidiMessage& msg) | |||||
{ | { | ||||
if (msg.isController()) | if (msg.isController()) | ||||
{ | |||||
result = { (Steinberg::Vst::CtrlNumber) msg.getControllerNumber(), msg.getControllerValue() / 127.0}; | |||||
return true; | |||||
} | |||||
return Vst3MidiControlEvent { (Steinberg::Vst::CtrlNumber) msg.getControllerNumber(), msg.getControllerValue() / 127.0 }; | |||||
if (msg.isPitchWheel()) | if (msg.isPitchWheel()) | ||||
{ | |||||
result = { Steinberg::Vst::kPitchBend, msg.getPitchWheelValue() / 16383.0}; | |||||
return true; | |||||
} | |||||
return Vst3MidiControlEvent { Steinberg::Vst::kPitchBend, msg.getPitchWheelValue() / 16383.0}; | |||||
if (msg.isChannelPressure()) | if (msg.isChannelPressure()) | ||||
{ | |||||
result = { Steinberg::Vst::kAfterTouch, msg.getChannelPressureValue() / 127.0}; | |||||
return true; | |||||
} | |||||
return Vst3MidiControlEvent { Steinberg::Vst::kAfterTouch, msg.getChannelPressureValue() / 127.0}; | |||||
result.controllerNumber = -1; | |||||
return false; | |||||
return {}; | |||||
} | } | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList) | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -100,6 +107,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor", | |||||
#include <public.sdk/source/common/memorystream.h> | #include <public.sdk/source/common/memorystream.h> | ||||
#include <public.sdk/source/vst/vsteditcontroller.h> | #include <public.sdk/source/vst/vsteditcontroller.h> | ||||
#include <public.sdk/source/vst/vstpresetfile.h> | #include <public.sdk/source/vst/vstpresetfile.h> | ||||
#include "pslextensions/ipslviewembedding.h" | |||||
#else | #else | ||||
// needed for VST_VERSION | // needed for VST_VERSION | ||||
#include <pluginterfaces/vst/vsttypes.h> | #include <pluginterfaces/vst/vsttypes.h> | ||||
@@ -150,6 +159,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor", | |||||
#include <public.sdk/source/vst/hosting/pluginterfacesupport.cpp> | #include <public.sdk/source/vst/hosting/pluginterfacesupport.cpp> | ||||
#endif | #endif | ||||
#include "pslextensions/ipslviewembedding.h" | |||||
//============================================================================== | //============================================================================== | ||||
namespace Steinberg | namespace Steinberg | ||||
{ | { | ||||
@@ -172,6 +183,12 @@ namespace Steinberg | |||||
DEF_CLASS_IID (Linux::IEventHandler) | DEF_CLASS_IID (Linux::IEventHandler) | ||||
#endif | #endif | ||||
} | } | ||||
namespace Presonus | |||||
{ | |||||
DEF_CLASS_IID (IPlugInViewEmbedding) | |||||
} | |||||
#endif // JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY | #endif // JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY | ||||
JUCE_END_IGNORE_WARNINGS_MSVC | JUCE_END_IGNORE_WARNINGS_MSVC | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -20,6 +27,18 @@ | |||||
#include "juce_VST3Headers.h" | #include "juce_VST3Headers.h" | ||||
#include "juce_VST3Common.h" | #include "juce_VST3Common.h" | ||||
#include "juce_ARACommon.h" | |||||
#if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS) | |||||
#include <ARA_API/ARAVST3.h> | |||||
namespace ARA | |||||
{ | |||||
DEF_CLASS_IID (IMainFactory) | |||||
DEF_CLASS_IID (IPlugInEntryPoint) | |||||
DEF_CLASS_IID (IPlugInEntryPoint2) | |||||
} | |||||
#endif | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
@@ -804,6 +823,20 @@ struct DescriptionFactory | |||||
auto numClasses = factory->countClasses(); | auto numClasses = factory->countClasses(); | ||||
// Every ARA::IMainFactory must have a matching Steinberg::IComponent. | |||||
// The match is determined by the two classes having the same name. | |||||
std::unordered_set<String> araMainFactoryClassNames; | |||||
#if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS) | |||||
for (Steinberg::int32 i = 0; i < numClasses; ++i) | |||||
{ | |||||
PClassInfo info; | |||||
factory->getClassInfo (i, &info); | |||||
if (std::strcmp (info.category, kARAMainFactoryClass) == 0) | |||||
araMainFactoryClassNames.insert (info.name); | |||||
} | |||||
#endif | |||||
for (Steinberg::int32 i = 0; i < numClasses; ++i) | for (Steinberg::int32 i = 0; i < numClasses; ++i) | ||||
{ | { | ||||
PClassInfo info; | PClassInfo info; | ||||
@@ -867,6 +900,9 @@ struct DescriptionFactory | |||||
} | } | ||||
} | } | ||||
if (araMainFactoryClassNames.find (name) != araMainFactoryClassNames.end()) | |||||
desc.hasARAExtension = true; | |||||
if (desc.uniqueId != 0) | if (desc.uniqueId != 0) | ||||
result = performOnDescription (desc); | result = performOnDescription (desc); | ||||
@@ -1330,6 +1366,72 @@ private: | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3ModuleHandle) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3ModuleHandle) | ||||
}; | }; | ||||
template <typename Type, size_t N> | |||||
static int compareWithString (Type (&charArray)[N], const String& str) | |||||
{ | |||||
return std::strncmp (str.toRawUTF8(), | |||||
charArray, | |||||
std::min (str.getNumBytesAsUTF8(), (size_t) numElementsInArray (charArray))); | |||||
} | |||||
template <typename Callback> | |||||
static void forEachARAFactory (IPluginFactory* pluginFactory, Callback&& cb) | |||||
{ | |||||
#if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS) | |||||
const auto numClasses = pluginFactory->countClasses(); | |||||
for (Steinberg::int32 i = 0; i < numClasses; ++i) | |||||
{ | |||||
PClassInfo info; | |||||
pluginFactory->getClassInfo (i, &info); | |||||
if (std::strcmp (info.category, kARAMainFactoryClass) == 0) | |||||
{ | |||||
const bool keepGoing = cb (info); | |||||
if (! keepGoing) | |||||
break; | |||||
} | |||||
} | |||||
#else | |||||
ignoreUnused (pluginFactory, cb); | |||||
#endif | |||||
} | |||||
static std::shared_ptr<const ARA::ARAFactory> getARAFactory (Steinberg::IPluginFactory* pluginFactory, const String& pluginName) | |||||
{ | |||||
std::shared_ptr<const ARA::ARAFactory> factory; | |||||
#if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS) | |||||
forEachARAFactory (pluginFactory, | |||||
[&pluginFactory, &pluginName, &factory] (const auto& pcClassInfo) | |||||
{ | |||||
if (compareWithString (pcClassInfo.name, pluginName) == 0) | |||||
{ | |||||
ARA::IMainFactory* source; | |||||
if (pluginFactory->createInstance (pcClassInfo.cid, ARA::IMainFactory::iid, (void**) &source) | |||||
== Steinberg::kResultOk) | |||||
{ | |||||
factory = getOrCreateARAFactory (source->getFactory(), | |||||
[source] (const ARA::ARAFactory*) { source->release(); }); | |||||
return false; | |||||
} | |||||
jassert (source == nullptr); | |||||
} | |||||
return true; | |||||
}); | |||||
#else | |||||
ignoreUnused (pluginFactory, pluginName); | |||||
#endif | |||||
return factory; | |||||
} | |||||
static std::shared_ptr<const ARA::ARAFactory> getARAFactory (VST3ModuleHandle& module) | |||||
{ | |||||
auto* pluginFactory = module.getPluginFactory(); | |||||
return getARAFactory (pluginFactory, module.getName()); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
struct VST3PluginWindow : public AudioProcessorEditor, | struct VST3PluginWindow : public AudioProcessorEditor, | ||||
private ComponentMovementWatcher, | private ComponentMovementWatcher, | ||||
@@ -1677,6 +1779,27 @@ private: | |||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996) // warning about overriding deprecated methods | JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996) // warning about overriding deprecated methods | ||||
//============================================================================== | |||||
static bool hasARAExtension (IPluginFactory* pluginFactory, const String& pluginClassName) | |||||
{ | |||||
bool result = false; | |||||
forEachARAFactory (pluginFactory, | |||||
[&pluginClassName, &result] (const auto& pcClassInfo) | |||||
{ | |||||
if (compareWithString (pcClassInfo.name, pluginClassName) == 0) | |||||
{ | |||||
result = true; | |||||
return false; | |||||
} | |||||
return true; | |||||
}); | |||||
return result; | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
struct VST3ComponentHolder | struct VST3ComponentHolder | ||||
{ | { | ||||
@@ -1802,6 +1925,8 @@ struct VST3ComponentHolder | |||||
totalNumInputChannels, | totalNumInputChannels, | ||||
totalNumOutputChannels); | totalNumOutputChannels); | ||||
description.hasARAExtension = hasARAExtension (factory, description.name); | |||||
return; | return; | ||||
} | } | ||||
@@ -2082,18 +2207,6 @@ public: | |||||
void setValue (float newValue) override | void setValue (float newValue) override | ||||
{ | { | ||||
pluginInstance.cachedParamValues.set (vstParamIndex, newValue); | pluginInstance.cachedParamValues.set (vstParamIndex, newValue); | ||||
pluginInstance.parameterDispatcher.push (vstParamIndex, newValue); | |||||
} | |||||
/* If the editor set the value, there's no need to notify it that the parameter | |||||
value changed. Instead, we set the cachedValue (which will be read by the | |||||
processor during the next processBlock) and notify listeners that the parameter | |||||
has changed. | |||||
*/ | |||||
void setValueFromEditor (float newValue) | |||||
{ | |||||
pluginInstance.cachedParamValues.set (vstParamIndex, newValue); | |||||
sendValueChangedMessageToListeners (newValue); | |||||
} | } | ||||
/* If we're syncing the editor to the processor, the processor won't need to | /* If we're syncing the editor to the processor, the processor won't need to | ||||
@@ -2292,7 +2405,8 @@ public: | |||||
void getExtensions (ExtensionsVisitor& visitor) const override | void getExtensions (ExtensionsVisitor& visitor) const override | ||||
{ | { | ||||
struct Extensions : public ExtensionsVisitor::VST3Client | |||||
struct Extensions : public ExtensionsVisitor::VST3Client, | |||||
public ExtensionsVisitor::ARAClient | |||||
{ | { | ||||
explicit Extensions (const VST3PluginInstance* instanceIn) : instance (instanceIn) {} | explicit Extensions (const VST3PluginInstance* instanceIn) : instance (instanceIn) {} | ||||
@@ -2305,10 +2419,21 @@ public: | |||||
return instance->setStateFromPresetFile (rawData); | return instance->setStateFromPresetFile (rawData); | ||||
} | } | ||||
void createARAFactoryAsync (std::function<void (ARAFactoryWrapper)> cb) const noexcept override | |||||
{ | |||||
cb (ARAFactoryWrapper { ::juce::getARAFactory (*(instance->holder->module)) }); | |||||
} | |||||
const VST3PluginInstance* instance = nullptr; | const VST3PluginInstance* instance = nullptr; | ||||
}; | }; | ||||
visitor.visitVST3Client (Extensions { this }); | |||||
Extensions extensions { this }; | |||||
visitor.visitVST3Client (extensions); | |||||
if (::juce::getARAFactory (*(holder->module))) | |||||
{ | |||||
visitor.visitARAClient (extensions); | |||||
} | |||||
} | } | ||||
void* getPlatformSpecificData() override { return holder->component; } | void* getPlatformSpecificData() override { return holder->component; } | ||||
@@ -2559,6 +2684,11 @@ public: | |||||
inputParameterChanges->set (cachedParamValues.getParamID (index), value); | inputParameterChanges->set (cachedParamValues.getParamID (index), value); | ||||
}); | }); | ||||
inputParameterChanges->forEach ([&] (Steinberg::int32 index, float value) | |||||
{ | |||||
parameterDispatcher.push (index, value); | |||||
}); | |||||
processor->process (data); | processor->process (data); | ||||
outputParameterChanges->forEach ([&] (Steinberg::int32 index, float value) | outputParameterChanges->forEach ([&] (Steinberg::int32 index, float value) | ||||
@@ -3024,7 +3154,9 @@ private: | |||||
{ | { | ||||
Steinberg::MemoryStream stream; | Steinberg::MemoryStream stream; | ||||
if (object->getState (&stream) == kResultTrue) | |||||
const auto result = object->getState (&stream); | |||||
if (result == kResultTrue) | |||||
{ | { | ||||
MemoryBlock info (stream.getData(), (size_t) stream.getSize()); | MemoryBlock info (stream.getData(), (size_t) stream.getSize()); | ||||
head.createNewChildElement (identifier)->addTextElement (info.toBase64Encoding()); | head.createNewChildElement (identifier)->addTextElement (info.toBase64Encoding()); | ||||
@@ -3112,7 +3244,7 @@ private: | |||||
if ((paramInfo.flags & Vst::ParameterInfo::kIsBypass) != 0) | if ((paramInfo.flags & Vst::ParameterInfo::kIsBypass) != 0) | ||||
bypassParam = param; | bypassParam = param; | ||||
std::function<AudioProcessorParameterGroup*(Vst::UnitID)> findOrCreateGroup; | |||||
std::function<AudioProcessorParameterGroup* (Vst::UnitID)> findOrCreateGroup; | |||||
findOrCreateGroup = [&groupMap, &infoMap, &findOrCreateGroup] (Vst::UnitID groupID) | findOrCreateGroup = [&groupMap, &infoMap, &findOrCreateGroup] (Vst::UnitID groupID) | ||||
{ | { | ||||
auto existingGroup = groupMap.find (groupID); | auto existingGroup = groupMap.find (groupID); | ||||
@@ -3322,8 +3454,12 @@ private: | |||||
{ | { | ||||
MidiEventList::hostToPluginEventList (*midiInputs, | MidiEventList::hostToPluginEventList (*midiInputs, | ||||
midiBuffer, | midiBuffer, | ||||
destination.inputParameterChanges, | |||||
storedMidiMapping); | |||||
storedMidiMapping, | |||||
[this] (const auto controlID, const auto paramValue) | |||||
{ | |||||
if (auto* param = this->getParameterForID (controlID)) | |||||
param->setValueNotifyingHost ((float) paramValue); | |||||
}); | |||||
} | } | ||||
destination.inputEvents = midiInputs; | destination.inputEvents = midiInputs; | ||||
@@ -3468,7 +3604,7 @@ tresult VST3HostContext::performEdit (Vst::ParamID paramID, Vst::ParamValue valu | |||||
if (auto* param = plugin->getParameterForID (paramID)) | if (auto* param = plugin->getParameterForID (paramID)) | ||||
{ | { | ||||
param->setValueFromEditor ((float) valueNormalised); | |||||
param->setValueNotifyingHost ((float) valueNormalised); | |||||
// did the plug-in already update the parameter internally | // did the plug-in already update the parameter internally | ||||
if (plugin->editController->getParamNormalized (paramID) != (float) valueNormalised) | if (plugin->editController->getParamNormalized (paramID) != (float) valueNormalised) | ||||
@@ -3670,6 +3806,22 @@ void VST3PluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& resul | |||||
} | } | ||||
} | } | ||||
void VST3PluginFormat::createARAFactoryAsync (const PluginDescription& description, ARAFactoryCreationCallback callback) | |||||
{ | |||||
if (! description.hasARAExtension) | |||||
{ | |||||
jassertfalse; | |||||
callback ({ {}, "The provided plugin does not support ARA features" }); | |||||
} | |||||
File file (description.fileOrIdentifier); | |||||
VSTComSmartPtr<IPluginFactory> pluginFactory ( | |||||
DLLHandleCache::getInstance()->findOrCreateHandle (file.getFullPathName()).getPluginFactory()); | |||||
const auto* pluginName = description.name.toRawUTF8(); | |||||
callback ({ ARAFactoryWrapper { ::juce::getARAFactory (pluginFactory, pluginName) }, {} }); | |||||
} | |||||
void VST3PluginFormat::createPluginInstance (const PluginDescription& description, | void VST3PluginFormat::createPluginInstance (const PluginDescription& description, | ||||
double, int, PluginCreationCallback callback) | double, int, PluginCreationCallback callback) | ||||
{ | { | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -61,6 +68,7 @@ public: | |||||
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override; | StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override; | ||||
bool doesPluginStillExist (const PluginDescription&) override; | bool doesPluginStillExist (const PluginDescription&) override; | ||||
FileSearchPath getDefaultLocationsToSearch() override; | FileSearchPath getDefaultLocationsToSearch() override; | ||||
void createARAFactoryAsync (const PluginDescription&, ARAFactoryCreationCallback callback) override; | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1208,10 +1215,6 @@ struct VSTPluginInstance final : public AudioPluginInstance, | |||||
wantsMidiMessages = pluginCanDo ("receiveVstMidiEvent") > 0 || isSynthPlugin(); | wantsMidiMessages = pluginCanDo ("receiveVstMidiEvent") > 0 || isSynthPlugin(); | ||||
#if JUCE_MAC && JUCE_SUPPORT_CARBON | |||||
usesCocoaNSView = ((unsigned int) pluginCanDo ("hasCockosViewAsConfig") & 0xffff0000ul) == 0xbeef0000ul; | |||||
#endif | |||||
setLatencySamples (vstEffect->latency); | setLatencySamples (vstEffect->latency); | ||||
} | } | ||||
@@ -1949,7 +1952,6 @@ struct VSTPluginInstance final : public AudioPluginInstance, | |||||
ModuleHandle::Ptr vstModule; | ModuleHandle::Ptr vstModule; | ||||
std::unique_ptr<VSTPluginFormat::ExtraFunctions> extraFunctions; | std::unique_ptr<VSTPluginFormat::ExtraFunctions> extraFunctions; | ||||
bool usesCocoaNSView = false; | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
@@ -2719,18 +2721,8 @@ public: | |||||
#elif JUCE_MAC | #elif JUCE_MAC | ||||
ignoreUnused (recursiveResize, pluginRefusesToResize, alreadyInside); | ignoreUnused (recursiveResize, pluginRefusesToResize, alreadyInside); | ||||
#if JUCE_SUPPORT_CARBON | |||||
if (! plug.usesCocoaNSView) | |||||
{ | |||||
carbonWrapper.reset (new CarbonWrapperComponent (*this)); | |||||
addAndMakeVisible (carbonWrapper.get()); | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
cocoaWrapper.reset (new NSViewComponentWithParent (plugin)); | |||||
addAndMakeVisible (cocoaWrapper.get()); | |||||
} | |||||
cocoaWrapper.reset (new NSViewComponentWithParent (plugin)); | |||||
addAndMakeVisible (cocoaWrapper.get()); | |||||
#endif | #endif | ||||
activeVSTWindows.add (this); | activeVSTWindows.add (this); | ||||
@@ -2756,9 +2748,6 @@ public: | |||||
closePluginWindow(); | closePluginWindow(); | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
#if JUCE_SUPPORT_CARBON | |||||
carbonWrapper.reset(); | |||||
#endif | |||||
cocoaWrapper.reset(); | cocoaWrapper.reset(); | ||||
#endif | #endif | ||||
@@ -2787,11 +2776,6 @@ public: | |||||
setSize (correctedBounds.getWidth(), correctedBounds.getHeight()); | setSize (correctedBounds.getWidth(), correctedBounds.getHeight()); | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
#if JUCE_SUPPORT_CARBON | |||||
if (carbonWrapper != nullptr) | |||||
carbonWrapper->setSize (correctedBounds.getWidth(), correctedBounds.getHeight()); | |||||
#endif | |||||
if (cocoaWrapper != nullptr) | if (cocoaWrapper != nullptr) | ||||
cocoaWrapper->setSize (correctedBounds.getWidth(), correctedBounds.getHeight()); | cocoaWrapper->setSize (correctedBounds.getWidth(), correctedBounds.getHeight()); | ||||
#endif | #endif | ||||
@@ -2807,25 +2791,19 @@ public: | |||||
void visibilityChanged() override | void visibilityChanged() override | ||||
{ | { | ||||
if (cocoaWrapper != nullptr) | |||||
{ | |||||
if (isShowing()) | |||||
openPluginWindow ((NSView*) cocoaWrapper->getView()); | |||||
else | |||||
closePluginWindow(); | |||||
} | |||||
if (isShowing()) | |||||
openPluginWindow ((NSView*) cocoaWrapper->getView()); | |||||
else | |||||
closePluginWindow(); | |||||
} | } | ||||
void childBoundsChanged (Component*) override | void childBoundsChanged (Component*) override | ||||
{ | { | ||||
if (cocoaWrapper != nullptr) | |||||
{ | |||||
auto w = cocoaWrapper->getWidth(); | |||||
auto h = cocoaWrapper->getHeight(); | |||||
auto w = cocoaWrapper->getWidth(); | |||||
auto h = cocoaWrapper->getHeight(); | |||||
if (w != getWidth() || h != getHeight()) | |||||
setSize (w, h); | |||||
} | |||||
if (w != getWidth() || h != getHeight()) | |||||
setSize (w, h); | |||||
} | } | ||||
void parentHierarchyChanged() override { visibilityChanged(); } | void parentHierarchyChanged() override { visibilityChanged(); } | ||||
@@ -3304,86 +3282,6 @@ private: | |||||
//============================================================================== | //============================================================================== | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
#if JUCE_SUPPORT_CARBON | |||||
struct CarbonWrapperComponent : public CarbonViewWrapperComponent | |||||
{ | |||||
CarbonWrapperComponent (VSTPluginWindow& w) : owner (w) | |||||
{ | |||||
keepPluginWindowWhenHidden = w.shouldAvoidDeletingWindow(); | |||||
setRepaintsChildHIViewWhenCreated (w.shouldRepaintCarbonWindowWhenCreated()); | |||||
} | |||||
~CarbonWrapperComponent() | |||||
{ | |||||
deleteWindow(); | |||||
} | |||||
HIViewRef attachView (WindowRef windowRef, HIViewRef /*rootView*/) override | |||||
{ | |||||
owner.openPluginWindow (windowRef); | |||||
return {}; | |||||
} | |||||
void removeView (HIViewRef) override | |||||
{ | |||||
if (owner.isOpen) | |||||
{ | |||||
owner.isOpen = false; | |||||
owner.dispatch (Vst2::plugInOpcodeCloseEditor, 0, 0, 0, 0); | |||||
owner.dispatch (Vst2::plugInOpcodeSleepEditor, 0, 0, 0, 0); | |||||
} | |||||
} | |||||
bool getEmbeddedViewSize (int& w, int& h) override | |||||
{ | |||||
Vst2::VstEditorBounds* rect = nullptr; | |||||
owner.dispatch (Vst2::plugInOpcodeGetEditorBounds, 0, 0, &rect, 0); | |||||
w = rect->rightmost - rect->leftmost; | |||||
h = rect->lower - rect->upper; | |||||
return true; | |||||
} | |||||
void handleMouseDown (int x, int y) override | |||||
{ | |||||
if (! alreadyInside) | |||||
{ | |||||
alreadyInside = true; | |||||
getTopLevelComponent()->toFront (true); | |||||
owner.dispatch (Vst2::plugInOpcodeGetMouse, x, y, 0, 0); | |||||
alreadyInside = false; | |||||
} | |||||
else | |||||
{ | |||||
PostEvent (::mouseDown, 0); | |||||
} | |||||
} | |||||
void handlePaint() override | |||||
{ | |||||
if (auto* peer = getPeer()) | |||||
{ | |||||
auto pos = peer->globalToLocal (getScreenPosition()); | |||||
Vst2::VstEditorBounds r; | |||||
r.leftmost = (int16) pos.getX(); | |||||
r.upper = (int16) pos.getY(); | |||||
r.rightmost = (int16) (r.leftmost + getWidth()); | |||||
r.lower = (int16) (r.upper + getHeight()); | |||||
owner.dispatch (Vst2::plugInOpcodeDrawEditor, 0, 0, &r, 0); | |||||
} | |||||
} | |||||
private: | |||||
VSTPluginWindow& owner; | |||||
bool alreadyInside = false; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CarbonWrapperComponent) | |||||
}; | |||||
friend struct CarbonWrapperComponent; | |||||
std::unique_ptr<CarbonWrapperComponent> carbonWrapper; | |||||
#endif | |||||
std::unique_ptr<NSViewComponentWithParent> cocoaWrapper; | std::unique_ptr<NSViewComponentWithParent> cocoaWrapper; | ||||
void resized() override | void resized() override | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -0,0 +1,190 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : ipslcontextinfo.h | |||||
// Created by : PreSonus Software Ltd., 08/2013, last updated 11/2016 | |||||
// Description : Context Information Interface | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _ipslcontextinfo_h | |||||
#define _ipslcontextinfo_h | |||||
#include "pluginterfaces/vst/vsttypes.h" | |||||
#include "pluginterfaces/base/falignpush.h" | |||||
namespace Presonus { | |||||
//************************************************************************************************ | |||||
// IContextInfoProvider | |||||
/** Callback interface to access context information from the host. Implemented by the host | |||||
as extension of Steinberg::Vst::IComponentHandler. | |||||
The host might not be able to report all available attributes at all times. Please check the | |||||
return value of getContextInfoValue() and getContextInfoString(). It's not required to implement | |||||
IContextInfoHandler on the plug-in side, but we recommend to do so. The host will then call | |||||
notifyContextInfoChange() during initialization to inform the plug-in about the initial state of | |||||
the available attributes. | |||||
Usage Example: | |||||
IComponentHandler* handler; | |||||
FUnknownPtr<IContextInfoProvider> contextInfoProvider (handler); | |||||
void PLUGIN_API MyEditController::notifyContextInfoChange () | |||||
{ | |||||
int32 channelIndex = 0; | |||||
contextInfoProvider->getContextInfoValue (channelIndex, ContextInfo::kIndex); | |||||
TChar channelName[128] = {0}; | |||||
contextInfoProvider->getContextInfoString (channelName, 128, ContextInfo::kName); | |||||
} | |||||
*/ | |||||
//************************************************************************************************ | |||||
struct IContextInfoProvider: Steinberg::FUnknown | |||||
{ | |||||
/** Get context information by identifier. */ | |||||
virtual Steinberg::tresult PLUGIN_API getContextInfoValue (Steinberg::int32& value, Steinberg::FIDString id) = 0; | |||||
/** Get context information by identifier. */ | |||||
virtual Steinberg::tresult PLUGIN_API getContextInfoString (Steinberg::Vst::TChar* string, Steinberg::int32 maxCharCount, Steinberg::FIDString id) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IContextInfoProvider, 0x483e61ea, 0x17994494, 0x8199a35a, 0xebb35e3c) | |||||
//************************************************************************************************ | |||||
// IContextInfoProvider2 | |||||
/** Extension to IContextInfoProvider enabling the plug-in to modify host context information. | |||||
Values like volume or pan support both, numeric and string representation for get and set.*/ | |||||
//************************************************************************************************ | |||||
struct IContextInfoProvider2: IContextInfoProvider | |||||
{ | |||||
using IContextInfoProvider::getContextInfoValue; | |||||
/** Get context information by identifier (floating-point). */ | |||||
virtual Steinberg::tresult PLUGIN_API getContextInfoValue (double& value, Steinberg::FIDString id) = 0; | |||||
/** Set context information by identifier (floating-point). */ | |||||
virtual Steinberg::tresult PLUGIN_API setContextInfoValue (Steinberg::FIDString id, double value) = 0; | |||||
/** Set context information by identifier (integer). */ | |||||
virtual Steinberg::tresult PLUGIN_API setContextInfoValue (Steinberg::FIDString id, Steinberg::int32 value) = 0; | |||||
/** Set context information by identifier (string). */ | |||||
virtual Steinberg::tresult PLUGIN_API setContextInfoString (Steinberg::FIDString id, Steinberg::Vst::TChar* string) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IContextInfoProvider2, 0x61e45968, 0x3d364f39, 0xb15e1733, 0x4944172b) | |||||
//************************************************************************************************ | |||||
// IContextInfoHandler | |||||
/** Notification interface for context information changes. Implemented by the plug-in as extension of | |||||
Steinberg::Vst::IEditController. */ | |||||
//************************************************************************************************ | |||||
struct IContextInfoHandler: Steinberg::FUnknown | |||||
{ | |||||
/** Called by the host if context information has changed. */ | |||||
virtual void PLUGIN_API notifyContextInfoChange () = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IContextInfoHandler, 0xc3b17bc0, 0x2c174494, 0x80293402, 0xfbc4bbf8) | |||||
//************************************************************************************************ | |||||
// IContextInfoHandler2 | |||||
/** Replacement of IContextInfoHandler passing additional information about what changed on the host-side. | |||||
This interface will be preferred if implemented by the plug-in. It is required to | |||||
receive certain notifications like volume, pan, etc. */ | |||||
//************************************************************************************************ | |||||
struct IContextInfoHandler2: Steinberg::FUnknown | |||||
{ | |||||
/** Called by the host if context information has changed. | |||||
The identifier (id) is empty for the inital update. */ | |||||
virtual void PLUGIN_API notifyContextInfoChange (Steinberg::FIDString id) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IContextInfoHandler2, 0x31e29a7a, 0xe55043ad, 0x8b95b9b8, 0xda1fbe1e) | |||||
//************************************************************************************************ | |||||
// Context Information Attributes | |||||
//************************************************************************************************ | |||||
namespace ContextInfo | |||||
{ | |||||
/** Channel types. */ | |||||
enum ChannelType | |||||
{ | |||||
kTrack = 0, ///< audio track | |||||
kBus, ///< audio bus | |||||
kFX, ///< FX channel | |||||
kSynth, ///< output of virtual instrument | |||||
kIn, ///< input from audio driver | |||||
kOut ///< output to audio driver (main or sub-out) | |||||
}; | |||||
/** Channel index mode. */ | |||||
enum ChannelIndexMode | |||||
{ | |||||
kFlatIndex = 0, ///< channel indices are contiguous (example: track 1, track 2, bus 3, bus 4) | |||||
kPerTypeIndex ///< channel indices restarts at zero for each type (example: track 1, track 2, bus 1, bus 2) | |||||
}; | |||||
// per instance | |||||
const Steinberg::FIDString kID = "id"; ///< (R) channel identifier, use to compare identity (string) | |||||
const Steinberg::FIDString kName = "name"; ///< (R/W) channel name, can be displayed to the user (string) | |||||
const Steinberg::FIDString kType = "type"; ///< (R) channel type (int32, see ChannelType enumeration) | |||||
const Steinberg::FIDString kMain = "main"; ///< (R) channel is main output (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kIndex = "index"; ///< (R) channel index (int32, starts at zero) | |||||
const Steinberg::FIDString kColor = "color"; ///< (R/W) channel color (int32: RGBA) | |||||
const Steinberg::FIDString kVisibility = "visibility"; ///< (R) channel visibility (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kSelected = "selected"; ///< (R/W) selection state, channel is selected exlusively and scrolled into view on write (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kMultiSelect = "multiselect"; ///< (W) select channel without unselecting others (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kFocused = "focused"; ///< (R) focus for user input when multiple channels are selected (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kRegionName = "regionName"; ///< (R) name of region/event for region/event-based effects (string) | |||||
const Steinberg::FIDString kRegionSelected = "regionSelected"; ///< (R) selection state of region/event for region/event-based effects (int32, 0: false, 1: true) | |||||
// per instance (requires IContextInfoHandler2 on plug-in side) | |||||
const Steinberg::FIDString kVolume = "volume"; ///< (R/W) volume factor [float, 0. = -oo dB, 1. = 0dB, etc.], also available as string | |||||
const Steinberg::FIDString kMaxVolume = "maxVolume"; ///< (R) maximum volume factor [float, 1. = 0dB], also available as string | |||||
const Steinberg::FIDString kPan = "pan"; ///< (R/W) stereo panning [float, < 0.5 = (L), 0.5 = (C), > 0.5 = (R)], also available as string | |||||
const Steinberg::FIDString kMute = "mute"; ///< (R/W) mute (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kSolo = "solo"; ///< (R/W) solo (int32, 0: false, 1: true) | |||||
const Steinberg::FIDString kSendCount = "sendcount"; ///< (R) send count [int] | |||||
const Steinberg::FIDString kSendLevel = "sendlevel"; ///< (R/W) send level factor, index is appended to id (e.g. "sendlevel0" for first), also available as string | |||||
const Steinberg::FIDString kMaxSendLevel = "maxSendlevel"; ///< (R) maximum send level factor, also available as string | |||||
// global | |||||
const Steinberg::FIDString kActiveDocumentID = "activeDocumentID"; ///< (R) active document identifier, use to get identity of the active document (string) | |||||
const Steinberg::FIDString kDocumentID = "documentID"; ///< (R) document identifier, use to compare identity (string) | |||||
const Steinberg::FIDString kDocumentName = "documentName"; ///< (R) document name, can be displayed to user (string) | |||||
const Steinberg::FIDString kDocumentFolder = "documentFolder"; ///< (R) document folder (string) | |||||
const Steinberg::FIDString kAudioFolder = "audioFolder"; ///< (R) folder for audio files (string) | |||||
const Steinberg::FIDString kIndexMode = "indexMode"; ///< (R) channel index mode (default is flat, see ChannelIndexMode enumeration) | |||||
} | |||||
} // namespace Presonus | |||||
#include "pluginterfaces/base/falignpop.h" | |||||
#endif // _ipslcontextinfo_h |
@@ -0,0 +1,108 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : ipsleditcontroller.h | |||||
// Created by : PreSonus Software Ltd., 02/2017, last updated 10/2017 | |||||
// Description : Plug-in Edit Controller Extension Interface | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _ipsleditcontroller_h | |||||
#define _ipsleditcontroller_h | |||||
#include "pluginterfaces/vst/vsttypes.h" | |||||
#include "pluginterfaces/base/funknown.h" | |||||
#include "pluginterfaces/base/falignpush.h" | |||||
namespace Steinberg { | |||||
namespace Vst { | |||||
class IEditController; }} | |||||
namespace Presonus { | |||||
/** Parameter extra flags. Used with IEditControllerExtra. */ | |||||
enum ParamExtraFlags | |||||
{ | |||||
kParamFlagMicroEdit = 1<<0 ///< parameter should be displayed in host micro view | |||||
}; | |||||
/** Automation mode. Used with IEditControllerExtra. */ | |||||
enum AutomationMode | |||||
{ | |||||
kAutomationNone = 0, ///< no automation data available | |||||
kAutomationOff, ///< data available, but mode is set to off | |||||
kAutomationRead, ///< data + read mode | |||||
kAutomationTouch, ///< data + touch mode | |||||
kAutomationLatch, ///< data + latch mode | |||||
kAutomationWrite ///< data + write mode | |||||
}; | |||||
/** Slave mode. Used with ISlaveControllerHandler. */ | |||||
enum SlaveMode | |||||
{ | |||||
kSlaveModeNormal, ///< plug-in used in different location following given master | |||||
kSlaveModeLowLatencyClone ///< plug-in used as hidden slave for low latency processing following given master | |||||
}; | |||||
//************************************************************************************************ | |||||
// IEditControllerExtra | |||||
/** Extension to Steinberg::Vst::IEditController with additonal flags and notifications | |||||
not available in the standard edit controller interface. */ | |||||
//************************************************************************************************ | |||||
struct IEditControllerExtra: Steinberg::FUnknown | |||||
{ | |||||
/** Get extra flags for given parameter (see ParamExtraFlags). */ | |||||
virtual Steinberg::int32 PLUGIN_API getParamExtraFlags (Steinberg::Vst::ParamID id) = 0; | |||||
/** Set automation mode for given parameter (see AutomationMode). */ | |||||
virtual Steinberg::tresult PLUGIN_API setParamAutomationMode (Steinberg::Vst::ParamID id, Steinberg::int32 automationMode) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IEditControllerExtra, 0x50553fd9, 0x1d2c4c24, 0xb410f484, 0xc5fb9f3f) | |||||
//************************************************************************************************ | |||||
// ISlaveControllerHandler | |||||
/** Extension to Steinberg::Vst::IEditController used to notify the plug-in about slave instances. | |||||
The host might decide to use "cloned" (slave) instances in various scenarios, e.g. to process | |||||
audio paths with different latencies simultaneously or to synchronize grouped plug-in instances | |||||
between multiple mixer channels - see SlaveMode. In this case multiple plug-in instances are active | |||||
at the same time even though it looks like one to the user, i.e. only the editor of the master | |||||
instance is visible and can be used to change parameters. The edit controller implementation has | |||||
to synchronize parameter changes between instances that aren't visible to the host internally. | |||||
*/ | |||||
//************************************************************************************************ | |||||
struct ISlaveControllerHandler: Steinberg::FUnknown | |||||
{ | |||||
/** Add slave edit controller. Implementation must sync non-automatable parameters between | |||||
this instance (master) and given slave instance internally, i.e. when the master (this) | |||||
changes update all connected slaves. | |||||
*/ | |||||
virtual Steinberg::tresult PLUGIN_API addSlave (Steinberg::Vst::IEditController* slave, Steinberg::int32 slaveMode) = 0; | |||||
/** Remove slave edit controller. */ | |||||
virtual Steinberg::tresult PLUGIN_API removeSlave (Steinberg::Vst::IEditController* slave) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (ISlaveControllerHandler, 0xd93894bd, 0x67454c29, 0x977ae2f5, 0xdb380434) | |||||
} // namespace Presonus | |||||
#include "pluginterfaces/base/falignpop.h" | |||||
#endif // _ipsleditcontroller_h |
@@ -0,0 +1,53 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : ipslgainreduction.h | |||||
// Created by : PreSonus Software Ltd., 03/2015 | |||||
// Description : Plug-in Gain Reduction Interface | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _ipslgainreduction_h | |||||
#define _ipslgainreduction_h | |||||
#include "pluginterfaces/base/funknown.h" | |||||
#include "pluginterfaces/base/falignpush.h" | |||||
namespace Presonus { | |||||
//************************************************************************************************ | |||||
// IGainReductionInfo | |||||
/** Interface to report gain reduction imposed to the audio signal by the plug-in to the | |||||
host for display in the UI. Implemented by the VST3 edit controller class. | |||||
*/ | |||||
//************************************************************************************************ | |||||
struct IGainReductionInfo: Steinberg::FUnknown | |||||
{ | |||||
/** Get current gain reduction for display. The returned value in dB is either 0.0 (no reduction) | |||||
or negative. The host calls this function periodically while the plug-in is active. | |||||
The value is used AS IS for UI display purposes, without imposing additional ballistics or | |||||
presentation latency compensation. Be sure to return zero if processing is bypassed internally. | |||||
For multiple reduction stages, please report the sum in dB here. | |||||
*/ | |||||
virtual double PLUGIN_API getGainReductionValueInDb () = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IGainReductionInfo, 0x8e3c292c, 0x95924f9d, 0xb2590b1e, 0x100e4198) | |||||
} // namespace Presonus | |||||
#include "pluginterfaces/base/falignpop.h" | |||||
#endif // _ipslgainreduction_h |
@@ -0,0 +1,121 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : ipslhostcommands.h | |||||
// Created by : PreSonus Software Ltd., 11/2009 | |||||
// Description : Host Command Interface | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _ipslhostcommands_h | |||||
#define _ipslhostcommands_h | |||||
#include "pluginterfaces/vst/vsttypes.h" | |||||
#include "pluginterfaces/base/funknown.h" | |||||
#include "pluginterfaces/base/falignpush.h" | |||||
namespace Steinberg { | |||||
class IPlugView; } | |||||
namespace Presonus { | |||||
struct ICommandList; | |||||
//************************************************************************************************ | |||||
// IHostCommandHandler | |||||
/** Callback interface to access host-specific parameter commands to be integrated | |||||
into a context menu inside the plug-in editor. Implemented as extension of | |||||
Steinberg::Vst::IComponentHandler. | |||||
Please note that the intention of this set of interfaces is not to allow a generic menu | |||||
implementation. This is the responsibility of a GUI toolkit. It basically provides | |||||
a way to enumerate and execute commands anonymously, i.e. the plug-in does not have to | |||||
know the exact sematics of the commands and the host does not break the consistency of | |||||
the plug-in GUI. | |||||
Usage Example: | |||||
IComponentHandler* handler; | |||||
FUnknownPtr<IHostCommandHandler> commandHandler (handler); | |||||
if(commandHandler) | |||||
if(ICommandList* commandList = commandHandler->createParamCommands (kMyParamId)) | |||||
{ | |||||
FReleaser commandListReleaser (commandList); | |||||
commandHandler->popupCommandMenu (commandList, xPos, yPos); | |||||
} | |||||
*/ | |||||
//************************************************************************************************ | |||||
struct IHostCommandHandler: Steinberg::FUnknown | |||||
{ | |||||
/** Create list of currently available host commands for given parameter. | |||||
The command list has a short lifecycle, it is recreated whenever | |||||
a context menu should appear. The returned pointer can be null, otherwise | |||||
it has to be released. */ | |||||
virtual ICommandList* PLUGIN_API createParamCommands (Steinberg::Vst::ParamID tag) = 0; | |||||
/** Helper to popup a command menu at given position. | |||||
Coordinates are relative to view or in screen coordintes if view is null. | |||||
Can be used for testing purpose, if the plug-in does not have its own context menu implementation | |||||
or if it wants to use the look & feel of the host menu. This method is not supposed | |||||
to support command lists implemented by the plug-in. */ | |||||
virtual Steinberg::tresult PLUGIN_API popupCommandMenu (ICommandList* commandList, Steinberg::int32 xPos, Steinberg::int32 yPos, Steinberg::IPlugView* view = 0) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IHostCommandHandler, 0xF92032CD, 0x7A84407C, 0xABE6F863, 0x058EA6C2) | |||||
//************************************************************************************************ | |||||
// CommandInfo | |||||
/** Describes a single command. */ | |||||
//************************************************************************************************ | |||||
struct CommandInfo | |||||
{ | |||||
Steinberg::Vst::String128 title; ///< command title (possibly localized into active host language) | |||||
Steinberg::int32 flags; ///< command flags | |||||
enum CommandFlags | |||||
{ | |||||
kCanExecute = 1<<0, ///< used to display command enabled/disabled | |||||
kIsSeparator = 1<<1, ///< not a command, it's a separator | |||||
kIsChecked = 1<<2 ///< used to display command with a check mark | |||||
}; | |||||
}; | |||||
//************************************************************************************************ | |||||
// ICommandList | |||||
/** Describes a list of commands. */ | |||||
//************************************************************************************************ | |||||
struct ICommandList: Steinberg::FUnknown | |||||
{ | |||||
/** Returns the number of commands. */ | |||||
virtual Steinberg::int32 PLUGIN_API getCommandCount () = 0; | |||||
/** Get command information for a given index. */ | |||||
virtual Steinberg::tresult PLUGIN_API getCommandInfo (Steinberg::int32 index, CommandInfo& info) = 0; | |||||
/** Execute command at given index. */ | |||||
virtual Steinberg::tresult PLUGIN_API executeCommand (Steinberg::int32 index) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (ICommandList, 0xC5A687DB, 0x82F344E9, 0xB378254A, 0x47C4D712) | |||||
} // namespace Presonus | |||||
#include "pluginterfaces/base/falignpop.h" | |||||
#endif // _ipslhostcommands_h |
@@ -0,0 +1,53 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : ipslviewembedding.h | |||||
// Created by : PreSonus Software Ltd., 05/2012 | |||||
// Description : Plug-in View Embedding Interface | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _ipslviewembedding_h | |||||
#define _ipslviewembedding_h | |||||
#include "pluginterfaces/base/funknown.h" | |||||
#include "pluginterfaces/base/falignpush.h" | |||||
namespace Steinberg { | |||||
class IPlugView; } | |||||
namespace Presonus { | |||||
//************************************************************************************************ | |||||
// IPlugInViewEmbedding | |||||
/** Support for plug-in view embedding, to be implemented by the VST3 controller class. */ | |||||
//************************************************************************************************ | |||||
class IPlugInViewEmbedding: public Steinberg::FUnknown | |||||
{ | |||||
public: | |||||
/** Check if view embedding is supported. */ | |||||
virtual Steinberg::TBool PLUGIN_API isViewEmbeddingSupported () = 0; | |||||
/** Inform plug-in that its view will be embedded. */ | |||||
virtual Steinberg::tresult PLUGIN_API setViewIsEmbedded (Steinberg::IPlugView* view, Steinberg::TBool embedded) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IPlugInViewEmbedding, 0xda57e6d1, 0x1f3242d1, 0xad9c1a82, 0xfdb95695) | |||||
} // namespace Presonus | |||||
#include "pluginterfaces/base/falignpop.h" | |||||
#endif // _ipslviewembedding_h |
@@ -0,0 +1,67 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : ipslviewscaling.h | |||||
// Created by : PreSonus Software Ltd., 03/2015 | |||||
// Description : Plug-in View DPI Scaling Interface | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _ipslviewscaling_h | |||||
#define _ipslviewscaling_h | |||||
#include "pluginterfaces/base/funknown.h" | |||||
#include "pluginterfaces/base/falignpush.h" | |||||
namespace Presonus { | |||||
//************************************************************************************************ | |||||
// IPlugInViewScaling | |||||
/** Support for plug-in view content scaling, to be implemented by the VST3 IPlugView class. | |||||
On Windows, if a process is "DPI-aware" and the system DPI setting is different from the default | |||||
value of 96 DPI, the application is responsible to scale the contents of its windows accordingly, | |||||
including child windows provided by 3rd party plug-ins. | |||||
This interface is used by the host to inform the plug-in about the current scaling factor. | |||||
The scaling factor is used to convert user space coordinates aka DIPs (device-independent pixels) | |||||
to physical pixels on screen. | |||||
The plug-in has to be prepared to deal with the following scaling factors: | |||||
96 DPI = 100% scaling (factor = 1.0) | |||||
120 DPI = 125% scaling (factor = 1.25) | |||||
144 DPI = 150% scaling (factor = 1.5) | |||||
192 DPI = 200% scaling (factor = 2.0) | |||||
On Windows 8.1 or later DPI settings are per monitor. The scaling factor for a window can change | |||||
when it is moved between screens. | |||||
*/ | |||||
//************************************************************************************************ | |||||
struct IPlugInViewScaling: Steinberg::FUnknown | |||||
{ | |||||
/** Inform the view about the current content scaling factor. The scaling factor can change | |||||
if the window is moved between screens. | |||||
*/ | |||||
virtual Steinberg::tresult PLUGIN_API setContentScaleFactor (float factor) = 0; | |||||
static const Steinberg::FUID iid; | |||||
}; | |||||
DECLARE_CLASS_IID (IPlugInViewScaling, 0x65ed9690, 0x8ac44525, 0x8aadef7a, 0x72ea703f) | |||||
} // namespace Presonus | |||||
#include "pluginterfaces/base/falignpop.h" | |||||
#endif // _ipslviewscaling_h |
@@ -0,0 +1,57 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : pslauextensions.h | |||||
// Created by : PreSonus Software Ltd., 08/2017, last updated 10/2017 | |||||
// Description : PreSonus-specific AU API Extensions | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _pslauextensions_h | |||||
#define _pslauextensions_h | |||||
#ifdef __cplusplus | |||||
namespace Presonus { | |||||
#endif | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
// Property IDs | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
/** This AU property in the global scope is of type CFArrayRef and is writable by the host. | |||||
The elements of the array are of type CFDataRef which encapsulate SlaveMode structures. | |||||
For more details, please check the documentation of Presonus::ISlaveControllerHandler. */ | |||||
static const AudioUnitPropertyID kSlaveEffectsPropID = 0x50534C01; | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
// Data types | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
enum SlaveMode | |||||
{ | |||||
kSlaveModeNormal, ///< plug-in used in different location following given master | |||||
kSlaveModeLowLatencyClone ///< plug-in used as hidden slave for low latency processing following given master | |||||
}; | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
struct SlaveEffect | |||||
{ | |||||
AudioUnit unit; ///< Audio Unit reference | |||||
SInt32 mode; ///< SlaveMode | |||||
}; | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif // _pslauextensions_h |
@@ -0,0 +1,111 @@ | |||||
//************************************************************************************************ | |||||
// | |||||
// PreSonus Plug-In Extensions | |||||
// Written and placed in the PUBLIC DOMAIN by PreSonus Software Ltd. | |||||
// | |||||
// Filename : pslvst2extensions.h | |||||
// Created by : PreSonus Software Ltd., 05/2012, last updated 08/2017 | |||||
// Description : PreSonus-specific VST2 API Extensions | |||||
// | |||||
//************************************************************************************************ | |||||
/* | |||||
DISCLAIMER: | |||||
The PreSonus Plug-In Extensions are host-specific extensions of existing proprietary technologies, | |||||
provided to the community on an AS IS basis. They are not part of any official 3rd party SDK and | |||||
PreSonus is not affiliated with the owner of the underlying technology in any way. | |||||
*/ | |||||
//************************************************************************************************ | |||||
#ifndef _pslvst2extensions_h | |||||
#define _pslvst2extensions_h | |||||
namespace Presonus { | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
// CanDo Strings | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
/** Identifiers to be passed to VST2's canDo() method. */ | |||||
namespace PlugCanDos | |||||
{ | |||||
/** Check if view can be resized by the host. */ | |||||
static const char* canDoViewResize = "supportsViewResize"; | |||||
/** Check if view can be embedded by the host. */ | |||||
static const char* canDoViewEmbedding = "supportsViewEmbedding"; | |||||
/** Check if view scaling for high-DPI is supported by the plug-in. */ | |||||
static const char* canDoViewDpiScaling = "supportsViewDpiScaling"; | |||||
/** Check if gain reduction reporting is supported by the plug-in. */ | |||||
static const char* canDoGainReductionInfo = "supportsGainReductionInfo"; | |||||
/** Check if slave effects are supported by plug-in. */ | |||||
static const char* canDoSlaveEffects = "supportsSlaveEffects"; | |||||
} | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
// Opcodes | |||||
////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
/** Vendor-specific opcodes a VST2 plug-in can implement to add non-standard features like | |||||
embedding its views as subview into the host, resizing from the host, high-DPI scaling, etc. | |||||
Embedding corresponds to the Presonus::IPlugInViewEmbedding VST3 extended interface. | |||||
Resizing works like VST3's checkSizeConstraint() and onSize() methods, VST3's canResize() | |||||
is defined via canDoViewResize. | |||||
For "DPI-aware" host applications on the Windows platform a similar mimic to the | |||||
Presonus::IPlugInViewScaling VST3 extended interface is defined here. | |||||
Gain reduction reporting corresponds to the Presonus::IGainReductionInfo VST3 interface. | |||||
Slave effect handling corresponds to the Presonus::ISlaveControllerHandler VST3 interface. | |||||
*/ | |||||
enum Opcodes | |||||
{ | |||||
/** PreSonus vendor ID - distinguishes our calls from other VST2 extensions. | |||||
Pass this vendor ID as "index" (aka "lArg1") parameter for vendor specific calls. */ | |||||
kVendorID = 'PreS', | |||||
/** The host can suggest a new editor size, and the plug-in can modify the suggested | |||||
size to a suitable value if it cannot resize to the given values. | |||||
The ptrArg is a ERect* to the input/output rect. This differs from the ERect** | |||||
used by effEditGetRect, because here the rect is owned by the host, not the plug-in. | |||||
The result is 0 on failure, 1 on success. */ | |||||
kEffEditCheckSizeConstraints = 'AeCc', | |||||
/** The host can set a new size after negotiating the size via the above | |||||
kEffEditCheckSizeConstraints, triggering the actual resizing. | |||||
The ptrArg is a ERect* to the input/output rect. This differs from the ERect** | |||||
used by effEditGetRect, because here the rect is owned by the host, not the plug-in. | |||||
The result is 0 on failure, 1 on success. */ | |||||
kEffEditSetRect = 'AeSr', | |||||
/** When the view is embedded, it may need to adjust its UI, e.g. by suppressing | |||||
its built-in resizing facility because this is then controlled by the host. | |||||
The ptrArg is a VstInt32*, pointing to 0 to disable or to 1 to enable embedding. | |||||
Per default, embedding is disabled until the host calls this to indicate otherwise. */ | |||||
kEffEditSetEmbedded = 'AeEm', | |||||
/** Inform the view about the current content scaling factor. The factor is passed in the opt argument. | |||||
For more details, please check the documentation of Presonus::IPlugInViewScaling. */ | |||||
kEffEditSetContentScaleFactor = 'AeCs', | |||||
/** Get current gain reduction for display. The ptrArg is a float* to be set to the dB value. | |||||
For more details, please check the documentation of Presonus::IGainReductionInfo. */ | |||||
kEffGetGainReductionValueInDb = 'GRdB', | |||||
/** Add slave effect. The ptrArg is a pointer to the slave AEffect, the 'opt' float transmits the mode (see enum SlaveMode). | |||||
For more details, please check the documentation of Presonus::ISlaveControllerHandler. */ | |||||
kEffAddSlave = 'AdSl', | |||||
/** Remove slave effect. The ptrArg is a pointer to the slave AEffect. | |||||
For more details, please check the documentation of Presonus::ISlaveControllerHandler. */ | |||||
kEffRemoveSlave = 'RmSl' | |||||
}; | |||||
} // namespace Presonus | |||||
#endif // _pslvst2extensions_h |
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -27,7 +34,9 @@ | |||||
#define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 | #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 | ||||
#define JUCE_CORE_INCLUDE_OBJC_HELPERS 1 | #define JUCE_CORE_INCLUDE_OBJC_HELPERS 1 | ||||
#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 | |||||
#endif | |||||
#define JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER 1 | #define JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER 1 | ||||
#define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 | #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 | ||||
@@ -36,14 +45,7 @@ | |||||
#include <juce_core/containers/juce_Optional.h> | #include <juce_core/containers/juce_Optional.h> | ||||
//============================================================================== | //============================================================================== | ||||
#if JUCE_MAC | |||||
#if JUCE_SUPPORT_CARBON && (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) | |||||
#include <Carbon/Carbon.h> | |||||
#include <juce_gui_extra/native/juce_mac_CarbonViewWrapperComponent.h> | |||||
#endif | |||||
#endif | |||||
#if (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3) && (JUCE_LINUX || JUCE_BSD) | |||||
#if (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3) && (JUCE_LINUX || JUCE_BSD) && ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
#include <sys/utsname.h> | #include <sys/utsname.h> | ||||
@@ -202,17 +204,23 @@ private: | |||||
#include "format_types/juce_LegacyAudioParameter.cpp" | #include "format_types/juce_LegacyAudioParameter.cpp" | ||||
#include "processors/juce_AudioProcessor.cpp" | #include "processors/juce_AudioProcessor.cpp" | ||||
#include "processors/juce_AudioPluginInstance.cpp" | #include "processors/juce_AudioPluginInstance.cpp" | ||||
#include "processors/juce_AudioProcessorEditor.cpp" | |||||
#include "processors/juce_AudioProcessorGraph.cpp" | #include "processors/juce_AudioProcessorGraph.cpp" | ||||
#include "processors/juce_GenericAudioProcessorEditor.cpp" | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include "processors/juce_AudioProcessorEditor.cpp" | |||||
#include "processors/juce_GenericAudioProcessorEditor.cpp" | |||||
#endif | |||||
#include "processors/juce_PluginDescription.cpp" | #include "processors/juce_PluginDescription.cpp" | ||||
#include "format_types/juce_ARACommon.cpp" | |||||
#include "format_types/juce_LADSPAPluginFormat.cpp" | #include "format_types/juce_LADSPAPluginFormat.cpp" | ||||
#include "format_types/juce_VSTPluginFormat.cpp" | #include "format_types/juce_VSTPluginFormat.cpp" | ||||
#include "format_types/juce_VST3PluginFormat.cpp" | #include "format_types/juce_VST3PluginFormat.cpp" | ||||
#include "format_types/juce_AudioUnitPluginFormat.mm" | #include "format_types/juce_AudioUnitPluginFormat.mm" | ||||
#include "scanning/juce_KnownPluginList.cpp" | |||||
#include "scanning/juce_PluginDirectoryScanner.cpp" | |||||
#include "scanning/juce_PluginListComponent.cpp" | |||||
#include "format_types/juce_ARAHosting.cpp" | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include "scanning/juce_KnownPluginList.cpp" | |||||
#include "scanning/juce_PluginDirectoryScanner.cpp" | |||||
#include "scanning/juce_PluginListComponent.cpp" | |||||
#endif | |||||
#include "processors/juce_AudioProcessorParameterGroup.cpp" | #include "processors/juce_AudioProcessorParameterGroup.cpp" | ||||
#include "utilities/juce_AudioProcessorParameterWithID.cpp" | #include "utilities/juce_AudioProcessorParameterWithID.cpp" | ||||
#include "utilities/juce_RangedAudioParameter.cpp" | #include "utilities/juce_RangedAudioParameter.cpp" | ||||
@@ -220,10 +228,13 @@ private: | |||||
#include "utilities/juce_AudioParameterInt.cpp" | #include "utilities/juce_AudioParameterInt.cpp" | ||||
#include "utilities/juce_AudioParameterBool.cpp" | #include "utilities/juce_AudioParameterBool.cpp" | ||||
#include "utilities/juce_AudioParameterChoice.cpp" | #include "utilities/juce_AudioParameterChoice.cpp" | ||||
#include "utilities/juce_ParameterAttachments.cpp" | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include "utilities/juce_ParameterAttachments.cpp" | |||||
#endif | |||||
#include "utilities/juce_AudioProcessorValueTreeState.cpp" | #include "utilities/juce_AudioProcessorValueTreeState.cpp" | ||||
#include "utilities/juce_PluginHostType.cpp" | #include "utilities/juce_PluginHostType.cpp" | ||||
#include "utilities/juce_NativeScaleFactorNotifier.cpp" | #include "utilities/juce_NativeScaleFactorNotifier.cpp" | ||||
#include "utilities/ARA/juce_ARA_utils.cpp" | |||||
#include "format_types/juce_LV2PluginFormat.cpp" | #include "format_types/juce_LV2PluginFormat.cpp" | ||||
@@ -231,3 +242,8 @@ private: | |||||
#include "format_types/juce_VST3PluginFormat_test.cpp" | #include "format_types/juce_VST3PluginFormat_test.cpp" | ||||
#include "format_types/juce_LV2PluginFormat_test.cpp" | #include "format_types/juce_LV2PluginFormat_test.cpp" | ||||
#endif | #endif | ||||
#if JUCE_AUDIOPROCESSOR_NO_GUI | |||||
// commonly used classes in DSP code | |||||
namespace juce { Colour::Colour(juce::uint32) noexcept {} } | |||||
#endif |
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -94,6 +101,17 @@ | |||||
#define JUCE_PLUGINHOST_LV2 0 | #define JUCE_PLUGINHOST_LV2 0 | ||||
#endif | #endif | ||||
/** Config: JUCE_PLUGINHOST_ARA | |||||
Enables the ARA plugin extension hosting classes. You will need to download the ARA SDK and specify the | |||||
path to it either in the Projucer, using juce_set_ara_sdk_path() in your CMake project file. | |||||
The directory can be obtained by recursively cloning https://github.com/Celemony/ARA_SDK and checking out | |||||
the tag releases/2.1.0. | |||||
*/ | |||||
#ifndef JUCE_PLUGINHOST_ARA | |||||
#define JUCE_PLUGINHOST_ARA 0 | |||||
#endif | |||||
/** Config: JUCE_CUSTOM_VST3_SDK | /** Config: JUCE_CUSTOM_VST3_SDK | ||||
If enabled, the embedded VST3 SDK in JUCE will not be added to the project and instead you should | If enabled, the embedded VST3 SDK in JUCE will not be added to the project and instead you should | ||||
add the path to your custom VST3 SDK to the project's header search paths. Most users shouldn't | add the path to your custom VST3 SDK to the project's header search paths. Most users shouldn't | ||||
@@ -107,10 +125,6 @@ | |||||
// #error "You need to set either the JUCE_PLUGINHOST_AU and/or JUCE_PLUGINHOST_VST and/or JUCE_PLUGINHOST_VST3 and/or JUCE_PLUGINHOST_LADSPA flags if you're using this module!" | // #error "You need to set either the JUCE_PLUGINHOST_AU and/or JUCE_PLUGINHOST_VST and/or JUCE_PLUGINHOST_VST3 and/or JUCE_PLUGINHOST_LADSPA flags if you're using this module!" | ||||
#endif | #endif | ||||
#if ! (defined (JUCE_SUPPORT_CARBON) || JUCE_64BIT || JUCE_IOS) | |||||
#define JUCE_SUPPORT_CARBON 1 | |||||
#endif | |||||
#ifndef JUCE_SUPPORT_LEGACY_AUDIOPROCESSOR | #ifndef JUCE_SUPPORT_LEGACY_AUDIOPROCESSOR | ||||
#define JUCE_SUPPORT_LEGACY_AUDIOPROCESSOR 1 | #define JUCE_SUPPORT_LEGACY_AUDIOPROCESSOR 1 | ||||
#endif | #endif | ||||
@@ -119,18 +133,23 @@ | |||||
#include "utilities/juce_VSTCallbackHandler.h" | #include "utilities/juce_VSTCallbackHandler.h" | ||||
#include "utilities/juce_VST3ClientExtensions.h" | #include "utilities/juce_VST3ClientExtensions.h" | ||||
#include "utilities/juce_NativeScaleFactorNotifier.h" | #include "utilities/juce_NativeScaleFactorNotifier.h" | ||||
#include "format_types/juce_ARACommon.h" | |||||
#include "utilities/juce_ExtensionsVisitor.h" | #include "utilities/juce_ExtensionsVisitor.h" | ||||
#include "processors/juce_AudioProcessorParameter.h" | #include "processors/juce_AudioProcessorParameter.h" | ||||
#include "processors/juce_HostedAudioProcessorParameter.h" | #include "processors/juce_HostedAudioProcessorParameter.h" | ||||
#include "processors/juce_AudioProcessorEditorHostContext.h" | #include "processors/juce_AudioProcessorEditorHostContext.h" | ||||
#include "processors/juce_AudioProcessorEditor.h" | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include "processors/juce_AudioProcessorEditor.h" | |||||
#endif | |||||
#include "processors/juce_AudioProcessorListener.h" | #include "processors/juce_AudioProcessorListener.h" | ||||
#include "processors/juce_AudioProcessorParameterGroup.h" | #include "processors/juce_AudioProcessorParameterGroup.h" | ||||
#include "processors/juce_AudioProcessor.h" | #include "processors/juce_AudioProcessor.h" | ||||
#include "processors/juce_PluginDescription.h" | #include "processors/juce_PluginDescription.h" | ||||
#include "processors/juce_AudioPluginInstance.h" | #include "processors/juce_AudioPluginInstance.h" | ||||
#include "processors/juce_AudioProcessorGraph.h" | #include "processors/juce_AudioProcessorGraph.h" | ||||
#include "processors/juce_GenericAudioProcessorEditor.h" | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include "processors/juce_GenericAudioProcessorEditor.h" | |||||
#endif | |||||
#include "format/juce_AudioPluginFormat.h" | #include "format/juce_AudioPluginFormat.h" | ||||
#include "format/juce_AudioPluginFormatManager.h" | #include "format/juce_AudioPluginFormatManager.h" | ||||
#include "scanning/juce_KnownPluginList.h" | #include "scanning/juce_KnownPluginList.h" | ||||
@@ -140,6 +159,7 @@ | |||||
#include "format_types/juce_VST3PluginFormat.h" | #include "format_types/juce_VST3PluginFormat.h" | ||||
#include "format_types/juce_VSTMidiEventList.h" | #include "format_types/juce_VSTMidiEventList.h" | ||||
#include "format_types/juce_VSTPluginFormat.h" | #include "format_types/juce_VSTPluginFormat.h" | ||||
#include "format_types/juce_ARAHosting.h" | |||||
#include "scanning/juce_PluginDirectoryScanner.h" | #include "scanning/juce_PluginDirectoryScanner.h" | ||||
#include "scanning/juce_PluginListComponent.h" | #include "scanning/juce_PluginListComponent.h" | ||||
#include "utilities/juce_AudioProcessorParameterWithID.h" | #include "utilities/juce_AudioProcessorParameterWithID.h" | ||||
@@ -148,11 +168,23 @@ | |||||
#include "utilities/juce_AudioParameterInt.h" | #include "utilities/juce_AudioParameterInt.h" | ||||
#include "utilities/juce_AudioParameterBool.h" | #include "utilities/juce_AudioParameterBool.h" | ||||
#include "utilities/juce_AudioParameterChoice.h" | #include "utilities/juce_AudioParameterChoice.h" | ||||
#include "utilities/juce_ParameterAttachments.h" | |||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
#include "utilities/juce_ParameterAttachments.h" | |||||
#endif | |||||
#include "utilities/juce_AudioProcessorValueTreeState.h" | #include "utilities/juce_AudioProcessorValueTreeState.h" | ||||
#include "utilities/juce_PluginHostType.h" | #include "utilities/juce_PluginHostType.h" | ||||
#include "utilities/ARA/juce_ARA_utils.h" | |||||
//============================================================================== | |||||
// These declarations are here to avoid missing-prototype warnings in user code. | |||||
// This is here to avoid missing-prototype warnings in user code. | |||||
// If you're implementing a plugin, you should supply a body for | // If you're implementing a plugin, you should supply a body for | ||||
// this function in your own code. | // this function in your own code. | ||||
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter(); | juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter(); | ||||
// If you are implementing an ARA enabled plugin, you need to | |||||
// implement this function somewhere in the codebase by returning | |||||
// SubclassOfARADocumentControllerSpecialisation::createARAFactory<SubclassOfARADocumentControllerSpecialisation>(); | |||||
#if JucePlugin_Enable_ARA | |||||
const ARA::ARAFactory* JUCE_CALLTYPE createARAFactory(); | |||||
#endif |
@@ -0,0 +1,40 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#include <juce_core/system/juce_CompilerWarnings.h> | |||||
#include <juce_core/system/juce_TargetPlatform.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_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 |
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -43,12 +50,14 @@ AudioProcessor::AudioProcessor (const BusesProperties& ioConfig) | |||||
AudioProcessor::~AudioProcessor() | AudioProcessor::~AudioProcessor() | ||||
{ | { | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
{ | { | ||||
const ScopedLock sl (activeEditorLock); | const ScopedLock sl (activeEditorLock); | ||||
// ooh, nasty - the editor should have been deleted before its AudioProcessor. | // ooh, nasty - the editor should have been deleted before its AudioProcessor. | ||||
jassert (activeEditor == nullptr); | jassert (activeEditor == nullptr); | ||||
} | } | ||||
#endif | |||||
#if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING | #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING | ||||
// This will fail if you've called beginParameterChangeGesture() for one | // This will fail if you've called beginParameterChangeGesture() for one | ||||
@@ -867,6 +876,7 @@ void AudioProcessor::audioIOChanged (bool busNumberChanged, bool channelNumChang | |||||
processorLayoutsChanged(); | processorLayoutsChanged(); | ||||
} | } | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
//============================================================================== | //============================================================================== | ||||
void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) noexcept | void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) noexcept | ||||
{ | { | ||||
@@ -903,6 +913,7 @@ AudioProcessorEditor* AudioProcessor::createEditorIfNeeded() | |||||
return ed; | return ed; | ||||
} | } | ||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
void AudioProcessor::getCurrentProgramStateInformation (juce::MemoryBlock& destData) | void AudioProcessor::getCurrentProgramStateInformation (juce::MemoryBlock& destData) | ||||
@@ -1241,7 +1252,6 @@ const char* AudioProcessor::getWrapperTypeDescription (AudioProcessor::WrapperTy | |||||
case AudioProcessor::wrapperType_VST3: return "VST3"; | case AudioProcessor::wrapperType_VST3: return "VST3"; | ||||
case AudioProcessor::wrapperType_AudioUnit: return "AU"; | case AudioProcessor::wrapperType_AudioUnit: return "AU"; | ||||
case AudioProcessor::wrapperType_AudioUnitv3: return "AUv3"; | case AudioProcessor::wrapperType_AudioUnitv3: return "AUv3"; | ||||
case AudioProcessor::wrapperType_RTAS: return "RTAS"; | |||||
case AudioProcessor::wrapperType_AAX: return "AAX"; | case AudioProcessor::wrapperType_AAX: return "AAX"; | ||||
case AudioProcessor::wrapperType_Standalone: return "Standalone"; | case AudioProcessor::wrapperType_Standalone: return "Standalone"; | ||||
case AudioProcessor::wrapperType_Unity: return "Unity"; | case AudioProcessor::wrapperType_Unity: return "Unity"; | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -24,7 +31,7 @@ namespace juce | |||||
Base class for audio processing classes or plugins. | Base class for audio processing classes or plugins. | ||||
This is intended to act as a base class of audio processor that is general enough | This is intended to act as a base class of audio processor that is general enough | ||||
to be wrapped as a VST, AU, RTAS, etc, or used internally. | |||||
to be wrapped as a VST, AU, AAX, etc, or used internally. | |||||
It is also used by the plugin hosting code as the wrapper around an instance | It is also used by the plugin hosting code as the wrapper around an instance | ||||
of a loaded plugin. | of a loaded plugin. | ||||
@@ -71,6 +78,12 @@ public: | |||||
doublePrecision | doublePrecision | ||||
}; | }; | ||||
enum class Realtime | |||||
{ | |||||
no, | |||||
yes | |||||
}; | |||||
using ChangeDetails = AudioProcessorListener::ChangeDetails; | using ChangeDetails = AudioProcessorListener::ChangeDetails; | ||||
//============================================================================== | //============================================================================== | ||||
@@ -916,11 +929,27 @@ public: | |||||
*/ | */ | ||||
bool isNonRealtime() const noexcept { return nonRealtime; } | bool isNonRealtime() const noexcept { return nonRealtime; } | ||||
/** Returns no if the processor is being run in an offline mode for rendering. | |||||
If the processor is being run live on realtime signals, this returns yes. | |||||
If the mode is unknown, this will assume it's realtime and return yes. | |||||
This value may be unreliable until the prepareToPlay() method has been called, | |||||
and could change each time prepareToPlay() is called. | |||||
@see setNonRealtime() | |||||
*/ | |||||
Realtime isRealtime() const noexcept | |||||
{ | |||||
return isNonRealtime() ? Realtime::no : Realtime::yes; | |||||
} | |||||
/** Called by the host to tell this processor whether it's being used in a non-realtime | /** Called by the host to tell this processor whether it's being used in a non-realtime | ||||
capacity for offline rendering or bouncing. | capacity for offline rendering or bouncing. | ||||
*/ | */ | ||||
virtual void setNonRealtime (bool isNonRealtime) noexcept; | virtual void setNonRealtime (bool isNonRealtime) noexcept; | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
//============================================================================== | //============================================================================== | ||||
/** Creates the processor's GUI. | /** Creates the processor's GUI. | ||||
@@ -970,6 +999,7 @@ public: | |||||
This may call createEditor() internally to create the component. | This may call createEditor() internally to create the component. | ||||
*/ | */ | ||||
AudioProcessorEditor* createEditorIfNeeded(); | AudioProcessorEditor* createEditorIfNeeded(); | ||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
/** Returns the default number of steps for a parameter. | /** Returns the default number of steps for a parameter. | ||||
@@ -1231,9 +1261,11 @@ public: | |||||
virtual CurveData getResponseCurve (CurveData::Type /*curveType*/) const { return {}; } | virtual CurveData getResponseCurve (CurveData::Type /*curveType*/) const { return {}; } | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
//============================================================================== | //============================================================================== | ||||
/** Not for public use - this is called before deleting an editor component. */ | /** Not for public use - this is called before deleting an editor component. */ | ||||
void editorBeingDeleted (AudioProcessorEditor*) noexcept; | void editorBeingDeleted (AudioProcessorEditor*) noexcept; | ||||
#endif | |||||
/** Flags to indicate the type of plugin context in which a processor is being used. */ | /** Flags to indicate the type of plugin context in which a processor is being used. */ | ||||
enum WrapperType | enum WrapperType | ||||
@@ -1243,7 +1275,6 @@ public: | |||||
wrapperType_VST3, | wrapperType_VST3, | ||||
wrapperType_AudioUnit, | wrapperType_AudioUnit, | ||||
wrapperType_AudioUnitv3, | wrapperType_AudioUnitv3, | ||||
wrapperType_RTAS, | |||||
wrapperType_AAX, | wrapperType_AAX, | ||||
wrapperType_Standalone, | wrapperType_Standalone, | ||||
wrapperType_Unity, | wrapperType_Unity, | ||||
@@ -1264,7 +1295,9 @@ public: | |||||
struct TrackProperties | struct TrackProperties | ||||
{ | { | ||||
String name; // The name of the track - this will be empty if the track name is not known | String name; // The name of the track - this will be empty if the track name is not known | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
Colour colour; // The colour of the track - this will be transparentBlack if the colour is not known | Colour colour; // The colour of the track - this will be transparentBlack if the colour is not known | ||||
#endif | |||||
// other properties may be added in the future | // other properties may be added in the future | ||||
}; | }; | ||||
@@ -1513,7 +1546,9 @@ private: | |||||
//============================================================================== | //============================================================================== | ||||
Array<AudioProcessorListener*> listeners; | Array<AudioProcessorListener*> listeners; | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
Component::SafePointer<AudioProcessorEditor> activeEditor; | Component::SafePointer<AudioProcessorEditor> activeEditor; | ||||
#endif | |||||
double currentSampleRate = 0; | double currentSampleRate = 0; | ||||
int blockSize = 0, latencySamples = 0; | int blockSize = 0, latencySamples = 0; | ||||
bool suspended = false; | bool suspended = false; | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1575,8 +1582,10 @@ bool AudioProcessorGraph::AudioGraphIOProcessor::producesMidi() const | |||||
bool AudioProcessorGraph::AudioGraphIOProcessor::isInput() const noexcept { return type == audioInputNode || type == midiInputNode; } | bool AudioProcessorGraph::AudioGraphIOProcessor::isInput() const noexcept { return type == audioInputNode || type == midiInputNode; } | ||||
bool AudioProcessorGraph::AudioGraphIOProcessor::isOutput() const noexcept { return type == audioOutputNode || type == midiOutputNode; } | bool AudioProcessorGraph::AudioGraphIOProcessor::isOutput() const noexcept { return type == audioOutputNode || type == midiOutputNode; } | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
bool AudioProcessorGraph::AudioGraphIOProcessor::hasEditor() const { return false; } | bool AudioProcessorGraph::AudioGraphIOProcessor::hasEditor() const { return false; } | ||||
AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { return nullptr; } | AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { return nullptr; } | ||||
#endif | |||||
int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; } | int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; } | ||||
int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; } | int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; } | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -357,8 +364,10 @@ public: | |||||
bool acceptsMidi() const override; | bool acceptsMidi() const override; | ||||
bool producesMidi() const override; | bool producesMidi() const override; | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
bool hasEditor() const override; | bool hasEditor() const override; | ||||
AudioProcessorEditor* createEditor() override; | AudioProcessorEditor* createEditor() override; | ||||
#endif | |||||
int getNumPrograms() override; | int getNumPrograms() override; | ||||
int getCurrentProgram() override; | int getCurrentProgram() override; | ||||
@@ -394,8 +403,10 @@ public: | |||||
bool acceptsMidi() const override; | bool acceptsMidi() const override; | ||||
bool producesMidi() const override; | bool producesMidi() const override; | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
bool hasEditor() const override { return false; } | bool hasEditor() const override { return false; } | ||||
AudioProcessorEditor* createEditor() override { return nullptr; } | AudioProcessorEditor* createEditor() override { return nullptr; } | ||||
#endif | |||||
int getNumPrograms() override { return 0; } | int getNumPrograms() override { return 0; } | ||||
int getCurrentProgram() override { return 0; } | int getCurrentProgram() override { return 0; } | ||||
void setCurrentProgram (int) override { } | void setCurrentProgram (int) override { } | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -72,6 +79,7 @@ std::unique_ptr<XmlElement> PluginDescription::createXml() const | |||||
e->setAttribute ("numInputs", numInputChannels); | e->setAttribute ("numInputs", numInputChannels); | ||||
e->setAttribute ("numOutputs", numOutputChannels); | e->setAttribute ("numOutputs", numOutputChannels); | ||||
e->setAttribute ("isShell", hasSharedContainer); | e->setAttribute ("isShell", hasSharedContainer); | ||||
e->setAttribute ("hasARAExtension", hasARAExtension); | |||||
e->setAttribute ("uid", String::toHexString (deprecatedUid)); | e->setAttribute ("uid", String::toHexString (deprecatedUid)); | ||||
@@ -95,6 +103,7 @@ bool PluginDescription::loadFromXml (const XmlElement& xml) | |||||
numInputChannels = xml.getIntAttribute ("numInputs"); | numInputChannels = xml.getIntAttribute ("numInputs"); | ||||
numOutputChannels = xml.getIntAttribute ("numOutputs"); | numOutputChannels = xml.getIntAttribute ("numOutputs"); | ||||
hasSharedContainer = xml.getBoolAttribute ("isShell", false); | hasSharedContainer = xml.getBoolAttribute ("isShell", false); | ||||
hasARAExtension = xml.getBoolAttribute ("hasARAExtension", false); | |||||
deprecatedUid = xml.getStringAttribute ("uid").getHexValue32(); | deprecatedUid = xml.getStringAttribute ("uid").getHexValue32(); | ||||
uniqueId = xml.getStringAttribute ("uniqueId", "0").getHexValue32(); | uniqueId = xml.getStringAttribute ("uniqueId", "0").getHexValue32(); | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -122,6 +129,9 @@ public: | |||||
/** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */ | /** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */ | ||||
bool hasSharedContainer = false; | 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. | /** 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 | This isn't quite as simple as them just having the same file (because of | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -0,0 +1,971 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
namespace juce | |||||
{ | |||||
class ARADocumentControllerSpecialisation::ARADocumentControllerImpl : public ARADocumentController, | |||||
private juce::Timer | |||||
{ | |||||
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; | |||||
//============================================================================== | |||||
// 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; | |||||
#ifndef DOXYGEN | |||||
//============================================================================== | |||||
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; | |||||
//============================================================================== | |||||
// juce::Timer overrides | |||||
void timerCallback() override; | |||||
public: | |||||
//============================================================================== | |||||
/** @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; | |||||
#endif | |||||
private: | |||||
//============================================================================== | |||||
ARADocumentControllerSpecialisation* specialisation; | |||||
std::atomic<bool> internalAnalysisProgressIsSynced { true }; | |||||
ScopedJuceInitialiser_GUI libraryInitialiser; | |||||
int activeAudioSourcesCount = 0; | |||||
//============================================================================== | |||||
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 (isTimerRunning() && (activeAudioSourcesCount == 0)) | |||||
stopTimer(); | |||||
else if (! isTimerRunning() && (activeAudioSourcesCount > 0)) | |||||
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); | |||||
} | |||||
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::timerCallback() | |||||
{ | |||||
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 += 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 (const ARA::PlugIn::AudioSource* audioSource, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
juce::ignoreUnused (audioSource, type); | |||||
return false; | |||||
} | |||||
ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioSourceContentGrade (const ARA::PlugIn::AudioSource* audioSource, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
// Overriding doIsAudioSourceContentAvailable() requires overriding | |||||
// doGetAudioSourceContentGrade() accordingly! | |||||
jassertfalse; | |||||
juce::ignoreUnused (audioSource, type); | |||||
return ARA::kARAContentGradeInitial; | |||||
} | |||||
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioSourceContentReader (ARA::PlugIn::AudioSource* audioSource, | |||||
ARA::ARAContentType type, | |||||
const ARA::ARAContentTimeRange* range) | |||||
{ | |||||
// Overriding doIsAudioSourceContentAvailable() requires overriding | |||||
// doCreateAudioSourceContentReader() accordingly! | |||||
jassertfalse; | |||||
juce::ignoreUnused (audioSource, type, range); | |||||
return nullptr; | |||||
} | |||||
bool ARADocumentControllerSpecialisation::doIsAudioModificationContentAvailable (const ARA::PlugIn::AudioModification* audioModification, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
juce::ignoreUnused (audioModification, type); | |||||
return false; | |||||
} | |||||
ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioModificationContentGrade (const ARA::PlugIn::AudioModification* audioModification, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
// Overriding doIsAudioModificationContentAvailable() requires overriding | |||||
// doGetAudioModificationContentGrade() accordingly! | |||||
jassertfalse; | |||||
juce::ignoreUnused (audioModification, type); | |||||
return ARA::kARAContentGradeInitial; | |||||
} | |||||
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioModificationContentReader (ARA::PlugIn::AudioModification* audioModification, | |||||
ARA::ARAContentType type, | |||||
const ARA::ARAContentTimeRange* range) | |||||
{ | |||||
// Overriding doIsAudioModificationContentAvailable() requires overriding | |||||
// doCreateAudioModificationContentReader() accordingly! | |||||
jassertfalse; | |||||
juce::ignoreUnused (audioModification, type, range); | |||||
return nullptr; | |||||
} | |||||
bool ARADocumentControllerSpecialisation::doIsPlaybackRegionContentAvailable (const ARA::PlugIn::PlaybackRegion* playbackRegion, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
juce::ignoreUnused (playbackRegion, type); | |||||
return false; | |||||
} | |||||
ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetPlaybackRegionContentGrade (const ARA::PlugIn::PlaybackRegion* playbackRegion, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
// Overriding doIsPlaybackRegionContentAvailable() requires overriding | |||||
// doGetPlaybackRegionContentGrade() accordingly! | |||||
jassertfalse; | |||||
juce::ignoreUnused (playbackRegion, type); | |||||
return ARA::kARAContentGradeInitial; | |||||
} | |||||
ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreatePlaybackRegionContentReader (ARA::PlugIn::PlaybackRegion* playbackRegion, | |||||
ARA::ARAContentType type, | |||||
const ARA::ARAContentTimeRange* range) | |||||
{ | |||||
// Overriding doIsPlaybackRegionContentAvailable() requires overriding | |||||
// doCreatePlaybackRegionContentReader() accordingly! | |||||
jassertfalse; | |||||
juce::ignoreUnused (playbackRegion, type, range); | |||||
return nullptr; | |||||
} | |||||
bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAnalysisIncomplete (const ARA::PlugIn::AudioSource* audioSource, | |||||
ARA::ARAContentType type) | |||||
{ | |||||
juce::ignoreUnused (audioSource, type); | |||||
return false; | |||||
} | |||||
void ARADocumentControllerSpecialisation::doRequestAudioSourceContentAnalysis (ARA::PlugIn::AudioSource* audioSource, | |||||
std::vector<ARA::ARAContentType> const& contentTypes) | |||||
{ | |||||
juce::ignoreUnused (audioSource, contentTypes); | |||||
} | |||||
ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmsCount() { return 0; } | |||||
const ARA::ARAProcessingAlgorithmProperties* | |||||
ARADocumentControllerSpecialisation::doGetProcessingAlgorithmProperties (ARA::ARAInt32 algorithmIndex) | |||||
{ | |||||
juce::ignoreUnused (algorithmIndex); | |||||
return nullptr; | |||||
} | |||||
ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmForAudioSource (const ARA::PlugIn::AudioSource* audioSource) | |||||
{ | |||||
// doGetProcessingAlgorithmForAudioSource() must be implemented if the supported | |||||
// algorithm count is greater than zero. | |||||
if (getDocumentController()->getProcessingAlgorithmsCount() > 0) | |||||
jassertfalse; | |||||
juce::ignoreUnused (audioSource); | |||||
return 0; | |||||
} | |||||
void ARADocumentControllerSpecialisation::doRequestProcessingAlgorithmForAudioSource (ARA::PlugIn::AudioSource* audioSource, | |||||
ARA::ARAInt32 algorithmIndex) | |||||
{ | |||||
// doRequestProcessingAlgorithmForAudioSource() must be implemented if the supported | |||||
// algorithm count is greater than zero. | |||||
if (getDocumentController()->getProcessingAlgorithmsCount() > 0) | |||||
jassertfalse; | |||||
juce::ignoreUnused (audioSource, algorithmIndex); | |||||
} | |||||
} // namespace juce |
@@ -0,0 +1,520 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#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<ARADocumentControllerSpecialisation, SpecialisationType>::value, | |||||
"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); | |||||
//============================================================================== | |||||
// 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. */ | |||||
ARADocument* doCreateDocument(); | |||||
/** Override to return a custom subclass instance of ARAMusicalContext. */ | |||||
ARAMusicalContext* doCreateMusicalContext (ARADocument* document, | |||||
ARA::ARAMusicalContextHostRef hostRef); | |||||
/** Override to return a custom subclass instance of ARARegionSequence. */ | |||||
ARARegionSequence* doCreateRegionSequence (ARADocument* document, | |||||
ARA::ARARegionSequenceHostRef hostRef); | |||||
/** Override to return a custom subclass instance of ARAAudioSource. */ | |||||
ARAAudioSource* doCreateAudioSource (ARADocument* document, | |||||
ARA::ARAAudioSourceHostRef hostRef); | |||||
/** Override to return a custom subclass instance of ARAAudioModification. */ | |||||
ARAAudioModification* doCreateAudioModification (ARAAudioSource* audioSource, | |||||
ARA::ARAAudioModificationHostRef hostRef, | |||||
const ARAAudioModification* optionalModificationToClone); | |||||
/** Override to return a custom subclass instance of ARAPlaybackRegion. */ | |||||
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 |
@@ -0,0 +1,71 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
namespace juce | |||||
{ | |||||
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 |
@@ -0,0 +1,199 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
namespace juce | |||||
{ | |||||
//============================================================================== | |||||
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 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); | |||||
} | |||||
} // namespace juce |
@@ -0,0 +1,92 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#include "juce_ARAPlugInInstanceRoles.h" | |||||
namespace juce | |||||
{ | |||||
bool ARARenderer::processBlock (AudioBuffer<double>& buffer, | |||||
AudioProcessor::Realtime realtime, | |||||
const AudioPlayHead::CurrentPositionInfo& positionInfo) noexcept | |||||
{ | |||||
ignoreUnused (buffer, realtime, positionInfo); | |||||
// 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; | |||||
} | |||||
//============================================================================== | |||||
#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 | |||||
//============================================================================== | |||||
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); | |||||
} | |||||
} // namespace juce |
@@ -0,0 +1,271 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#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) | |||||
{ | |||||
ignoreUnused (sampleRate, maximumSamplesPerBlock, numChannels, precision, alwaysNonRealtime); | |||||
} | |||||
/** 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::CurrentPositionInfo& 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::CurrentPositionInfo& 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::CurrentPositionInfo& positionInfo) noexcept override | |||||
{ | |||||
ignoreUnused (buffer, realtime, positionInfo); | |||||
return false; | |||||
} | |||||
// 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::CurrentPositionInfo& positionInfo) noexcept override | |||||
{ | |||||
ignoreUnused (buffer, isNonRealtime, positionInfo); | |||||
return true; | |||||
} | |||||
private: | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAEditorRenderer) | |||||
}; | |||||
//============================================================================== | |||||
/** Base class for a renderer 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> | |||||
std::vector<RegionSequence_t*> const& 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 (std::vector<ARA::PlugIn::RegionSequence*> const& 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; | |||||
ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN | |||||
/** Called when the editor view's selection changes. | |||||
@param viewSelection The current selection state | |||||
*/ | |||||
virtual void onNewSelection (const ARA::PlugIn::ViewSelection& viewSelection) | |||||
{ | |||||
ignoreUnused (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 (std::vector<ARARegionSequence*> const& regionSequences) | |||||
{ | |||||
ignoreUnused (regionSequences); | |||||
} | |||||
ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END | |||||
}; | |||||
/** \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) | |||||
}; | |||||
} |
@@ -0,0 +1,32 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#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" | |||||
#endif |
@@ -0,0 +1,85 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#if JucePlugin_Enable_ARA | |||||
// Include ARA SDK headers | |||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments", | |||||
"-Wunused-parameter") | |||||
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 |
@@ -0,0 +1,156 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#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::CurrentPositionInfo& 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) | |||||
{ | |||||
AudioPlayHead::CurrentPositionInfo positionInfo; | |||||
if (! isBoundToARA() || ! playhead || ! playhead->getCurrentPosition (positionInfo)) | |||||
positionInfo.resetToDefault(); | |||||
return processBlockForARA (buffer, realtime, 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_DISABLE_ASSERTIONS) | |||||
// 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 |
@@ -0,0 +1,204 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
DISCLAIMED. | |||||
============================================================================== | |||||
*/ | |||||
#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::CurrentPositionInfo& 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 |
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -466,6 +473,7 @@ void AudioProcessorValueTreeState::timerCallback() | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
template <typename Attachment, typename Control> | template <typename Attachment, typename Control> | ||||
std::unique_ptr<Attachment> makeAttachment (const AudioProcessorValueTreeState& stateToUse, | std::unique_ptr<Attachment> makeAttachment (const AudioProcessorValueTreeState& stateToUse, | ||||
const String& parameterID, | const String& parameterID, | ||||
@@ -498,6 +506,7 @@ AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessor | |||||
: attachment (makeAttachment<ButtonParameterAttachment> (stateToUse, parameterID, button)) | : attachment (makeAttachment<ButtonParameterAttachment> (stateToUse, parameterID, button)) | ||||
{ | { | ||||
} | } | ||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
//============================================================================== | //============================================================================== | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -519,6 +526,7 @@ public: | |||||
friend class AudioProcessorValueTreeState::ParameterAdapter; | friend class AudioProcessorValueTreeState::ParameterAdapter; | ||||
}; | }; | ||||
#if ! JUCE_AUDIOPROCESSOR_NO_GUI | |||||
//============================================================================== | //============================================================================== | ||||
/** An object of this class maintains a connection between a Slider and a parameter | /** An object of this class maintains a connection between a Slider and a parameter | ||||
in an AudioProcessorValueTreeState. | in an AudioProcessorValueTreeState. | ||||
@@ -586,6 +594,7 @@ public: | |||||
std::unique_ptr<ButtonParameterAttachment> attachment; | std::unique_ptr<ButtonParameterAttachment> attachment; | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment) | ||||
}; | }; | ||||
#endif | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -30,7 +37,7 @@ namespace Steinberg | |||||
#endif | #endif | ||||
//============================================================================== | //============================================================================== | ||||
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined(AUDIOCOMPONENT_NOCARBONINSTANCES) && AUDIOCOMPONENT_NOCARBONINSTANCES) | |||||
#if TARGET_OS_IPHONE | |||||
struct OpaqueAudioComponentInstance; | struct OpaqueAudioComponentInstance; | ||||
typedef struct OpaqueAudioComponentInstance* AudioComponentInstance; | typedef struct OpaqueAudioComponentInstance* AudioComponentInstance; | ||||
#else | #else | ||||
@@ -108,6 +115,13 @@ struct ExtensionsVisitor | |||||
virtual AEffect* getAEffectPtr() const noexcept = 0; | 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; | |||||
}; | |||||
virtual ~ExtensionsVisitor() = default; | virtual ~ExtensionsVisitor() = default; | ||||
/** Will be called if there is no platform specific information available. */ | /** Will be called if there is no platform specific information available. */ | ||||
@@ -121,6 +135,9 @@ struct ExtensionsVisitor | |||||
/** Called with AU-specific information. */ | /** Called with AU-specific information. */ | ||||
virtual void visitAudioUnitClient (const AudioUnitClient&) {} | virtual void visitAudioUnitClient (const AudioUnitClient&) {} | ||||
/** Called with ARA-specific information. */ | |||||
virtual void visitARAClient (const ARAClient&) {} | |||||
}; | }; | ||||
} // namespace juce | } // namespace juce |
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||
@@ -1,13 +1,20 @@ | |||||
/* | /* | ||||
============================================================================== | ============================================================================== | ||||
This file is part of the JUCE 7 technical preview. | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2022 - Raw Material Software Limited | Copyright (c) 2022 - Raw Material Software Limited | ||||
You may use this code under the terms of the GPL v3 | |||||
(see www.gnu.org/licenses). | |||||
JUCE is an open source library subject to commercial or open-source | |||||
licensing. | |||||
For the technical preview this file cannot be licensed commercially. | |||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License | |||||
Agreement and JUCE Privacy Policy. | |||||
End User License Agreement: www.juce.com/juce-7-licence | |||||
Privacy Policy: www.juce.com/juce-privacy-policy | |||||
Or: You may also use this code under the terms of the GPL v3 (see | |||||
www.gnu.org/licenses). | |||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | ||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | ||||