migrating to the latest JUCE version

This commit is contained in:
2022-11-04 23:11:33 +01:00
committed by Nikolai Rodionov
parent 4257a0f8ba
commit faf8f18333
2796 changed files with 888518 additions and 784244 deletions

View File

@ -0,0 +1,67 @@
/*
==============================================================================
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
#include <juce_core/system/juce_PlatformDefs.h>
#ifndef JUCE_API
#define JUCE_API
#endif
#if (JucePlugin_Enable_ARA || (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU))) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)
namespace juce
{
//==============================================================================
#if (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS) || JUCE_LOG_ASSERTIONS
#define ARA_ENABLE_INTERNAL_ASSERTS 1
#else
#define ARA_ENABLE_INTERNAL_ASSERTS 0
#endif // (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS) || JUCE_LOG_ASSERTIONS
//==============================================================================
#if ARA_ENABLE_INTERNAL_ASSERTS
JUCE_API void JUCE_CALLTYPE handleARAAssertion (const char* file, const int line, const char* diagnosis) noexcept;
#if !defined(ARA_HANDLE_ASSERT)
#define ARA_HANDLE_ASSERT(file, line, diagnosis) juce::handleARAAssertion (file, line, diagnosis)
#endif
#if JUCE_LOG_ASSERTIONS
#define ARA_ENABLE_DEBUG_OUTPUT 1
#endif
#endif
} // namespace juce
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments", "-Wmissing-prototypes")
#include <ARA_Library/Debug/ARADebug.h>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif

View File

@ -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 += (int64) numberOfBytes;
return true;
}
bool ARAOutputStream::setPosition (int64 newPosition)
{
position = newPosition;
return true;
}
//==============================================================================
ARADocumentControllerSpecialisation::ARADocumentControllerSpecialisation (
const ARA::PlugIn::PlugInEntry* entry,
const ARA::ARADocumentControllerHostInstance* instance)
: documentController (std::make_unique<ARADocumentControllerImpl> (entry, instance, this))
{
}
ARADocumentControllerSpecialisation::~ARADocumentControllerSpecialisation() = default;
ARAPlaybackRenderer* ARADocumentControllerSpecialisation::doCreatePlaybackRenderer()
{
return new ARAPlaybackRenderer (getDocumentController());
}
ARAEditorRenderer* ARADocumentControllerSpecialisation::doCreateEditorRenderer()
{
return new ARAEditorRenderer (getDocumentController());
}
ARAEditorView* ARADocumentControllerSpecialisation::doCreateEditorView()
{
return new ARAEditorView (getDocumentController());
}
bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAvailable (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

View File

@ -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. */
virtual ARADocument* doCreateDocument();
/** Override to return a custom subclass instance of ARAMusicalContext. */
virtual ARAMusicalContext* doCreateMusicalContext (ARADocument* document,
ARA::ARAMusicalContextHostRef hostRef);
/** Override to return a custom subclass instance of ARARegionSequence. */
virtual ARARegionSequence* doCreateRegionSequence (ARADocument* document,
ARA::ARARegionSequenceHostRef hostRef);
/** Override to return a custom subclass instance of ARAAudioSource. */
virtual ARAAudioSource* doCreateAudioSource (ARADocument* document,
ARA::ARAAudioSourceHostRef hostRef);
/** Override to return a custom subclass instance of ARAAudioModification. */
virtual ARAAudioModification* doCreateAudioModification (ARAAudioSource* audioSource,
ARA::ARAAudioModificationHostRef hostRef,
const ARAAudioModification* optionalModificationToClone);
/** Override to return a custom subclass instance of ARAPlaybackRegion. */
virtual ARAPlaybackRegion* doCreatePlaybackRegion (ARAAudioModification* modification,
ARA::ARAPlaybackRegionHostRef hostRef);
private:
//==============================================================================
template <typename SpecialisationType>
class FactoryConfig : public ARA::PlugIn::FactoryConfig
{
public:
FactoryConfig() noexcept
{
const juce::String compatibleDocumentArchiveIDString = JucePlugin_ARACompatibleArchiveIDs;
if (compatibleDocumentArchiveIDString.isNotEmpty())
{
compatibleDocumentArchiveIDStrings = juce::StringArray::fromLines (compatibleDocumentArchiveIDString);
for (const auto& compatibleID : compatibleDocumentArchiveIDStrings)
compatibleDocumentArchiveIDs.push_back (compatibleID.toRawUTF8());
}
// Update analyzeable content types
static constexpr std::array<ARA::ARAContentType, 6> contentTypes {
ARA::kARAContentTypeNotes,
ARA::kARAContentTypeTempoEntries,
ARA::kARAContentTypeBarSignatures,
ARA::kARAContentTypeStaticTuning,
ARA::kARAContentTypeKeySignatures,
ARA::kARAContentTypeSheetChords
};
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6313)
for (size_t i = 0; i < contentTypes.size(); ++i)
if (JucePlugin_ARAContentTypes & (1 << i))
analyzeableContentTypes.push_back (contentTypes[i]);
JUCE_END_IGNORE_WARNINGS_MSVC
// Update playback transformation flags
static constexpr std::array<ARA::ARAPlaybackTransformationFlags, 4> playbackTransformationFlags {
ARA::kARAPlaybackTransformationTimestretch,
ARA::kARAPlaybackTransformationTimestretchReflectingTempo,
ARA::kARAPlaybackTransformationContentBasedFadeAtTail,
ARA::kARAPlaybackTransformationContentBasedFadeAtHead
};
supportedPlaybackTransformationFlags = 0;
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6313)
for (size_t i = 0; i < playbackTransformationFlags.size(); ++i)
if (JucePlugin_ARATransformationFlags & (1 << i))
supportedPlaybackTransformationFlags |= playbackTransformationFlags[i];
JUCE_END_IGNORE_WARNINGS_MSVC
}
const char* getFactoryID() const noexcept override { return JucePlugin_ARAFactoryID; }
const char* getPlugInName() const noexcept override { return JucePlugin_Name; }
const char* getManufacturerName() const noexcept override { return JucePlugin_Manufacturer; }
const char* getInformationURL() const noexcept override { return JucePlugin_ManufacturerWebsite; }
const char* getVersion() const noexcept override { return JucePlugin_VersionString; }
const char* getDocumentArchiveID() const noexcept override { return JucePlugin_ARADocumentArchiveID; }
ARA::ARASize getCompatibleDocumentArchiveIDsCount() const noexcept override
{
return compatibleDocumentArchiveIDs.size();
}
const ARA::ARAPersistentID* getCompatibleDocumentArchiveIDs() const noexcept override
{
return compatibleDocumentArchiveIDs.empty() ? nullptr : compatibleDocumentArchiveIDs.data();
}
ARA::ARASize getAnalyzeableContentTypesCount() const noexcept override
{
return analyzeableContentTypes.size();
}
const ARA::ARAContentType* getAnalyzeableContentTypes() const noexcept override
{
return analyzeableContentTypes.empty() ? nullptr : analyzeableContentTypes.data();
}
ARA::ARAPlaybackTransformationFlags getSupportedPlaybackTransformationFlags() const noexcept override
{
return supportedPlaybackTransformationFlags;
}
ARA::PlugIn::DocumentController* createDocumentController (const ARA::PlugIn::PlugInEntry* entry,
const ARA::ARADocumentControllerHostInstance* instance) const noexcept override
{
auto* spec = new SpecialisationType (entry, instance);
return spec->getDocumentController();
}
void destroyDocumentController (ARA::PlugIn::DocumentController* controller) const noexcept override
{
delete getSpecialisedDocumentController (controller);
}
private:
juce::StringArray compatibleDocumentArchiveIDStrings;
std::vector<ARA::ARAPersistentID> compatibleDocumentArchiveIDs;
std::vector<ARA::ARAContentType> analyzeableContentTypes;
ARA::ARAPlaybackTransformationFlags supportedPlaybackTransformationFlags;
};
//==============================================================================
static ARADocumentControllerSpecialisation* getSpecialisedDocumentControllerImpl (ARA::PlugIn::DocumentController*);
ARADocument* getDocumentImpl();
//==============================================================================
class ARADocumentControllerImpl;
std::unique_ptr<ARADocumentControllerImpl> documentController;
};
/** Used to read persisted ARA archives - see doRestoreObjectsFromStream() for details.
@tags{ARA}
*/
class ARAInputStream : public InputStream
{
public:
explicit ARAInputStream (ARA::PlugIn::HostArchiveReader*);
int64 getPosition() override { return position; }
int64 getTotalLength() override { return size; }
int read (void*, int) override;
bool setPosition (int64) override;
bool isExhausted() override;
bool failed() const { return failure; }
private:
ARA::PlugIn::HostArchiveReader* archiveReader;
int64 position = 0;
int64 size;
bool failure = false;
};
/** Used to write persistent ARA archives - see doStoreObjectsToStream() for details.
@tags{ARA}
*/
class ARAOutputStream : public OutputStream
{
public:
explicit ARAOutputStream (ARA::PlugIn::HostArchiveWriter*);
int64 getPosition() override { return position; }
void flush() override {}
bool write (const void*, size_t) override;
bool setPosition (int64) override;
private:
ARA::PlugIn::HostArchiveWriter* archiveWriter;
int64 position = 0;
};
} // namespace juce

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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::PositionInfo& 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

