From 31b2a8655916730922740d1f3d57a9cc9e75f689 Mon Sep 17 00:00:00 2001 From: attila Date: Tue, 1 Mar 2022 17:51:05 +0100 Subject: [PATCH] Projucer: Add ARA support --- extras/AudioPluginHost/AudioPluginHost.jucer | 2 + .../MacOSX/Projucer.xcodeproj/project.pbxproj | 8 + .../VisualStudio2015/Projucer_App.vcxproj | 11 + .../Projucer_App.vcxproj.filters | 15 + .../VisualStudio2017/Projucer_App.vcxproj | 11 + .../Projucer_App.vcxproj.filters | 15 + .../VisualStudio2019/Projucer_App.vcxproj | 11 + .../Projucer_App.vcxproj.filters | 15 + .../VisualStudio2022/Projucer_App.vcxproj | 11 + .../Projucer_App.vcxproj.filters | 15 + extras/Projucer/CMakeLists.txt | 4 + .../Projucer/JuceLibraryCode/BinaryData.cpp | 376 +++++++++++++++--- extras/Projucer/JuceLibraryCode/BinaryData.h | 16 +- extras/Projucer/Projucer.jucer | 8 + .../StartPage/jucer_NewProjectTemplates.h | 24 +- .../StartPage/jucer_NewProjectWizard.cpp | 17 + .../jucer_GlobalPathsWindowComponent.h | 6 +- .../Source/Application/jucer_CommandLine.cpp | 2 +- ...dioPluginARADocumentControllerTemplate.cpp | 42 ++ ...AudioPluginARADocumentControllerTemplate.h | 36 ++ ...AudioPluginARAPlaybackRendererTemplate.cpp | 112 ++++++ ...r_AudioPluginARAPlaybackRendererTemplate.h | 45 +++ .../jucer_AudioPluginFilterTemplate.h | 3 + .../Projucer/Source/Project/jucer_Project.cpp | 203 +++++++++- .../Projucer/Source/Project/jucer_Project.h | 24 ++ .../ProjectSaving/jucer_ProjectExport_MSVC.h | 3 + .../ProjectSaving/jucer_ProjectExport_Xcode.h | 4 + .../ProjectSaving/jucer_ProjectExporter.cpp | 27 ++ .../ProjectSaving/jucer_ProjectExporter.h | 5 +- .../Source/Settings/jucer_StoredSettings.cpp | 10 + .../Source/Utility/Helpers/jucer_PresetIDs.h | 8 + 31 files changed, 1021 insertions(+), 68 deletions(-) create mode 100644 extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.cpp create mode 100644 extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.h create mode 100644 extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.cpp create mode 100644 extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.h diff --git a/extras/AudioPluginHost/AudioPluginHost.jucer b/extras/AudioPluginHost/AudioPluginHost.jucer index 2b7b50bdc0..186ba0bfaf 100644 --- a/extras/AudioPluginHost/AudioPluginHost.jucer +++ b/extras/AudioPluginHost/AudioPluginHost.jucer @@ -203,6 +203,8 @@ + + true + + true + + + true + true @@ -278,6 +284,9 @@ true + + true + true @@ -1546,6 +1555,8 @@ + + diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters index 357d27d0c1..310f50db3d 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters @@ -349,6 +349,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates @@ -556,6 +562,9 @@ JUCE Modules\juce_core\containers + + JUCE Modules\juce_core\containers + JUCE Modules\juce_core\containers @@ -1989,6 +1998,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj index f5409fcd7f..5839c391d8 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj @@ -157,6 +157,12 @@ true + + true + + + true + true @@ -278,6 +284,9 @@ true + + true + true @@ -1546,6 +1555,8 @@ + + diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters index b7a61c47a1..d812985937 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters @@ -349,6 +349,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates @@ -556,6 +562,9 @@ JUCE Modules\juce_core\containers + + JUCE Modules\juce_core\containers + JUCE Modules\juce_core\containers @@ -1989,6 +1998,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj index 9d14dd96bd..fe1290651f 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj @@ -157,6 +157,12 @@ true + + true + + + true + true @@ -278,6 +284,9 @@ true + + true + true @@ -1546,6 +1555,8 @@ + + diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters index 9696b57ba3..5ecbb574bc 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters @@ -349,6 +349,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates @@ -556,6 +562,9 @@ JUCE Modules\juce_core\containers + + JUCE Modules\juce_core\containers + JUCE Modules\juce_core\containers @@ -1989,6 +1998,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates diff --git a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj index 3259f8cc02..5eeaa76fb4 100644 --- a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj @@ -157,6 +157,12 @@ true + + true + + + true + true @@ -278,6 +284,9 @@ true + + true + true @@ -1546,6 +1555,8 @@ + + diff --git a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters index 8edf98299d..4f24520951 100644 --- a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters @@ -349,6 +349,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates @@ -556,6 +562,9 @@ JUCE Modules\juce_core\containers + + JUCE Modules\juce_core\containers + JUCE Modules\juce_core\containers @@ -1989,6 +1998,12 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + + + Projucer\BinaryData\Templates + Projucer\BinaryData\Templates diff --git a/extras/Projucer/CMakeLists.txt b/extras/Projucer/CMakeLists.txt index c31a76c74c..819e638ec2 100644 --- a/extras/Projucer/CMakeLists.txt +++ b/extras/Projucer/CMakeLists.txt @@ -112,6 +112,10 @@ juce_add_binary_data(ProjucerData SOURCES Source/BinaryData/Templates/jucer_AudioComponentSimpleTemplate.h Source/BinaryData/Templates/jucer_AudioComponentTemplate.cpp Source/BinaryData/Templates/jucer_AudioComponentTemplate.h + Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.cpp + Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.h + Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.cpp + Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.h Source/BinaryData/Templates/jucer_AudioPluginEditorTemplate.cpp Source/BinaryData/Templates/jucer_AudioPluginEditorTemplate.h Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.cpp diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp index 7bd0332fe2..31349c8a11 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp +++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp @@ -6797,11 +6797,266 @@ static const unsigned char temp_binary_data_35[] = const char* jucer_AudioComponentTemplate_h = (const char*) temp_binary_data_35; -//================== jucer_AudioPluginEditorTemplate.cpp ================== +//================== jucer_AudioPluginARADocumentControllerTemplate.cpp ================== static const unsigned char temp_binary_data_36[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" +" This file was auto-generated!\r\n" +"\r\n" +" It contains the basic framework code for an ARA document controller implementation.\r\n" +"\r\n" +" ==============================================================================\r\n" +"*/\r\n" +"\r\n" +"%%aradocumentcontroller_headers%%\r\n" +"%%araplaybackrenderer_headers%%\r\n" +"\r\n" +"//==============================================================================\r\n" +"ARA::PlugIn::PlaybackRenderer* %%aradocumentcontroller_class_name%%::doCreatePlaybackRenderer() noexcept\r\n" +"{\r\n" +" return new %%araplaybackrenderer_class_name%% (getDocumentController());\r\n" +"}\r\n" +"\r\n" +"//==============================================================================\r\n" +"bool %%aradocumentcontroller_class_name%%::doRestoreObjectsFromStream (juce::ARAInputStream& input, const juce::ARARestoreObjectsFilter* filter) noexcept\r\n" +"{\r\n" +" // You should use this method to read any persistent data associated with\r\n" +" // your ARA model graph stored in an archive using the supplied ARAInputStream.\r\n" +" // Be sure to check the ARARestoreObjectsFilter to determine which objects to restore.\r\n" +" return true;\r\n" +"}\r\n" +"\r\n" +"bool %%aradocumentcontroller_class_name%%::doStoreObjectsToStream (juce::ARAOutputStream& output, const juce::ARAStoreObjectsFilter* filter) noexcept\r\n" +"{\r\n" +" // You should use this method to write any persistent data associated with\r\n" +" // your ARA model graph into the an archive using the supplied ARAOutputStream.\r\n" +" // Be sure to check the ARAStoreObjectsFilter to determine which objects to store.\r\n" +" return true;\r\n" +"}\r\n" +"\r\n" +"//==============================================================================\r\n" +"// This creates the static ARAFactory instances for the plugin.\r\n" +"const ARA::ARAFactory* JUCE_CALLTYPE createARAFactory()\r\n" +"{\r\n" +" return juce::ARADocumentControllerSpecialisation::createARAFactory<%%aradocumentcontroller_class_name%%>();\r\n" +"}\r\n"; + +const char* jucer_AudioPluginARADocumentControllerTemplate_cpp = (const char*) temp_binary_data_36; + +//================== jucer_AudioPluginARADocumentControllerTemplate.h ================== +static const unsigned char temp_binary_data_37[] = +"/*\r\n" +" ==============================================================================\r\n" +"\r\n" +" This file was auto-generated!\r\n" +"\r\n" +" It contains the basic framework code for an ARA document controller implementation.\r\n" +"\r\n" +" ==============================================================================\r\n" +"*/\r\n" +"\r\n" +"#pragma once\r\n" +"\r\n" +"#include \r\n" +"\r\n" +"//==============================================================================\r\n" +"/**\r\n" +"*/\r\n" +"class %%aradocumentcontroller_class_name%% : public juce::ARADocumentControllerSpecialisation\r\n" +"{\r\n" +"public:\r\n" +" //==============================================================================\r\n" +" using ARADocumentControllerSpecialisation::ARADocumentControllerSpecialisation;\r\n" +"\r\n" +"protected:\r\n" +" //==============================================================================\r\n" +" // Override document controller customization methods here\r\n" +"\r\n" +" ARAPlaybackRenderer* doCreatePlaybackRenderer() noexcept override;\r\n" +"\r\n" +" bool doRestoreObjectsFromStream (juce::ARAInputStream& input, const juce::ARARestoreObjectsFilter* filter) noexcept override;\r\n" +" bool doStoreObjectsToStream (juce::ARAOutputStream& output, const juce::ARAStoreObjectsFilter* filter) noexcept override;\r\n" +"\r\n" +"private:\r\n" +" //==============================================================================\r\n" +" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%aradocumentcontroller_class_name%%)\r\n" +"};\r\n"; + +const char* jucer_AudioPluginARADocumentControllerTemplate_h = (const char*) temp_binary_data_37; + +//================== jucer_AudioPluginARAPlaybackRendererTemplate.cpp ================== +static const unsigned char temp_binary_data_38[] = +"/*\r\n" +" ==============================================================================\r\n" +"\r\n" +" This file was auto-generated!\r\n" +"\r\n" +" It contains the basic framework code for an ARA playback renderer implementation.\r\n" +"\r\n" +" ==============================================================================\r\n" +"*/\r\n" +"\r\n" +"%%araplaybackrenderer_headers%%\r\n" +"\r\n" +"//==============================================================================\r\n" +"void %%araplaybackrenderer_class_name%%::prepareToPlay (double sampleRateIn, int maximumSamplesPerBlockIn, int numChannelsIn, juce::AudioProcessor::ProcessingPrecision, AlwaysNonRealtime alwaysNonRealtime)\r\n" +"{\r\n" +" numChannels = numChannelsIn;\r\n" +" sampleRate = sampleRateIn;\r\n" +" maximumSamplesPerBlock = maximumSamplesPerBlockIn;\r\n" +" useBufferedAudioSourceReader = alwaysNonRealtime == AlwaysNonRealtime::no;\r\n" +"}\r\n" +"\r\n" +"void %%araplaybackrenderer_class_name%%::releaseResources()\r\n" +"{\r\n" +"}\r\n" +"\r\n" +"//==============================================================================\r\n" +"bool %%araplaybackrenderer_class_name%%::processBlock (juce::AudioBuffer& buffer, juce::AudioProcessor::Realtime realtime, const juce::AudioPlayHead::CurrentPositionInfo& positionInfo) noexcept\r\n" +"{\r\n" +" const auto numSamples = buffer.getNumSamples();\r\n" +" jassert (numSamples <= maximumSamplesPerBlock);\r\n" +" jassert (numChannels == buffer.getNumChannels());\r\n" +" jassert (realtime == juce::AudioProcessor::Realtime::no || useBufferedAudioSourceReader);\r\n" +" const auto timeInSamples = positionInfo.timeInSamples;\r\n" +" const auto isPlaying = positionInfo.isPlaying;\r\n" +"\r\n" +" bool success = true;\r\n" +" bool didRenderAnyRegion = false;\r\n" +"\r\n" +" if (isPlaying)\r\n" +" {\r\n" +" const auto blockRange = juce::Range::withStartAndLength (timeInSamples, numSamples);\r\n" +"\r\n" +" for (const auto& playbackRegion : getPlaybackRegions())\r\n" +" {\r\n" +" // Evaluate region borders in song time, calculate sample range to render in song time.\r\n" +" // Note that this example does not use head- or tailtime, so the includeHeadAndTail\r\n" +" // parameter is set to false here - this might need to be adjusted in actual plug-ins.\r\n" +" const auto playbackSampleRange = playbackRegion->getSampleRange (sampleRate,\r\n" +" juce::ARAPlaybackRegion::IncludeHeadAndTail::no);\r\n" +" auto renderRange = blockRange.getIntersectionWith (playbackSampleRange);\r\n" +"\r\n" +" if (renderRange.isEmpty())\r\n" +" continue;\r\n" +"\r\n" +" // Evaluate region borders in modification/source time and calculate offset between\r\n" +" // song and source samples, then clip song samples accordingly\r\n" +" // (if an actual plug-in supports time stretching, this must be taken into account here).\r\n" +" juce::Range modificationSampleRange { playbackRegion->getStartInAudioModificationSamples(),\r\n" +" playbackRegion->getEndInAudioModificationSamples() };\r\n" +" const auto modificationSampleOffset = modificationSampleRange.getStart() - playbackSampleRange.getStart();\r\n" +"\r\n" +" renderRange = renderRange.getIntersectionWith (modificationSampleRange.movedToStartAt (playbackSampleRange.getStart()));\r\n" +"\r\n" +" if (renderRange.isEmpty())\r\n" +" continue;\r\n" +"\r\n" +" // Now calculate the samples in renderRange for this PlaybackRegion based on the ARA model\r\n" +" // graph. If didRenderAnyRegion is true, add the region's output samples in renderRange to\r\n" +" // the buffer. Otherwise the buffer needs to be initialised so the sample value must be\r\n" +" // overwritten.\r\n" +" const int numSamplesToRead = (int) renderRange.getLength();\r\n" +" const int startInBuffer = (int) (renderRange.getStart() - blockRange.getStart());\r\n" +" const auto startInSource = renderRange.getStart() + modificationSampleOffset;\r\n" +"\r\n" +" for (int c = 0; c < numChannels; ++c)\r\n" +" {\r\n" +" auto* channelData = buffer.getWritePointer (c);\r\n" +"\r\n" +" for (int i = 0; i < numSamplesToRead; ++i)\r\n" +" {\r\n" +" // Calculate region output sample at index startInSource + i ...\r\n" +" float sample = 0.0f;\r\n" +"\r\n" +" if (didRenderAnyRegion)\r\n" +" channelData[startInBuffer + i] += sample;\r\n" +" else\r\n" +" channelData[startInBuffer + i] = sample;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" // If rendering first region, clear any excess at start or end of the region.\r\n" +" if (! didRenderAnyRegion)\r\n" +" {\r\n" +" if (startInBuffer != 0)\r\n" +" buffer.clear (0, startInBuffer);\r\n" +"\r\n" +" const int endInBuffer = startInBuffer + numSamples;\r\n" +" const int remainingSamples = numSamples - endInBuffer;\r\n" +"\r\n" +" if (remainingSamples != 0)\r\n" +" buffer.clear (endInBuffer, remainingSamples);\r\n" +"\r\n" +" didRenderAnyRegion = true;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" if (! didRenderAnyRegion)\r\n" +" buffer.clear();\r\n" +"\r\n" +" return success;\r\n" +"}\r\n"; + +const char* jucer_AudioPluginARAPlaybackRendererTemplate_cpp = (const char*) temp_binary_data_38; + +//================== jucer_AudioPluginARAPlaybackRendererTemplate.h ================== +static const unsigned char temp_binary_data_39[] = +"/*\r\n" +" ==============================================================================\r\n" +"\r\n" +" This file was auto-generated!\r\n" +"\r\n" +" It contains the basic framework code for an ARA playback renderer implementation.\r\n" +"\r\n" +" ==============================================================================\r\n" +"*/\r\n" +"\r\n" +"#pragma once\r\n" +"\r\n" +"#include \r\n" +"\r\n" +"//==============================================================================\r\n" +"/**\r\n" +"*/\r\n" +"class %%araplaybackrenderer_class_name%% : public juce::ARAPlaybackRenderer\r\n" +"{\r\n" +"public:\r\n" +" //==============================================================================\r\n" +" using juce::ARAPlaybackRenderer::ARAPlaybackRenderer;\r\n" +"\r\n" +" //==============================================================================\r\n" +" void prepareToPlay (double sampleRate,\r\n" +" int maximumSamplesPerBlock,\r\n" +" int numChannels,\r\n" +" juce::AudioProcessor::ProcessingPrecision,\r\n" +" AlwaysNonRealtime alwaysNonRealtime) override;\r\n" +" void releaseResources() override;\r\n" +"\r\n" +" //==============================================================================\r\n" +" bool processBlock (juce::AudioBuffer & buffer,\r\n" +" juce::AudioProcessor::Realtime realtime,\r\n" +" const juce::AudioPlayHead::CurrentPositionInfo& positionInfo) noexcept override;\r\n" +"\r\n" +"private:\r\n" +" //==============================================================================\r\n" +" double sampleRate = 44100.0;\r\n" +" int maximumSamplesPerBlock = 4096;\r\n" +" int numChannels = 1;\r\n" +" bool useBufferedAudioSourceReader = true;\r\n" +"\r\n" +" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%araplaybackrenderer_class_name%%)\r\n" +"};\r\n"; + +const char* jucer_AudioPluginARAPlaybackRendererTemplate_h = (const char*) temp_binary_data_39; + +//================== jucer_AudioPluginEditorTemplate.cpp ================== +static const unsigned char temp_binary_data_40[] = +"/*\r\n" +" ==============================================================================\r\n" +"\r\n" " This file contains the basic framework code for a JUCE plugin editor.\r\n" "\r\n" " ==============================================================================\r\n" @@ -6839,10 +7094,10 @@ static const unsigned char temp_binary_data_36[] = " // subcomponents in your editor..\r\n" "}\r\n"; -const char* jucer_AudioPluginEditorTemplate_cpp = (const char*) temp_binary_data_36; +const char* jucer_AudioPluginEditorTemplate_cpp = (const char*) temp_binary_data_40; //================== jucer_AudioPluginEditorTemplate.h ================== -static const unsigned char temp_binary_data_37[] = +static const unsigned char temp_binary_data_41[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6876,10 +7131,10 @@ static const unsigned char temp_binary_data_37[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%editor_class_name%%)\r\n" "};\r\n"; -const char* jucer_AudioPluginEditorTemplate_h = (const char*) temp_binary_data_37; +const char* jucer_AudioPluginEditorTemplate_h = (const char*) temp_binary_data_41; //================== jucer_AudioPluginFilterTemplate.cpp ================== -static const unsigned char temp_binary_data_38[] = +static const unsigned char temp_binary_data_42[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7071,10 +7326,10 @@ static const unsigned char temp_binary_data_38[] = " return new %%filter_class_name%%();\r\n" "}\r\n"; -const char* jucer_AudioPluginFilterTemplate_cpp = (const char*) temp_binary_data_38; +const char* jucer_AudioPluginFilterTemplate_cpp = (const char*) temp_binary_data_42; //================== jucer_AudioPluginFilterTemplate.h ================== -static const unsigned char temp_binary_data_39[] = +static const unsigned char temp_binary_data_43[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7091,6 +7346,9 @@ static const unsigned char temp_binary_data_39[] = "/**\r\n" "*/\r\n" "class %%filter_class_name%% : public juce::AudioProcessor\r\n" +" #if JucePlugin_Enable_ARA\r\n" +" , public juce::AudioProcessorARAExtension\r\n" +" #endif\r\n" "{\r\n" "public:\r\n" " //==============================================================================\r\n" @@ -7135,10 +7393,10 @@ static const unsigned char temp_binary_data_39[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%filter_class_name%%)\r\n" "};\r\n"; -const char* jucer_AudioPluginFilterTemplate_h = (const char*) temp_binary_data_39; +const char* jucer_AudioPluginFilterTemplate_h = (const char*) temp_binary_data_43; //================== jucer_ComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_40[] = +static const unsigned char temp_binary_data_44[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7214,10 +7472,10 @@ static const unsigned char temp_binary_data_40[] = "//[EndFile] You can add extra defines here...\r\n" "//[/EndFile]\r\n"; -const char* jucer_ComponentTemplate_cpp = (const char*) temp_binary_data_40; +const char* jucer_ComponentTemplate_cpp = (const char*) temp_binary_data_44; //================== jucer_ComponentTemplate.h ================== -static const unsigned char temp_binary_data_41[] = +static const unsigned char temp_binary_data_45[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7280,10 +7538,10 @@ static const unsigned char temp_binary_data_41[] = "//[EndFile] You can add extra defines here...\r\n" "//[/EndFile]\r\n"; -const char* jucer_ComponentTemplate_h = (const char*) temp_binary_data_41; +const char* jucer_ComponentTemplate_h = (const char*) temp_binary_data_45; //================== jucer_ContentCompSimpleTemplate.h ================== -static const unsigned char temp_binary_data_42[] = +static const unsigned char temp_binary_data_46[] = "#pragma once\r\n" "\r\n" "%%include_juce%%\r\n" @@ -7333,10 +7591,10 @@ static const unsigned char temp_binary_data_42[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_ContentCompSimpleTemplate_h = (const char*) temp_binary_data_42; +const char* jucer_ContentCompSimpleTemplate_h = (const char*) temp_binary_data_46; //================== jucer_ContentCompTemplate.cpp ================== -static const unsigned char temp_binary_data_43[] = +static const unsigned char temp_binary_data_47[] = "%%include_corresponding_header%%\r\n" "\r\n" "//==============================================================================\r\n" @@ -7367,10 +7625,10 @@ static const unsigned char temp_binary_data_43[] = " // update their positions.\r\n" "}\r\n"; -const char* jucer_ContentCompTemplate_cpp = (const char*) temp_binary_data_43; +const char* jucer_ContentCompTemplate_cpp = (const char*) temp_binary_data_47; //================== jucer_ContentCompTemplate.h ================== -static const unsigned char temp_binary_data_44[] = +static const unsigned char temp_binary_data_48[] = "#pragma once\r\n" "\r\n" "%%include_juce%%\r\n" @@ -7399,10 +7657,10 @@ static const unsigned char temp_binary_data_44[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_ContentCompTemplate_h = (const char*) temp_binary_data_44; +const char* jucer_ContentCompTemplate_h = (const char*) temp_binary_data_48; //================== jucer_InlineComponentTemplate.h ================== -static const unsigned char temp_binary_data_45[] = +static const unsigned char temp_binary_data_49[] = "//==============================================================================\r\n" "class %%component_class%% : public juce::Component\r\n" "{\r\n" @@ -7444,10 +7702,10 @@ static const unsigned char temp_binary_data_45[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%component_class%%)\r\n" "};\r\n"; -const char* jucer_InlineComponentTemplate_h = (const char*) temp_binary_data_45; +const char* jucer_InlineComponentTemplate_h = (const char*) temp_binary_data_49; //================== jucer_MainConsoleAppTemplate.cpp ================== -static const unsigned char temp_binary_data_46[] = +static const unsigned char temp_binary_data_50[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7468,10 +7726,10 @@ static const unsigned char temp_binary_data_46[] = " return 0;\r\n" "}\r\n"; -const char* jucer_MainConsoleAppTemplate_cpp = (const char*) temp_binary_data_46; +const char* jucer_MainConsoleAppTemplate_cpp = (const char*) temp_binary_data_50; //================== jucer_MainTemplate_NoWindow.cpp ================== -static const unsigned char temp_binary_data_47[] = +static const unsigned char temp_binary_data_51[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7524,10 +7782,10 @@ static const unsigned char temp_binary_data_47[] = "// This macro generates the main() routine that launches the app.\r\n" "START_JUCE_APPLICATION (%%app_class_name%%)\r\n"; -const char* jucer_MainTemplate_NoWindow_cpp = (const char*) temp_binary_data_47; +const char* jucer_MainTemplate_NoWindow_cpp = (const char*) temp_binary_data_51; //================== jucer_MainTemplate_Window.cpp ================== -static const unsigned char temp_binary_data_48[] = +static const unsigned char temp_binary_data_52[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7633,10 +7891,10 @@ static const unsigned char temp_binary_data_48[] = "// This macro generates the main() routine that launches the app.\r\n" "START_JUCE_APPLICATION (%%app_class_name%%)\r\n"; -const char* jucer_MainTemplate_Window_cpp = (const char*) temp_binary_data_48; +const char* jucer_MainTemplate_Window_cpp = (const char*) temp_binary_data_52; //================== jucer_NewComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_49[] = +static const unsigned char temp_binary_data_53[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7689,10 +7947,10 @@ static const unsigned char temp_binary_data_49[] = "\r\n" "}\r\n"; -const char* jucer_NewComponentTemplate_cpp = (const char*) temp_binary_data_49; +const char* jucer_NewComponentTemplate_cpp = (const char*) temp_binary_data_53; //================== jucer_NewComponentTemplate.h ================== -static const unsigned char temp_binary_data_50[] = +static const unsigned char temp_binary_data_54[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7723,10 +7981,10 @@ static const unsigned char temp_binary_data_50[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%component_class%%)\r\n" "};\r\n"; -const char* jucer_NewComponentTemplate_h = (const char*) temp_binary_data_50; +const char* jucer_NewComponentTemplate_h = (const char*) temp_binary_data_54; //================== jucer_NewCppFileTemplate.cpp ================== -static const unsigned char temp_binary_data_51[] = +static const unsigned char temp_binary_data_55[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7739,10 +7997,10 @@ static const unsigned char temp_binary_data_51[] = "\r\n" "%%include_corresponding_header%%\r\n"; -const char* jucer_NewCppFileTemplate_cpp = (const char*) temp_binary_data_51; +const char* jucer_NewCppFileTemplate_cpp = (const char*) temp_binary_data_55; //================== jucer_NewCppFileTemplate.h ================== -static const unsigned char temp_binary_data_52[] = +static const unsigned char temp_binary_data_56[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7755,10 +8013,10 @@ static const unsigned char temp_binary_data_52[] = "\r\n" "#pragma once\r\n"; -const char* jucer_NewCppFileTemplate_h = (const char*) temp_binary_data_52; +const char* jucer_NewCppFileTemplate_h = (const char*) temp_binary_data_56; //================== jucer_NewInlineComponentTemplate.h ================== -static const unsigned char temp_binary_data_53[] = +static const unsigned char temp_binary_data_57[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7821,10 +8079,10 @@ static const unsigned char temp_binary_data_53[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%component_class%%)\r\n" "};\r\n"; -const char* jucer_NewInlineComponentTemplate_h = (const char*) temp_binary_data_53; +const char* jucer_NewInlineComponentTemplate_h = (const char*) temp_binary_data_57; //================== jucer_OpenGLComponentSimpleTemplate.h ================== -static const unsigned char temp_binary_data_54[] = +static const unsigned char temp_binary_data_58[] = "#pragma once\r\n" "\r\n" "%%include_juce%%\r\n" @@ -7893,10 +8151,10 @@ static const unsigned char temp_binary_data_54[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_OpenGLComponentSimpleTemplate_h = (const char*) temp_binary_data_54; +const char* jucer_OpenGLComponentSimpleTemplate_h = (const char*) temp_binary_data_58; //================== jucer_OpenGLComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_55[] = +static const unsigned char temp_binary_data_59[] = "%%include_corresponding_header%%\r\n" "\r\n" "//==============================================================================\r\n" @@ -7946,10 +8204,10 @@ static const unsigned char temp_binary_data_55[] = " // update their positions.\r\n" "}\r\n"; -const char* jucer_OpenGLComponentTemplate_cpp = (const char*) temp_binary_data_55; +const char* jucer_OpenGLComponentTemplate_cpp = (const char*) temp_binary_data_59; //================== jucer_OpenGLComponentTemplate.h ================== -static const unsigned char temp_binary_data_56[] = +static const unsigned char temp_binary_data_60[] = "#pragma once\r\n" "\r\n" "%%include_juce%%\r\n" @@ -7983,10 +8241,10 @@ static const unsigned char temp_binary_data_56[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_OpenGLComponentTemplate_h = (const char*) temp_binary_data_56; +const char* jucer_OpenGLComponentTemplate_h = (const char*) temp_binary_data_60; //================== jucer_PIPAudioProcessorTemplate.h ================== -static const unsigned char temp_binary_data_57[] = +static const unsigned char temp_binary_data_61[] = "class %%class_name%% : public juce::AudioProcessor\r\n" "{\r\n" "public:\r\n" @@ -8095,10 +8353,10 @@ static const unsigned char temp_binary_data_57[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%class_name%%)\r\n" "};\r\n"; -const char* jucer_PIPAudioProcessorTemplate_h = (const char*) temp_binary_data_57; +const char* jucer_PIPAudioProcessorTemplate_h = (const char*) temp_binary_data_61; //================== jucer_PIPTemplate.h ================== -static const unsigned char temp_binary_data_58[] = +static const unsigned char temp_binary_data_62[] = "/*******************************************************************************\r\n" " The block below describes the properties of this PIP. A PIP is a short snippet\r\n" " of code that can be read by the Projucer and used to generate a JUCE project.\r\n" @@ -8117,10 +8375,10 @@ static const unsigned char temp_binary_data_58[] = "//==============================================================================\r\n" "%%pip_code%%\r\n"; -const char* jucer_PIPTemplate_h = (const char*) temp_binary_data_58; +const char* jucer_PIPTemplate_h = (const char*) temp_binary_data_62; //================== colourscheme_dark.xml ================== -static const unsigned char temp_binary_data_59[] = +static const unsigned char temp_binary_data_63[] = "\r\n" "\r\n" "\r\n" @@ -8145,10 +8403,10 @@ static const unsigned char temp_binary_data_59[] = " \r\n" "\r\n"; -const char* colourscheme_dark_xml = (const char*) temp_binary_data_59; +const char* colourscheme_dark_xml = (const char*) temp_binary_data_63; //================== colourscheme_light.xml ================== -static const unsigned char temp_binary_data_60[] = +static const unsigned char temp_binary_data_64[] = "\r\n" "\r\n" "\r\n" @@ -8173,10 +8431,10 @@ static const unsigned char temp_binary_data_60[] = " \r\n" "\r\n"; -const char* colourscheme_light_xml = (const char*) temp_binary_data_60; +const char* colourscheme_light_xml = (const char*) temp_binary_data_64; //================== juce_runtime_arch_detection.cpp ================== -static const unsigned char temp_binary_data_61[] = +static const unsigned char temp_binary_data_65[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -8255,7 +8513,7 @@ static const unsigned char temp_binary_data_61[] = "\r\n" "#endif\r\n"; -const char* juce_runtime_arch_detection_cpp = (const char*) temp_binary_data_61; +const char* juce_runtime_arch_detection_cpp = (const char*) temp_binary_data_65; const char* getNamedResource (const char* resourceNameUTF8, int& numBytes); @@ -8305,10 +8563,14 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) case 0xfb6f6d96: numBytes = 3554; return jucer_AudioComponentSimpleTemplate_h; case 0xafccbd3f: numBytes = 2941; return jucer_AudioComponentTemplate_cpp; case 0x915d7304: numBytes = 1187; return jucer_AudioComponentTemplate_h; + case 0x744d44d6: numBytes = 1920; return jucer_AudioPluginARADocumentControllerTemplate_cpp; + case 0x3eb8f45b: numBytes = 1439; return jucer_AudioPluginARADocumentControllerTemplate_h; + case 0xea35a37d: numBytes = 5192; return jucer_AudioPluginARAPlaybackRendererTemplate_cpp; + case 0x78a6d0c2: numBytes = 1765; return jucer_AudioPluginARAPlaybackRendererTemplate_h; case 0x27c5a93a: numBytes = 1355; return jucer_AudioPluginEditorTemplate_cpp; case 0x4d0721bf: numBytes = 973; return jucer_AudioPluginEditorTemplate_h; case 0x51b49ac5: numBytes = 6218; return jucer_AudioPluginFilterTemplate_cpp; - case 0x488afa0a: numBytes = 2299; return jucer_AudioPluginFilterTemplate_h; + case 0x488afa0a: numBytes = 2462; return jucer_AudioPluginFilterTemplate_h; case 0xabad7041: numBytes = 2147; return jucer_ComponentTemplate_cpp; case 0xfc72fe86: numBytes = 2065; return jucer_ComponentTemplate_h; case 0x1657b643: numBytes = 1524; return jucer_ContentCompSimpleTemplate_h; @@ -8376,6 +8638,10 @@ const char* namedResourceList[] = "jucer_AudioComponentSimpleTemplate_h", "jucer_AudioComponentTemplate_cpp", "jucer_AudioComponentTemplate_h", + "jucer_AudioPluginARADocumentControllerTemplate_cpp", + "jucer_AudioPluginARADocumentControllerTemplate_h", + "jucer_AudioPluginARAPlaybackRendererTemplate_cpp", + "jucer_AudioPluginARAPlaybackRendererTemplate_h", "jucer_AudioPluginEditorTemplate_cpp", "jucer_AudioPluginEditorTemplate_h", "jucer_AudioPluginFilterTemplate_cpp", @@ -8442,6 +8708,10 @@ const char* originalFilenames[] = "jucer_AudioComponentSimpleTemplate.h", "jucer_AudioComponentTemplate.cpp", "jucer_AudioComponentTemplate.h", + "jucer_AudioPluginARADocumentControllerTemplate.cpp", + "jucer_AudioPluginARADocumentControllerTemplate.h", + "jucer_AudioPluginARAPlaybackRendererTemplate.cpp", + "jucer_AudioPluginARAPlaybackRendererTemplate.h", "jucer_AudioPluginEditorTemplate.cpp", "jucer_AudioPluginEditorTemplate.h", "jucer_AudioPluginFilterTemplate.cpp", diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h index a21c2091c3..18ce0656d0 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.h +++ b/extras/Projucer/JuceLibraryCode/BinaryData.h @@ -116,6 +116,18 @@ namespace BinaryData extern const char* jucer_AudioComponentTemplate_h; const int jucer_AudioComponentTemplate_hSize = 1187; + extern const char* jucer_AudioPluginARADocumentControllerTemplate_cpp; + const int jucer_AudioPluginARADocumentControllerTemplate_cppSize = 1920; + + extern const char* jucer_AudioPluginARADocumentControllerTemplate_h; + const int jucer_AudioPluginARADocumentControllerTemplate_hSize = 1439; + + extern const char* jucer_AudioPluginARAPlaybackRendererTemplate_cpp; + const int jucer_AudioPluginARAPlaybackRendererTemplate_cppSize = 5192; + + extern const char* jucer_AudioPluginARAPlaybackRendererTemplate_h; + const int jucer_AudioPluginARAPlaybackRendererTemplate_hSize = 1765; + extern const char* jucer_AudioPluginEditorTemplate_cpp; const int jucer_AudioPluginEditorTemplate_cppSize = 1355; @@ -126,7 +138,7 @@ namespace BinaryData const int jucer_AudioPluginFilterTemplate_cppSize = 6218; extern const char* jucer_AudioPluginFilterTemplate_h; - const int jucer_AudioPluginFilterTemplate_hSize = 2299; + const int jucer_AudioPluginFilterTemplate_hSize = 2462; extern const char* jucer_ComponentTemplate_cpp; const int jucer_ComponentTemplate_cppSize = 2147; @@ -195,7 +207,7 @@ namespace BinaryData const int juce_runtime_arch_detection_cppSize = 2760; // Number of elements in the namedResourceList and originalFileNames arrays. - const int namedResourceListSize = 62; + const int namedResourceListSize = 66; // Points to the start of a list of resource names. extern const char* namedResourceList[]; diff --git a/extras/Projucer/Projucer.jucer b/extras/Projucer/Projucer.jucer index 9400d5b4a5..e64b19b7d9 100644 --- a/extras/Projucer/Projucer.jucer +++ b/extras/Projucer/Projucer.jucer @@ -257,6 +257,14 @@ resource="1" file="Source/BinaryData/Templates/jucer_AudioComponentTemplate.cpp"/> + + + + ; @@ -87,6 +88,7 @@ namespace NewProjectTemplates if (opt == FileCreationOptions::header) return "header"; if (opt == FileCreationOptions::headerAndCpp) return "headercpp"; if (opt == FileCreationOptions::processorAndEditor) return "processoreditor"; + if (opt == FileCreationOptions::araPluginFiles) return "arapluginfiles"; jassertfalse; return {}; @@ -99,6 +101,7 @@ namespace NewProjectTemplates if (opt == "header") return FileCreationOptions::header; if (opt == "headercpp") return FileCreationOptions::headerAndCpp; if (opt == "processoreditor") return FileCreationOptions::processorAndEditor; + if (opt == "arapluginfiles") return FileCreationOptions::araPluginFiles; jassertfalse; return {}; @@ -111,6 +114,7 @@ namespace NewProjectTemplates if (opt == FileCreationOptions::header) return "Main.cpp + .h"; if (opt == FileCreationOptions::headerAndCpp) return "Main.cpp + .h/.cpp "; if (opt == FileCreationOptions::processorAndEditor) return "Processor and Editor"; + if (opt == FileCreationOptions::araPluginFiles) return "ARA Plugin Files"; jassertfalse; return {}; @@ -222,6 +226,24 @@ namespace NewProjectTemplates FileCreationOptions::processorAndEditor }, + { ProjectCategory::plugin, + "ARA", "Creates an ARA audio plug-in, augmenting the basic audio plug-in with ARA functionality.", + build_tools::ProjectType_ARAAudioPlugin::getTypeName(), + BinaryData::wizard_AudioPlugin_svg, + getModulesRequiredForAudioProcessor(), + { + { FileCreationOptions::araPluginFiles, { { "PluginProcessor.cpp", "jucer_AudioPluginFilterTemplate_cpp" }, + { "PluginProcessor.h", "jucer_AudioPluginFilterTemplate_h" }, + { "PluginEditor.cpp", "jucer_AudioPluginEditorTemplate_cpp" }, + { "PluginEditor.h", "jucer_AudioPluginEditorTemplate_h" }, + { "PluginARADocumentController.cpp", "jucer_AudioPluginARADocumentControllerTemplate_cpp" }, + { "PluginARADocumentController.h", "jucer_AudioPluginARADocumentControllerTemplate_h" }, + { "PluginARAPlaybackRenderer.cpp", "jucer_AudioPluginARAPlaybackRendererTemplate_cpp" }, + { "PluginARAPlaybackRenderer.h", "jucer_AudioPluginARAPlaybackRendererTemplate_h" }} } + }, + FileCreationOptions::araPluginFiles + }, + { ProjectCategory::library, "Static Library", "Creates a static library.", build_tools::ProjectType_StaticLibrary::getTypeName(), diff --git a/extras/Projucer/Source/Application/StartPage/jucer_NewProjectWizard.cpp b/extras/Projucer/Source/Application/StartPage/jucer_NewProjectWizard.cpp index 7f0682a5e7..18d497ba9f 100644 --- a/extras/Projucer/Source/Application/StartPage/jucer_NewProjectWizard.cpp +++ b/extras/Projucer/Source/Application/StartPage/jucer_NewProjectWizard.cpp @@ -114,11 +114,28 @@ static std::map getPluginFileTokenReplacements (const String& na processorClassName = processorClassName.substring (0, 1).toUpperCase() + processorClassName.substring (1); auto editorClassName = processorClassName + "Editor"; + const auto araDocumentControllerCppFile = sourceFolder.getChildFile ("PluginARADocumentController.cpp"); + const auto araDocumentControllerHFile = araDocumentControllerCppFile.withFileExtension (".h"); + const auto araPlaybackRendererCppFile = sourceFolder.getChildFile ("PluginARAPlaybackRenderer.cpp"); + const auto araPlaybackRendererHFile = araPlaybackRendererCppFile.withFileExtension (".h"); + + const auto araDocumentControllerHInclude = CodeHelpers::createIncludeStatement (araDocumentControllerHFile, araDocumentControllerCppFile); + const auto araPlaybackRendererHInclude = CodeHelpers::createIncludeStatement (araPlaybackRendererHFile, araPlaybackRendererCppFile); + + auto araDocumentControllerClassName = build_tools::makeValidIdentifier (name, true, true, false) + "DocumentController"; + araDocumentControllerClassName = araDocumentControllerClassName.substring (0, 1).toUpperCase() + araDocumentControllerClassName.substring (1); + auto araPlaybackRendererClassName = build_tools::makeValidIdentifier (name, true, true, false) + "PlaybackRenderer"; + araPlaybackRendererClassName = araPlaybackRendererClassName.substring (0, 1).toUpperCase() + araPlaybackRendererClassName.substring (1); + tokenReplacements.insert ({"%%filter_headers%%", processorHInclude + newLine + editorHInclude }); tokenReplacements.insert ({"%%filter_class_name%%", processorClassName }); tokenReplacements.insert ({"%%editor_class_name%%", editorClassName }); tokenReplacements.insert ({"%%editor_cpp_headers%%", processorHInclude + newLine + editorHInclude }); tokenReplacements.insert ({"%%editor_headers%%", getJuceHeaderInclude() + newLine + processorHInclude }); + tokenReplacements.insert ({"%%aradocumentcontroller_headers%%", araDocumentControllerHInclude }); + tokenReplacements.insert ({"%%aradocumentcontroller_class_name%%", araDocumentControllerClassName }); + tokenReplacements.insert ({"%%araplaybackrenderer_headers%%", araPlaybackRendererHInclude }); + tokenReplacements.insert ({"%%araplaybackrenderer_class_name%%", araPlaybackRendererClassName }); return tokenReplacements; } diff --git a/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h b/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h index c77e5f40ba..a257ee75a8 100644 --- a/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h +++ b/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h @@ -218,6 +218,8 @@ private: "If you are building a legacy VST plug-in then this path should point to a VST2 SDK. " "The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK or JUCE version 5.3.2. " "You also need a VST2 license from Steinberg to distribute VST2 plug-ins."); + builder.add (new FilePathPropertyComponent (araPathValue, "ARA SDK", true, isThisOS), + "If you are building ARA enabled plug-ins, this should be the path to the ARA SDK folder."); if (getSelectedOS() != TargetOS::linux) { @@ -263,6 +265,7 @@ private: userModulePathValue = settings.getStoredPath (Ids::defaultUserModulePath, os); vstPathValue = settings.getStoredPath (Ids::vstLegacyPath, os); aaxPathValue = settings.getStoredPath (Ids::aaxPath, os); + araPathValue = settings.getStoredPath (Ids::araPath, os); androidSDKPathValue = settings.getStoredPath (Ids::androidSDKPath, os); clionExePathValue = settings.getStoredPath (Ids::clionExePath, os); androidStudioExePathValue = settings.getStoredPath (Ids::androidStudioExePath, os); @@ -275,6 +278,7 @@ private: userModulePathValue .resetToDefault(); vstPathValue .resetToDefault(); aaxPathValue .resetToDefault(); + araPathValue .resetToDefault(); androidSDKPathValue .resetToDefault(); clionExePathValue .resetToDefault(); androidStudioExePathValue.resetToDefault(); @@ -286,7 +290,7 @@ private: Value selectedOSValue; ValueTreePropertyWithDefault jucePathValue, juceModulePathValue, userModulePathValue, - vstPathValue, aaxPathValue, androidSDKPathValue, + vstPathValue, aaxPathValue, araPathValue, androidSDKPathValue, clionExePathValue, androidStudioExePathValue; Viewport propertyViewport; diff --git a/extras/Projucer/Source/Application/jucer_CommandLine.cpp b/extras/Projucer/Source/Application/jucer_CommandLine.cpp index a5181e8e67..caf1330ed3 100644 --- a/extras/Projucer/Source/Application/jucer_CommandLine.cpp +++ b/extras/Projucer/Source/Application/jucer_CommandLine.cpp @@ -708,7 +708,7 @@ namespace static bool isValidPathIdentifier (const String& id, const String& os) { - return id == "vstLegacyPath" || (id == "aaxPath" && os != "linux") + return id == "vstLegacyPath" || (id == "aaxPath" && os != "linux") || id == "araPath" || id == "androidSDKPath" || id == "defaultJuceModulePath" || id == "defaultUserModulePath"; } diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.cpp b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.cpp new file mode 100644 index 0000000000..ebbe4952a3 --- /dev/null +++ b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.cpp @@ -0,0 +1,42 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for an ARA document controller implementation. + + ============================================================================== +*/ + +%%aradocumentcontroller_headers%% +%%araplaybackrenderer_headers%% + +//============================================================================== +ARA::PlugIn::PlaybackRenderer* %%aradocumentcontroller_class_name%%::doCreatePlaybackRenderer() noexcept +{ + return new %%araplaybackrenderer_class_name%% (getDocumentController()); +} + +//============================================================================== +bool %%aradocumentcontroller_class_name%%::doRestoreObjectsFromStream (juce::ARAInputStream& input, const juce::ARARestoreObjectsFilter* filter) noexcept +{ + // You should use this method to read any persistent data associated with + // your ARA model graph stored in an archive using the supplied ARAInputStream. + // Be sure to check the ARARestoreObjectsFilter to determine which objects to restore. + return true; +} + +bool %%aradocumentcontroller_class_name%%::doStoreObjectsToStream (juce::ARAOutputStream& output, const juce::ARAStoreObjectsFilter* filter) noexcept +{ + // You should use this method to write any persistent data associated with + // your ARA model graph into the an archive using the supplied ARAOutputStream. + // Be sure to check the ARAStoreObjectsFilter to determine which objects to store. + return true; +} + +//============================================================================== +// This creates the static ARAFactory instances for the plugin. +const ARA::ARAFactory* JUCE_CALLTYPE createARAFactory() +{ + return juce::ARADocumentControllerSpecialisation::createARAFactory<%%aradocumentcontroller_class_name%%>(); +} diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.h b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.h new file mode 100644 index 0000000000..8dbcb340e5 --- /dev/null +++ b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARADocumentControllerTemplate.h @@ -0,0 +1,36 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for an ARA document controller implementation. + + ============================================================================== +*/ + +#pragma once + +#include + +//============================================================================== +/** +*/ +class %%aradocumentcontroller_class_name%% : public juce::ARADocumentControllerSpecialisation +{ +public: + //============================================================================== + using ARADocumentControllerSpecialisation::ARADocumentControllerSpecialisation; + +protected: + //============================================================================== + // Override document controller customization methods here + + ARAPlaybackRenderer* doCreatePlaybackRenderer() noexcept override; + + bool doRestoreObjectsFromStream (juce::ARAInputStream& input, const juce::ARARestoreObjectsFilter* filter) noexcept override; + bool doStoreObjectsToStream (juce::ARAOutputStream& output, const juce::ARAStoreObjectsFilter* filter) noexcept override; + +private: + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%aradocumentcontroller_class_name%%) +}; diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.cpp b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.cpp new file mode 100644 index 0000000000..f7e547ba82 --- /dev/null +++ b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.cpp @@ -0,0 +1,112 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for an ARA playback renderer implementation. + + ============================================================================== +*/ + +%%araplaybackrenderer_headers%% + +//============================================================================== +void %%araplaybackrenderer_class_name%%::prepareToPlay (double sampleRateIn, int maximumSamplesPerBlockIn, int numChannelsIn, juce::AudioProcessor::ProcessingPrecision, AlwaysNonRealtime alwaysNonRealtime) +{ + numChannels = numChannelsIn; + sampleRate = sampleRateIn; + maximumSamplesPerBlock = maximumSamplesPerBlockIn; + useBufferedAudioSourceReader = alwaysNonRealtime == AlwaysNonRealtime::no; +} + +void %%araplaybackrenderer_class_name%%::releaseResources() +{ +} + +//============================================================================== +bool %%araplaybackrenderer_class_name%%::processBlock (juce::AudioBuffer& buffer, juce::AudioProcessor::Realtime realtime, const juce::AudioPlayHead::CurrentPositionInfo& positionInfo) noexcept +{ + const auto numSamples = buffer.getNumSamples(); + jassert (numSamples <= maximumSamplesPerBlock); + jassert (numChannels == buffer.getNumChannels()); + jassert (realtime == juce::AudioProcessor::Realtime::no || useBufferedAudioSourceReader); + const auto timeInSamples = positionInfo.timeInSamples; + const auto isPlaying = positionInfo.isPlaying; + + bool success = true; + bool didRenderAnyRegion = false; + + if (isPlaying) + { + const auto blockRange = juce::Range::withStartAndLength (timeInSamples, numSamples); + + for (const auto& playbackRegion : getPlaybackRegions()) + { + // Evaluate region borders in song time, calculate sample range to render in song time. + // Note that this example does not use head- or tailtime, so the includeHeadAndTail + // parameter is set to false here - this might need to be adjusted in actual plug-ins. + const auto playbackSampleRange = playbackRegion->getSampleRange (sampleRate, + juce::ARAPlaybackRegion::IncludeHeadAndTail::no); + auto renderRange = blockRange.getIntersectionWith (playbackSampleRange); + + if (renderRange.isEmpty()) + continue; + + // Evaluate region borders in modification/source time and calculate offset between + // song and source samples, then clip song samples accordingly + // (if an actual plug-in supports time stretching, this must be taken into account here). + juce::Range modificationSampleRange { playbackRegion->getStartInAudioModificationSamples(), + playbackRegion->getEndInAudioModificationSamples() }; + const auto modificationSampleOffset = modificationSampleRange.getStart() - playbackSampleRange.getStart(); + + renderRange = renderRange.getIntersectionWith (modificationSampleRange.movedToStartAt (playbackSampleRange.getStart())); + + if (renderRange.isEmpty()) + continue; + + // Now calculate the samples in renderRange for this PlaybackRegion based on the ARA model + // graph. If didRenderAnyRegion is true, add the region's output samples in renderRange to + // the buffer. Otherwise the buffer needs to be initialised so the sample value must be + // overwritten. + const int numSamplesToRead = (int) renderRange.getLength(); + const int startInBuffer = (int) (renderRange.getStart() - blockRange.getStart()); + const auto startInSource = renderRange.getStart() + modificationSampleOffset; + + for (int c = 0; c < numChannels; ++c) + { + auto* channelData = buffer.getWritePointer (c); + + for (int i = 0; i < numSamplesToRead; ++i) + { + // Calculate region output sample at index startInSource + i ... + float sample = 0.0f; + + if (didRenderAnyRegion) + channelData[startInBuffer + i] += sample; + else + channelData[startInBuffer + i] = sample; + } + } + + // If rendering first region, clear any excess at start or end of the region. + if (! didRenderAnyRegion) + { + if (startInBuffer != 0) + buffer.clear (0, startInBuffer); + + const int endInBuffer = startInBuffer + numSamples; + const int remainingSamples = numSamples - endInBuffer; + + if (remainingSamples != 0) + buffer.clear (endInBuffer, remainingSamples); + + didRenderAnyRegion = true; + } + } + } + + if (! didRenderAnyRegion) + buffer.clear(); + + return success; +} diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.h b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.h new file mode 100644 index 0000000000..60b3bd472f --- /dev/null +++ b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginARAPlaybackRendererTemplate.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file was auto-generated! + + It contains the basic framework code for an ARA playback renderer implementation. + + ============================================================================== +*/ + +#pragma once + +#include + +//============================================================================== +/** +*/ +class %%araplaybackrenderer_class_name%% : public juce::ARAPlaybackRenderer +{ +public: + //============================================================================== + using juce::ARAPlaybackRenderer::ARAPlaybackRenderer; + + //============================================================================== + void prepareToPlay (double sampleRate, + int maximumSamplesPerBlock, + int numChannels, + juce::AudioProcessor::ProcessingPrecision, + AlwaysNonRealtime alwaysNonRealtime) override; + void releaseResources() override; + + //============================================================================== + bool processBlock (juce::AudioBuffer & buffer, + juce::AudioProcessor::Realtime realtime, + const juce::AudioPlayHead::CurrentPositionInfo& positionInfo) noexcept override; + +private: + //============================================================================== + double sampleRate = 44100.0; + int maximumSamplesPerBlock = 4096; + int numChannels = 1; + bool useBufferedAudioSourceReader = true; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%araplaybackrenderer_class_name%%) +}; diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.h b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.h index bfc4dc9536..ae40b224d3 100644 --- a/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.h +++ b/extras/Projucer/Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.h @@ -14,6 +14,9 @@ /** */ class %%filter_class_name%% : public juce::AudioProcessor + #if JucePlugin_Enable_ARA + , public juce::AudioProcessorARAExtension + #endif { public: //============================================================================== diff --git a/extras/Projucer/Source/Project/jucer_Project.cpp b/extras/Projucer/Source/Project/jucer_Project.cpp index 683cf99ecf..aa2c673b04 100644 --- a/extras/Projucer/Source/Project/jucer_Project.cpp +++ b/extras/Projucer/Source/Project/jucer_Project.cpp @@ -156,6 +156,9 @@ void Project::updateTitleDependencies() pluginAUExportPrefixValue.setDefault (build_tools::makeValidIdentifier (projectName, false, true, false) + "AU"); pluginAAXIdentifierValue. setDefault (getDefaultAAXIdentifierString()); pluginLV2URIValue. setDefault (getDefaultLV2URI()); + pluginARAFactoryIDValue. setDefault (getDefaultARAFactoryIDString()); + pluginARAArchiveIDValue. setDefault (getDefaultARADocumentArchiveID()); + pluginARACompatibleArchiveIDsValue.setDefault (getDefaultARACompatibleArchiveIDs()); } String Project::getDocumentTitle() @@ -166,7 +169,10 @@ String Project::getDocumentTitle() void Project::updateCompanyNameDependencies() { bundleIdentifierValue.setDefault (getDefaultBundleIdentifierString()); + companyWebsiteValue.setDefault (getDefaultCompanyWebsiteString()); pluginAAXIdentifierValue.setDefault (getDefaultAAXIdentifierString()); + pluginARAFactoryIDValue.setDefault (getDefaultARAFactoryIDString()); + pluginARAArchiveIDValue.setDefault (getDefaultARADocumentArchiveID()); pluginManufacturerValue.setDefault (getDefaultPluginManufacturerString()); updateLicenseWarning(); @@ -273,7 +279,7 @@ void Project::initialiseProjectValues() companyNameValue.referTo (projectRoot, Ids::companyName, getUndoManager()); companyCopyrightValue.referTo (projectRoot, Ids::companyCopyright, getUndoManager()); - companyWebsiteValue.referTo (projectRoot, Ids::companyWebsite, getUndoManager()); + companyWebsiteValue.referTo (projectRoot, Ids::companyWebsite, getUndoManager(), getDefaultCompanyWebsiteString()); companyEmailValue.referTo (projectRoot, Ids::companyEmail, getUndoManager()); projectTypeValue.referTo (projectRoot, Ids::projectType, getUndoManager(), build_tools::ProjectType_GUIApp::getTypeName()); @@ -329,6 +335,8 @@ void Project::initialiseAudioPluginValues() pluginCodeValue.referTo (projectRoot, Ids::pluginCode, getUndoManager(), makeValid4CC (getProjectUIDString() + getProjectUIDString())); pluginChannelConfigsValue.referTo (projectRoot, Ids::pluginChannelConfigs, getUndoManager()); pluginAAXIdentifierValue.referTo (projectRoot, Ids::aaxIdentifier, getUndoManager(), getDefaultAAXIdentifierString()); + pluginARAFactoryIDValue.referTo (projectRoot, Ids::araFactoryID, getUndoManager(), getDefaultARAFactoryIDString()); + pluginARAArchiveIDValue.referTo (projectRoot, Ids::araDocumentArchiveID, getUndoManager(), getDefaultARADocumentArchiveID()); pluginAUExportPrefixValue.referTo (projectRoot, Ids::pluginAUExportPrefix, getUndoManager(), build_tools::makeValidIdentifier (getProjectNameString(), false, true, false) + "AU"); @@ -338,6 +346,11 @@ void Project::initialiseAudioPluginValues() pluginVST3CategoryValue.referTo (projectRoot, Ids::pluginVST3Category, getUndoManager(), getDefaultVST3Categories(), ","); pluginAAXCategoryValue.referTo (projectRoot, Ids::pluginAAXCategory, getUndoManager(), getDefaultAAXCategories(), ","); + pluginEnableARA.referTo (projectRoot, Ids::enableARA, getUndoManager(), shouldEnableARA(), ","); + pluginARAAnalyzableContentValue.referTo (projectRoot, Ids::pluginARAAnalyzableContent, getUndoManager(), getDefaultARAContentTypes(), ","); + pluginARATransformFlagsValue.referTo (projectRoot, Ids::pluginARATransformFlags, getUndoManager(), getDefaultARATransformationFlags(), ","); + pluginARACompatibleArchiveIDsValue.referTo (projectRoot, Ids::araCompatibleArchiveIDs, getUndoManager(), getDefaultARACompatibleArchiveIDs()); + pluginVSTNumMidiInputsValue.referTo (projectRoot, Ids::pluginVSTNumMidiInputs, getUndoManager(), 16); pluginVSTNumMidiOutputsValue.referTo (projectRoot, Ids::pluginVSTNumMidiOutputs, getUndoManager(), 16); @@ -504,6 +517,24 @@ void Project::updatePluginCategories() pluginVSTCategoryValue.resetToDefault(); } + { + const auto araAnalyzableContent = projectRoot.getProperty (Ids::pluginARAAnalyzableContent, {}).toString(); + + if (getAllARAContentTypeVars().contains (araAnalyzableContent)) + pluginARAAnalyzableContentValue = araAnalyzableContent; + else if (getAllARAContentTypeStrings().contains (araAnalyzableContent)) + pluginARAAnalyzableContentValue = Array (getAllARAContentTypeVars()[getAllARAContentTypeStrings().indexOf (araAnalyzableContent)]); + } + + { + const auto araTransformationFlags = projectRoot.getProperty (Ids::pluginARATransformFlags, {}).toString(); + + if (getAllARATransformationFlagVars().contains (araTransformationFlags)) + pluginARATransformFlagsValue = araTransformationFlags; + else if (getAllARATransformationFlagStrings().contains (araTransformationFlags)) + pluginARATransformFlagsValue = Array (getAllARATransformationFlagVars()[getAllARATransformationFlagStrings().indexOf (araTransformationFlags)]); + } + { auto auMainType = projectRoot.getProperty (Ids::pluginAUMainType, {}).toString(); @@ -1081,6 +1112,9 @@ void Project::valueTreePropertyChanged (ValueTree& tree, const Identifier& prope pluginVSTCategoryValue.setDefault (getDefaultVSTCategories()); pluginVST3CategoryValue.setDefault (getDefaultVST3Categories()); pluginAAXCategoryValue.setDefault (getDefaultAAXCategories()); + pluginEnableARA.setDefault (getDefaultEnableARA()); + pluginARAAnalyzableContentValue.setDefault (getDefaultARAContentTypes()); + pluginARATransformFlagsValue.setDefault (getDefaultARATransformationFlags()); if (shouldWriteLegacyPluginCharacteristicsSettings) writeLegacyPluginCharacteristicsSettings(); @@ -1427,14 +1461,23 @@ void Project::createPropertyEditors (PropertyListBuilder& props) void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) { - props.add (new MultiChoicePropertyComponent (pluginFormatsValue, "Plugin Formats", - { "VST3", "AU", "AUv3", "AAX", "Standalone", "LV2", "Unity", "Enable IAA", "VST (Legacy)" }, - { Ids::buildVST3.toString(), Ids::buildAU.toString(), Ids::buildAUv3.toString(), - Ids::buildAAX.toString(), Ids::buildStandalone.toString(), - Ids::buildLV2.toString(), Ids::buildUnity.toString(), Ids::enableIAA.toString(), Ids::buildVST.toString() }), - "Plugin formats to build. If you have selected \"VST (Legacy)\" then you will need to ensure that you have a VST2 SDK " - "in your header search paths. The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK " - "or JUCE version 5.3.2. You also need a VST2 license from Steinberg to distribute VST2 plug-ins."); + { + StringArray pluginFormatChoices { "VST3", "AU", "AUv3", "AAX", "Standalone", "LV2", "Unity", "Enable IAA", "VST (Legacy)" }; + Array pluginFormatChoiceValues { Ids::buildVST3.toString(), Ids::buildAU.toString(), Ids::buildAUv3.toString(), + Ids::buildAAX.toString(), Ids::buildStandalone.toString(), + Ids::buildLV2.toString(), Ids::buildUnity.toString(), Ids::enableIAA.toString(), Ids::buildVST.toString() }; + if (! getProjectType().isARAAudioPlugin()) + { + pluginFormatChoices.add ("Enable ARA"); + pluginFormatChoiceValues.add (Ids::enableARA.toString()); + } + props.add (new MultiChoicePropertyComponent (pluginFormatsValue, "Plugin Formats", pluginFormatChoices, pluginFormatChoiceValues), + "Plugin formats to build. If you have selected \"VST (Legacy)\" then you will need to ensure that you have a VST2 SDK " + "in your header search paths. The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK " + "or JUCE version 5.3.2. You also need a VST2 license from Steinberg to distribute VST2 plug-ins. If you enable ARA you " + "will have to obtain the ARA SDK by recursively cloning https://github.com/Celemony/ARA_SDK and checking out the tag " + "releases/2.1.0."); + } props.add (new MultiChoicePropertyComponent (pluginCharacteristicsValue, "Plugin Characteristics", { "Plugin is a Synth", "Plugin MIDI Input", "Plugin MIDI Output", "MIDI Effect Plugin", "Plugin Editor Requires Keyboard Focus", "Disable AAX Bypass", "Disable AAX Multi-Mono" }, @@ -1515,6 +1558,25 @@ void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) "This acts as a unique identifier for this plugin. " "If you make any incompatible changes to your plugin (remove parameters, reorder parameters, change preset format etc.) " "you MUST change this value. LV2 hosts will assume that any plugins with the same URI are interchangeable."); + + if (shouldEnableARA()) + { + props.add (new MultiChoicePropertyComponent (pluginARAAnalyzableContentValue, "Plugin ARA Analyzeable Content Types", getAllARAContentTypeStrings(), getAllARAContentTypeVars()), + "ARA Analyzeable Content Types."); + + props.add (new MultiChoicePropertyComponent (pluginARATransformFlagsValue, "Plugin ARA Transformation Flags", getAllARATransformationFlagStrings(), getAllARATransformationFlagVars()), + "ARA Transformation Flags."); + + props.add (new TextPropertyComponent (pluginARAFactoryIDValue, "Plugin ARA Factory ID", 256, false), + "ARA Factory ID."); + + props.add (new TextPropertyComponent (pluginARAArchiveIDValue, "Plugin ARA Document Archive ID", 256, false), + "ARA Document Archive ID."); + + props.add (new TextPropertyComponent (pluginARACompatibleArchiveIDsValue, "Plugin ARA Compatible Document Archive IDs", 1024, true), + "List of compatible ARA Document Archive IDs - one per line"); + + } } //============================================================================== @@ -2110,11 +2172,31 @@ String Project::getDefaultBundleIdentifierString() const + "." + build_tools::makeValidIdentifier (getProjectNameString(), false, true, false); } +String Project::getDefaultCompanyWebsiteString() const +{ + return "www." + build_tools::makeValidIdentifier (getCompanyNameOrDefault (getCompanyNameString()), false, true, false) + ".com"; +} + String Project::getDefaultPluginManufacturerString() const { return getCompanyNameOrDefault (getCompanyNameString()); } +String Project::getDefaultARAFactoryIDString() const +{ + return getDefaultBundleIdentifierString() + ".factory"; +} + +String Project::getDefaultARADocumentArchiveID() const +{ + return getDefaultBundleIdentifierString() + ".aradocumentarchive." + getVersionString(); +} + +String Project::getDefaultARACompatibleArchiveIDs() const +{ + return String(); +} + String Project::getAUMainTypeString() const noexcept { auto v = pluginAUMainTypeValue.get(); @@ -2222,6 +2304,32 @@ String Project::getIAAPluginName() const return s; } +int Project::getARAContentTypes() const noexcept +{ + int res = 0; + + if (auto* arr = pluginARAAnalyzableContentValue.get().getArray()) + { + for (auto c : *arr) + res |= (int) c; + } + + return res; +} + +int Project::getARATransformationFlags() const noexcept +{ + int res = 0; + + if (auto* arr = pluginARATransformFlagsValue.get().getArray()) + { + for (auto c : *arr) + res |= (int) c; + } + + return res; +} + //============================================================================== bool Project::isAUPluginHost() { @@ -2243,6 +2351,16 @@ bool Project::isLV2PluginHost() return getEnabledModules().isModuleEnabled ("juce_audio_processors") && isConfigFlagEnabled ("JUCE_PLUGINHOST_LV2", false); } +bool Project::isARAPluginHost() +{ + return (isVST3PluginHost() || isAUPluginHost()) && isConfigFlagEnabled ("JUCE_PLUGINHOST_ARA", false); +} + +void Project::disableStandaloneForARAPlugIn() +{ + pluginFormatsValue.referTo (projectRoot, Ids::pluginFormats, getUndoManager(), Array (Ids::buildVST3.toString(), Ids::buildAU.toString()), ","); +} + //============================================================================== StringArray Project::getAllAUMainTypeStrings() noexcept { @@ -2332,6 +2450,67 @@ Array Project::getDefaultAAXCategories() const noexcept return getAllAAXCategoryVars()[getAllAAXCategoryStrings().indexOf ("AAX_ePlugInCategory_None")]; } +bool Project::getDefaultEnableARA() const noexcept +{ + return false; +} + +StringArray Project::getAllARAContentTypeStrings() noexcept +{ + static StringArray araContentTypes { "Notes", + "Tempo Entries", + "Bar Signatures", + "Static Tuning", + "Dynamic Tuning Offsets", + "Key Signatures", + "Sheet Chords" }; + return araContentTypes; +} + +Array Project::getAllARAContentTypeVars() noexcept +{ + static Array araContentVars { + /*kARAContentTypeNotes =*/ 1 << 0, + /*kARAContentTypeTempoEntries =*/ 1 << 1, + /*kARAContentTypeBarSignatures =*/ 1 << 2, + /*kARAContentTypeStaticTuning =*/ 1 << 3, + /*kARAContentTypeDynamicTuningOffsets =*/ 1 << 4, + /*kARAContentTypeKeySignatures =*/ 1 << 5, + /*kARAContentTypeSheetChords =*/ 1 << 6, + }; + return araContentVars; +} + +Array Project::getDefaultARAContentTypes() const noexcept +{ + return {}; +} + +StringArray Project::getAllARATransformationFlagStrings() noexcept +{ + static StringArray araTransformationFlags { "Time Stretch", + "Time Stretch (reflecting tempo)", + "Content Based Fades At Tail", + "Content Based Fades At Head" }; + return araTransformationFlags; +} + +Array Project::getAllARATransformationFlagVars() noexcept +{ + static Array araContentVars { + /*kARAPlaybackTransformationTimestretch =*/ 1 << 0, + /*kARAPlaybackTransformationTimestretchReflectingTempo =*/ 1 << 1, + /*kARAPlaybackTransformationContentBasedFadesAtTail =*/ 1 << 2, + /*kARAPlaybackTransformationContentBasedFadesAtHead =*/ 1 << 3 + }; + return araContentVars; +} + +Array Project::getDefaultARATransformationFlags() const noexcept +{ + return {}; +} + //============================================================================== EnabledModulesList& Project::getEnabledModules() { @@ -2587,6 +2766,7 @@ StringPairArray Project::getAudioPluginFlags() const flags.set ("JucePlugin_Build_Unity", boolToString (shouldBuildUnityPlugin())); flags.set ("JucePlugin_Build_LV2", boolToString (shouldBuildLV2())); flags.set ("JucePlugin_Enable_IAA", boolToString (shouldEnableIAA())); + flags.set ("JucePlugin_Enable_ARA", boolToString (shouldEnableARA())); flags.set ("JucePlugin_Name", toStringLiteral (getPluginNameString())); flags.set ("JucePlugin_Desc", toStringLiteral (getPluginDescriptionString())); flags.set ("JucePlugin_Manufacturer", toStringLiteral (getPluginManufacturerString())); @@ -2622,6 +2802,11 @@ StringPairArray Project::getAudioPluginFlags() const flags.set ("JucePlugin_IAAName", toStringLiteral (getIAAPluginName())); flags.set ("JucePlugin_VSTNumMidiInputs", getVSTNumMIDIInputsString()); flags.set ("JucePlugin_VSTNumMidiOutputs", getVSTNumMIDIOutputsString()); + flags.set ("JucePlugin_ARAContentTypes", String (getARAContentTypes())); + flags.set ("JucePlugin_ARATransformationFlags", String (getARATransformationFlags())); + flags.set ("JucePlugin_ARAFactoryID", toStringLiteral(getARAFactoryIDString())); + flags.set ("JucePlugin_ARADocumentArchiveID", toStringLiteral(getARADocumentArchiveIDString())); + flags.set ("JucePlugin_ARACompatibleArchiveIDs", toStringLiteral(getARACompatibleArchiveIDStrings())); { String plugInChannelConfig = getPluginChannelConfigsString(); diff --git a/extras/Projucer/Source/Project/jucer_Project.h b/extras/Projucer/Source/Project/jucer_Project.h index 63fac30c1c..110b845cb9 100644 --- a/extras/Projucer/Source/Project/jucer_Project.h +++ b/extras/Projucer/Source/Project/jucer_Project.h @@ -192,9 +192,13 @@ public: String getBundleIdentifierString() const { return bundleIdentifierValue.get(); } String getDefaultBundleIdentifierString() const; + String getDefaultCompanyWebsiteString() const; String getDefaultAAXIdentifierString() const { return getDefaultBundleIdentifierString(); } String getDefaultPluginManufacturerString() const; String getDefaultLV2URI() const { return getCompanyWebsiteString() + "/plugins/" + build_tools::makeValidIdentifier (getProjectNameString(), false, true, false); } + String getDefaultARAFactoryIDString() const; + String getDefaultARADocumentArchiveID() const; + String getDefaultARACompatibleArchiveIDs() const; String getCompanyNameString() const { return companyNameValue.get(); } String getCompanyCopyrightString() const { return companyCopyrightValue.get(); } @@ -241,7 +245,11 @@ public: String getPluginCodeString() const { return pluginCodeValue.get(); } String getPluginChannelConfigsString() const { return pluginChannelConfigsValue.get(); } String getAAXIdentifierString() const { return pluginAAXIdentifierValue.get(); } + String getARAFactoryIDString() const { return pluginARAFactoryIDValue.get(); } + String getARADocumentArchiveIDString() const { return pluginARAArchiveIDValue.get(); } + String getARACompatibleArchiveIDStrings() const { return pluginARACompatibleArchiveIDsValue.get(); } String getPluginAUExportPrefixString() const { return pluginAUExportPrefixValue.get(); } + String getPluginAUMainTypeString() const { return pluginAUMainTypeValue.get(); } String getVSTNumMIDIInputsString() const { return pluginVSTNumMidiInputsValue.get(); } String getVSTNumMIDIOutputsString() const { return pluginVSTNumMidiOutputsValue.get(); } @@ -269,6 +277,7 @@ public: bool shouldBuildUnityPlugin() const { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildUnity); } bool shouldBuildLV2() const { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildLV2); } bool shouldEnableIAA() const { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::enableIAA); } + bool shouldEnableARA() const { return (isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::enableARA)) || getProjectType().isARAAudioPlugin(); } bool isPluginSynth() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginIsSynth); } bool pluginWantsMidiInput() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginWantsMidiIn); } @@ -278,6 +287,8 @@ public: bool isPluginAAXBypassDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableBypass); } bool isPluginAAXMultiMonoDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableMultiMono); } + void disableStandaloneForARAPlugIn(); + static StringArray getAllAUMainTypeStrings() noexcept; static Array getAllAUMainTypeVars() noexcept; Array getDefaultAUMainTypes() const noexcept; @@ -292,11 +303,22 @@ public: static Array getAllAAXCategoryVars() noexcept; Array getDefaultAAXCategories() const noexcept; + bool getDefaultEnableARA() const noexcept; + static StringArray getAllARAContentTypeStrings() noexcept; + static Array getAllARAContentTypeVars() noexcept; + Array getDefaultARAContentTypes() const noexcept; + + static StringArray getAllARATransformationFlagStrings() noexcept; + static Array getAllARATransformationFlagVars() noexcept; + Array getDefaultARATransformationFlags() const noexcept; + String getAUMainTypeString() const noexcept; bool isAUSandBoxSafe() const noexcept; String getVSTCategoryString() const noexcept; String getVST3CategoryString() const noexcept; int getAAXCategory() const noexcept; + int getARAContentTypes() const noexcept; + int getARATransformationFlags() const noexcept; String getIAATypeCode() const; String getIAAPluginName() const; @@ -317,6 +339,7 @@ public: bool isVSTPluginHost(); bool isVST3PluginHost(); bool isLV2PluginHost(); + bool isARAPluginHost(); //============================================================================== bool shouldBuildTargetType (build_tools::ProjectType::Target::Type targetType) const noexcept; @@ -548,6 +571,7 @@ private: ValueTreePropertyWithDefault pluginFormatsValue, pluginNameValue, pluginDescriptionValue, pluginManufacturerValue, pluginManufacturerCodeValue, pluginCodeValue, pluginChannelConfigsValue, pluginCharacteristicsValue, pluginAUExportPrefixValue, pluginAAXIdentifierValue, pluginAUMainTypeValue, pluginAUSandboxSafeValue, pluginVSTCategoryValue, pluginVST3CategoryValue, pluginAAXCategoryValue, + pluginEnableARA, pluginARAAnalyzableContentValue, pluginARAFactoryIDValue, pluginARAArchiveIDValue, pluginARACompatibleArchiveIDsValue, pluginARATransformFlagsValue, pluginVSTNumMidiInputsValue, pluginVSTNumMidiOutputsValue, pluginLV2URIValue; //============================================================================== diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h index 35949f2194..3a299fe535 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h @@ -131,6 +131,9 @@ public: aaxPathValueWrapper.init ({ settings, Ids::aaxFolder, nullptr }, getAppSettings().getStoredPath (Ids::aaxPath, TargetOS::windows), TargetOS::windows); + + araPathValueWrapper.init ({ settings, Ids::araFolder, nullptr }, + getAppSettings().getStoredPath (Ids::araPath, TargetOS::windows), TargetOS::windows); } //============================================================================== diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h index 712452925e..b219d7a7b3 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h @@ -773,6 +773,9 @@ public: aaxPathValueWrapper.init ({ settings, Ids::aaxFolder, nullptr }, getAppSettings().getStoredPath (Ids::aaxPath, TargetOS::osx), TargetOS::osx); + + araPathValueWrapper.init ({ settings, Ids::araFolder, nullptr }, + getAppSettings().getStoredPath (Ids::araPath, TargetOS::osx), TargetOS::osx); } protected: @@ -1897,6 +1900,7 @@ public: options.isAuSandboxSafe = owner.project.isAUSandBoxSafe(); options.isPluginSynth = owner.project.isPluginSynth(); options.suppressResourceUsage = owner.getSuppressPlistResourceUsage(); + options.isPluginARAEffect = owner.project.shouldEnableARA(); options.write (infoPlistFile); } diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp index 251040d54b..b87ecb4b36 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp @@ -273,6 +273,13 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) "If you're building an AAX plug-in, this must be the folder containing the AAX SDK. This can be an absolute path, or a path relative to the Projucer project file."); } + if (project.shouldEnableARA() || project.isARAPluginHost()) + { + props.add (new FilePathPropertyComponent (araPathValueWrapper.getWrappedValueTreePropertyWithDefault(), "ARA SDK Folder", true, + getTargetOSForExporter() == TargetOS::getThisOS(), "*", project.getProjectFolder()), + "If you're building an ARA enabled plug-in, this must be the folder containing the ARA SDK. This can be an absolute path, or a path relative to the Projucer project file."); + } + props.add (new TextPropertyComponent (extraPPDefsValue, "Extra Preprocessor Definitions", 32768, true), "Extra preprocessor definitions. Use the form \"NAME1=value NAME2=value\", using whitespace, commas, " "or new-lines to separate the items - to include a space or comma in a definition, precede it with a backslash."); @@ -335,6 +342,8 @@ void ProjectExporter::addSettingsForProjectType (const build_tools::ProjectType& { addExtraIncludePathsIfPluginOrHost(); + addARAPathsIfPluginOrHost(); + if (type.isAudioPlugin()) addCommonAudioPluginSettings(); @@ -385,6 +394,12 @@ void ProjectExporter::addExtraIncludePathsIfPluginOrHost() } } +void ProjectExporter::addARAPathsIfPluginOrHost() +{ + if (project.shouldEnableARA() || project.isARAPluginHost()) + addARAFoldersToPath(); +} + void ProjectExporter::addCommonAudioPluginSettings() { if (shouldBuildTargetType (build_tools::ProjectType::Target::AAXPlugIn)) @@ -420,6 +435,14 @@ void ProjectExporter::addAAXFoldersToPath() } } +void ProjectExporter::addARAFoldersToPath() +{ + const auto araFolder = getARAPathString(); + + if (araFolder.isNotEmpty()) + addToExtraSearchPaths (build_tools::RelativePath (araFolder, build_tools::RelativePath::projectFolder)); +} + //============================================================================== StringPairArray ProjectExporter::getAllPreprocessorDefs (const BuildConfiguration& config, const build_tools::ProjectType::Target::Type targetType) const { @@ -468,6 +491,10 @@ void ProjectExporter::addTargetSpecificPreprocessorDefs (StringPairArray& defs, for (auto& flag : targetFlags) defs.set (flag.first, (targetType == flag.second ? "1" : "0")); } + if (project.shouldEnableARA()) + { + defs.set ("JucePlugin_Enable_ARA", "1"); + } } void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h index 9cd34c33b0..530a457fdf 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h @@ -144,6 +144,7 @@ public: String getVSTLegacyPathString() const { return vstLegacyPathValueWrapper.getCurrentValue(); } String getAAXPathString() const { return aaxPathValueWrapper.getCurrentValue(); } + String getARAPathString() const { return araPathValueWrapper.getCurrentValue(); } // NB: this is the path to the parent "modules" folder that contains the named module, not the // module folder itself. @@ -405,7 +406,7 @@ protected: const File projectFolder; //============================================================================== - ValueTreePropertyWithDefaultWrapper vstLegacyPathValueWrapper, aaxPathValueWrapper; + ValueTreePropertyWithDefaultWrapper vstLegacyPathValueWrapper, aaxPathValueWrapper, araPathValueWrapper; ValueTreePropertyWithDefault targetLocationValue, extraCompilerFlagsValue, extraLinkerFlagsValue, externalLibrariesValue, userNotesValue, gnuExtensionsValue, bigIconValue, smallIconValue, extraPPDefsValue; @@ -467,10 +468,12 @@ private: void createIconProperties (PropertyListBuilder&); void addExtraIncludePathsIfPluginOrHost(); + void addARAPathsIfPluginOrHost(); void addCommonAudioPluginSettings(); void addLegacyVSTFolderToPathIfSpecified(); build_tools::RelativePath getInternalVST3SDKPath(); void addAAXFoldersToPath(); + void addARAFoldersToPath(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectExporter) }; diff --git a/extras/Projucer/Source/Settings/jucer_StoredSettings.cpp b/extras/Projucer/Source/Settings/jucer_StoredSettings.cpp index 5ad34e4137..59d6e20ec7 100644 --- a/extras/Projucer/Source/Settings/jucer_StoredSettings.cpp +++ b/extras/Projucer/Source/Settings/jucer_StoredSettings.cpp @@ -276,6 +276,10 @@ static bool isGlobalPathValid (const File& relativeTo, const Identifier& key, co { fileToCheckFor = "Interfaces/AAX_Exports.cpp"; } + else if (key == Ids::araPath) + { + fileToCheckFor = "ARA_API/ARAInterface.h"; + } else if (key == Ids::androidSDKPath) { #if JUCE_WINDOWS @@ -367,6 +371,12 @@ static String getFallbackPathForOS (const Identifier& key, DependencyPathOS os) else if (os == TargetOS::osx) return "~/SDKs/AAX"; else return {}; // no AAX on this OS! } + else if (key == Ids::araPath) + { + if (os == TargetOS::windows) return "C:\\SDKs\\ARA_SDK"; + else if (os == TargetOS::osx) return "~/SDKs/ARA_SDK"; + else return {}; + } else if (key == Ids::androidSDKPath) { if (os == TargetOS::windows) return "${user.home}\\AppData\\Local\\Android\\Sdk"; diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h index 727ddfe69d..f963f8b733 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h @@ -68,6 +68,7 @@ namespace Ids DECLARE_ID (auFolder); DECLARE_ID (vstLegacyPath); DECLARE_ID (aaxPath); + DECLARE_ID (araPath); DECLARE_ID (flags); DECLARE_ID (line); DECLARE_ID (index); @@ -154,7 +155,11 @@ namespace Ids DECLARE_ID (enableIncrementalLinking); DECLARE_ID (bundleIdentifier); DECLARE_ID (aaxIdentifier); + DECLARE_ID (araFactoryID); + DECLARE_ID (araDocumentArchiveID); + DECLARE_ID (araCompatibleArchiveIDs); DECLARE_ID (aaxFolder); + DECLARE_ID (araFolder); DECLARE_ID (compile); DECLARE_ID (noWarnings); DECLARE_ID (skipPCH); @@ -330,6 +335,7 @@ namespace Ids DECLARE_ID (buildUnity); DECLARE_ID (buildLV2); DECLARE_ID (enableIAA); + DECLARE_ID (enableARA); DECLARE_ID (pluginName); DECLARE_ID (pluginDesc); DECLARE_ID (pluginManufacturer); @@ -352,6 +358,8 @@ namespace Ids DECLARE_ID (pluginAAXCategory); DECLARE_ID (pluginAAXDisableBypass); DECLARE_ID (pluginAAXDisableMultiMono); + DECLARE_ID (pluginARAAnalyzableContent); + DECLARE_ID (pluginARATransformFlags); DECLARE_ID (pluginVSTNumMidiInputs); DECLARE_ID (pluginVSTNumMidiOutputs); DECLARE_ID (suppressPlistResourceUsage);