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