View File

@ -0,0 +1,275 @@
/*
==============================================================================
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::PositionInfo& positionInfo) noexcept = 0;
/** Renders the output into the given buffer. Returns true if rendering executed without error,
false otherwise.
@param buffer The output buffer for the rendering. ARAPlaybackRenderers will
replace the sample data, while ARAEditorRenderer will add to it.
@param realtime Indicates whether the call is executed under real time constraints.
The value of this parameter may change from one call to the next,
and if the value is yes, the rendering may fail if the required
samples cannot be obtained in time.
@param positionInfo Current song position, playback state and playback loop location.
There should be no need to access the bpm, timeSig and ppqPosition
members in any ARA renderer since ARA provides that information with
random access in its model graph.
Returns false if non-ARA fallback rendering is required and true otherwise.
*/
virtual bool processBlock (AudioBuffer<double>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept;
};
//==============================================================================
/** Base class for a renderer fulfilling the ARAPlaybackRenderer role as described in the ARA SDK.
Instances of this class are constructed by the DocumentController. If you are subclassing
ARAPlaybackRenderer, make sure to call the base class implementation of any overridden function,
except for processBlock.
@tags{ARA}
*/
class JUCE_API ARAPlaybackRenderer : public ARA::PlugIn::PlaybackRenderer,
public ARARenderer
{
public:
using ARA::PlugIn::PlaybackRenderer::PlaybackRenderer;
bool processBlock (AudioBuffer<float>& buffer,
AudioProcessor::Realtime realtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept override
{
ignoreUnused (buffer, realtime, positionInfo);
return false;
}
using ARARenderer::processBlock;
// Shadowing templated getters to default to JUCE versions of the returned classes
/** Returns the PlaybackRegions
*
* @tparam PlaybackRegion_t
* @return
*/
template <typename PlaybackRegion_t = ARAPlaybackRegion>
std::vector<PlaybackRegion_t*> const& getPlaybackRegions() const noexcept
{
return ARA::PlugIn::PlaybackRenderer::getPlaybackRegions<PlaybackRegion_t>();
}
#if ARA_VALIDATE_API_CALLS
void addPlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept override;
void removePlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept override;
AudioProcessorARAExtension* araExtension {};
#endif
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAPlaybackRenderer)
};
//==============================================================================
/** Base class for a renderer fulfilling the ARAEditorRenderer role as described in the ARA SDK.
Instances of this class are constructed by the DocumentController. If you are subclassing
ARAEditorRenderer, make sure to call the base class implementation of any overridden function,
except for processBlock.
@tags{ARA}
*/
class JUCE_API ARAEditorRenderer : public ARA::PlugIn::EditorRenderer,
public ARARenderer
{
public:
using ARA::PlugIn::EditorRenderer::EditorRenderer;
// Shadowing templated getters to default to JUCE versions of the returned classes
template <typename PlaybackRegion_t = ARAPlaybackRegion>
std::vector<PlaybackRegion_t*> const& getPlaybackRegions() const noexcept
{
return ARA::PlugIn::EditorRenderer::getPlaybackRegions<PlaybackRegion_t>();
}
template <typename RegionSequence_t = ARARegionSequence>
std::vector<RegionSequence_t*> const& getRegionSequences() const noexcept
{
return ARA::PlugIn::EditorRenderer::getRegionSequences<RegionSequence_t>();
}
// By default, editor renderers will just let the signal pass through unaltered.
// If you're overriding this to implement actual audio preview, remember to check
// isNonRealtime of the process context - typically preview is limited to realtime.
bool processBlock (AudioBuffer<float>& buffer,
AudioProcessor::Realtime isNonRealtime,
const AudioPlayHead::PositionInfo& positionInfo) noexcept override
{
ignoreUnused (buffer, isNonRealtime, positionInfo);
return true;
}
using ARARenderer::processBlock;
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)
};
}

