ARA Demo Plugin is broken

The way ARA Audio readers are being used does not align with the requirements.

See ARA docs: ARA::PlugIn::HostAudioAccessController::createAudioReaderForSource

To stop shooting myself into the foot, I added simple stacktrace validation for debug builds:

    void validateStackTrace()
    {
#ifndef JUCE_DEBUG
        return;
#endif

        const auto backtrace = SystemStats::getStackBacktrace();
        StringArray validMethods {
            "doCreateAudioSource",
            "doDestroyAudioSource",
            "willUpdateAudioSourceProperties",
            "didUpdateAudioSourceProperties",
            "doUpdateAudioSourceContent",
            "willEnableAudioSourceSamplesAccess",
            "didEnableAudioSourceSamplesAccess",
            "willDeactivateAudioSourceForUndoHistory",
            "didDeactivateAudioSourceForUndoHistory",
            "didAddAudioModificationToAudioSource",
            "willRemoveAudioModificationFromAudioSource",
            "willDestroyAudioSource",
            "didEndEditing"
        };

        for (const auto& method : validMethods)
        {
            if(backtrace.contains(method))
                return;
        }

        /*
         * The ARA::PlugIn::HostAudioReader (hostReader member) can only be created or destroyed during audio source management hooks in the document controller.
         * It wraps ARAAudioAccessControllerInterface, so see ARAAudioAccessControllerInterface::createAudioReaderForSource and ARAAudioAccessControllerInterface::destroyAudioReader for documentation.
         */
        jassertfalse;
    }

ARAAudioSourceReader::ARAAudioSourceReader (ARAAudioSource* audioSource)
    : AudioFormatReader (nullptr, "ARAAudioSourceReader"),
      audioSourceBeingRead (audioSource)
{
    jassert (audioSourceBeingRead != nullptr);

    bitsPerSample = 32;
    usesFloatingPointData = true;
    sampleRate = audioSourceBeingRead->getSampleRate();
    numChannels = (unsigned int) audioSourceBeingRead->getChannelCount();
    lengthInSamples = audioSourceBeingRead->getSampleCount();
    tmpPtrs.resize (numChannels);

    audioSourceBeingRead->addListener (this);

    validateStackTrace();
    if (audioSourceBeingRead->isSampleAccessEnabled())
        hostReader.reset (new ARA::PlugIn::HostAudioReader (audioSourceBeingRead));
}

In practice this does cause issues in some hosts, from the top of my head I remember Cubase and Nuendo.

Just to clarify — are you saying that a plugin shouldn’t request audio source readers from the host on the GUI thread (or at arbitrary times)?

The plugin must create readers from the gui thread, only during the audio source management ara hooks, or endEditing.

ARA Docs:

Create audio reader instance to access sample data in an audio source. The format of the data is matching the format of the audio source, with a choice of reading samples as 32 bit or 64 bit (hosts must support both formats). Similar to the rules for creating content readers, the plug-in may call these functions only from calls in the “Audio Source Management” section of ARADocumentControllerInterface for the particular audio source the call is referring to, or from ARADocumentControllerInterface::endEditing() for any audio source. Contrary to content readers, audio readers are long-living objects that are not bound to a certain stack frame.

1 Like