View File

@ -0,0 +1,56 @@
/*
==============================================================================
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 || (JUCE_PLUGINHOST_ARA && (JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU))) && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)
namespace juce
{
#if ARA_ENABLE_INTERNAL_ASSERTS
JUCE_API void JUCE_CALLTYPE handleARAAssertion (const char* file, const int line, const char* diagnosis) noexcept
{
#if (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS)
DBG (diagnosis);
#endif
logAssertion (file, line);
#if (JUCE_DEBUG && ! JUCE_DISABLE_ASSERTIONS)
if (juce_isRunningUnderDebugger())
JUCE_BREAK_IN_DEBUGGER;
JUCE_ANALYZER_NORETURN
#endif
}
#endif
}
#endif
#if JucePlugin_Enable_ARA
#include "juce_ARADocumentControllerCommon.cpp"
#include "juce_ARADocumentController.cpp"
#include "juce_ARAModelObjects.cpp"
#include "juce_ARAPlugInInstanceRoles.cpp"
#include "juce_AudioProcessor_ARAExtensions.cpp"
ARA_SETUP_DEBUG_MESSAGE_PREFIX(JucePlugin_Name);
#endif

View File

@ -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

View File

@ -0,0 +1,154 @@
/*
==============================================================================
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::PositionInfo& positionInfo)
{
// validate that the host has prepared us before processing
ARA_VALIDATE_API_STATE (isPrepared);
if (! isBoundToARA())
return false;
// Render our ARA playback regions for this buffer.
if (auto playbackRenderer = getPlaybackRenderer())
playbackRenderer->processBlock (buffer, realtime, positionInfo);
// Render our ARA editor regions and sequences for this buffer.
// This example does not support editor rendering and thus uses the default implementation,
// which is a no-op and could be omitted in actual plug-ins to optimize performance.
if (auto editorRenderer = getEditorRenderer())
editorRenderer->processBlock (buffer, realtime, positionInfo);
return true;
}
bool AudioProcessorARAExtension::processBlockForARA (AudioBuffer<float>& buffer,
juce::AudioProcessor::Realtime realtime,
AudioPlayHead* playhead)
{
return processBlockForARA (buffer,
realtime,
playhead != nullptr ? playhead->getPosition().orFallback (AudioPlayHead::PositionInfo{})
: AudioPlayHead::PositionInfo{});
}
//==============================================================================
void AudioProcessorARAExtension::didBindToARA() noexcept
{
// validate that the ARA binding is not established by the host while prepared to play
#if ARA_VALIDATE_API_CALLS
ARA_VALIDATE_API_STATE (! isPrepared);
if (auto playbackRenderer = getPlaybackRenderer())
playbackRenderer->araExtension = this;
#endif
#if (! JUCE_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

View File

@ -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::PositionInfo& positionInfo);
/** Implementation helper for AudioProcessor::processBlock().
If bound to ARA, this traverses the instance roles to let them process the block and returns
true. Otherwise returns false and does nothing.
Use this overload if your rendering code does not have a current positionInfo available.
*/
bool processBlockForARA (AudioBuffer<float>& buffer, AudioProcessor::Realtime isNonRealtime, AudioPlayHead* playhead);
//==============================================================================
/** Optional hook for derived classes to perform any additional initialization that may be needed.
If overriding this, make sure you call the base class implementation from your override.
*/
void didBindToARA() noexcept override;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorARAExtension)
};
//==============================================================================
/** Extension class meant to be subclassed by the plugin's implementation of @see AudioProcessorEditor.
Subclassing AudioProcessorARAExtension allows access to the ARAEditorView instance role as
described by the ARA SDK.
@tags{ARA}
*/
class JUCE_API AudioProcessorEditorARAExtension
{
public:
/** Constructor. */
explicit AudioProcessorEditorARAExtension (AudioProcessor* audioProcessor);
/** \copydoc AudioProcessorARAExtension::getEditorView */
template <typename EditorView_t = ARAEditorView>
EditorView_t* getARAEditorView() const noexcept
{
return (this->araProcessorExtension != nullptr) ? this->araProcessorExtension->getEditorView<EditorView_t>()
: nullptr;
}
/** \copydoc AudioProcessorARAExtension::isEditorView */
bool isARAEditorView() const noexcept { return getARAEditorView() != nullptr; }
protected:
/** Destructor. */
~AudioProcessorEditorARAExtension();
private:
AudioProcessorARAExtension* araProcessorExtension;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorEditorARAExtension)
};
} // namespace juce