From dd5ced96c1542cb32f5e1b306196702760394418 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 20 Aug 2025 19:33:06 +0100 Subject: [PATCH] VSTPluginFormat: Extract headless plugin format type --- .../juce_audio_plugin_client_VST2.cpp | 3 +- .../format_types/juce_VSTPluginFormat.cpp | 3126 +---------------- .../format_types/juce_VSTPluginFormat.h | 93 +- .../juce_audio_processors.h | 1 - .../format_types/juce_VSTCommon.h | 2 + .../format_types/juce_VSTMidiEventList.h | 5 +- .../juce_VSTPluginFormatHeadless.cpp | 278 ++ .../juce_VSTPluginFormatHeadless.h | 140 + .../format_types/juce_VSTPluginFormatImpl.h | 2816 +++++++++++++++ .../juce_audio_processors_headless.cpp | 1 + .../juce_audio_processors_headless.h | 1 + 11 files changed, 3330 insertions(+), 3136 deletions(-) rename modules/{juce_audio_processors => juce_audio_processors_headless}/format_types/juce_VSTCommon.h (97%) rename modules/{juce_audio_processors => juce_audio_processors_headless}/format_types/juce_VSTMidiEventList.h (95%) create mode 100644 modules/juce_audio_processors_headless/format_types/juce_VSTPluginFormatHeadless.cpp create mode 100644 modules/juce_audio_processors_headless/format_types/juce_VSTPluginFormatHeadless.h create mode 100644 modules/juce_audio_processors_headless/format_types/juce_VSTPluginFormatImpl.h diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp index 0c8632d7ae..d45d14c94e 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp @@ -119,7 +119,8 @@ using namespace juce; #include #include -#include +#include +#include #ifdef JUCE_MSVC #pragma pack (pop) diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index c972359e43..11e921ed4b 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -34,2757 +34,32 @@ #if JUCE_PLUGINHOST_VST -#include +#include -//============================================================================== -#undef PRAGMA_ALIGN_SUPPORTED - - -#if ! JUCE_MSVC - #define __cdecl -#endif - -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant") -JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996) - -#define VST_FORCE_DEPRECATED 0 -#define JUCE_VSTINTERFACE_H_INCLUDED 1 - -namespace Vst2 -{ -struct AEffect; - -// If the following files cannot be found then you are probably trying to host -// VST2 plug-ins. To do this you must have a VST2 SDK in your header search -// paths or use the "VST (Legacy) SDK Folder" field in the Projucer. The VST2 -// SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 -// SDK or JUCE version 5.3.2. -#include -#include -} - -#include "juce_VSTCommon.h" - -JUCE_END_IGNORE_WARNINGS_MSVC -JUCE_END_IGNORE_WARNINGS_GCC_LIKE - -JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4355) -JUCE_BEGIN_IGNORE_DEPRECATION_WARNINGS - -#include "juce_VSTMidiEventList.h" - -#if ! JUCE_WINDOWS - static void _fpreset() {} - static void _clearfp() {} -#endif - -#ifndef JUCE_VST_WRAPPER_LOAD_CUSTOM_MAIN - #define JUCE_VST_WRAPPER_LOAD_CUSTOM_MAIN -#endif - -#ifndef JUCE_VST_WRAPPER_INVOKE_MAIN -#define JUCE_VST_WRAPPER_INVOKE_MAIN effect = module->moduleMain (audioMaster); -#endif - -#ifndef JUCE_VST_FALLBACK_HOST_NAME - #define JUCE_VST_FALLBACK_HOST_NAME "Juce VST Host" -#endif - -//============================================================================== namespace juce { -//============================================================================== -namespace -{ - const int fxbVersionNum = 1; - - struct fxProgram - { - int32 chunkMagic; // 'CcnK' - int32 byteSize; // of this chunk, excl. magic + byteSize - int32 fxMagic; // 'FxCk' - int32 version; - int32 fxID; // fx unique id - int32 fxVersion; - int32 numParams; - char prgName[28]; - float params[1]; // variable no. of parameters - }; - - struct fxSet - { - int32 chunkMagic; // 'CcnK' - int32 byteSize; // of this chunk, excl. magic + byteSize - int32 fxMagic; // 'FxBk' - int32 version; - int32 fxID; // fx unique id - int32 fxVersion; - int32 numPrograms; - char future[128]; - fxProgram programs[1]; // variable no. of programs - }; - - struct fxChunkSet - { - int32 chunkMagic; // 'CcnK' - int32 byteSize; // of this chunk, excl. magic + byteSize - int32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh' - int32 version; - int32 fxID; // fx unique id - int32 fxVersion; - int32 numPrograms; - char future[128]; - int32 chunkSize; - char chunk[8]; // variable - }; - - struct fxProgramSet - { - int32 chunkMagic; // 'CcnK' - int32 byteSize; // of this chunk, excl. magic + byteSize - int32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh' - int32 version; - int32 fxID; // fx unique id - int32 fxVersion; - int32 numPrograms; - char name[28]; - int32 chunkSize; - char chunk[8]; // variable - }; - - // Compares a magic value in either endianness. - static bool compareMagic (int32 magic, const char* name) noexcept - { - return magic == (int32) ByteOrder::littleEndianInt (name) - || magic == (int32) ByteOrder::bigEndianInt (name); - } - - static int32 fxbName (const char* name) noexcept { return (int32) ByteOrder::littleEndianInt (name); } - static int32 fxbSwap (int32 x) noexcept { return (int32) ByteOrder::swapIfLittleEndian ((uint32) x); } - - static float fxbSwapFloat (const float x) noexcept - { - #ifdef JUCE_LITTLE_ENDIAN - union { uint32 asInt; float asFloat; } n; - n.asFloat = x; - n.asInt = ByteOrder::swap (n.asInt); - return n.asFloat; - #else - return x; - #endif - } -} - -//============================================================================== -namespace -{ - static double getVSTHostTimeNanoseconds() noexcept - { - #if JUCE_WINDOWS - return timeGetTime() * 1000000.0; - #elif JUCE_LINUX || JUCE_BSD || JUCE_IOS || JUCE_ANDROID - timeval micro; - gettimeofday (µ, nullptr); - return (double) micro.tv_usec * 1000.0; - #elif JUCE_MAC - UnsignedWide micro; - Microseconds (µ); - return micro.lo * 1000.0; - #endif - } - - static int shellUIDToCreate = 0; - static int insideVSTCallback = 0; - - struct IdleCallRecursionPreventer - { - IdleCallRecursionPreventer() : isMessageThread (MessageManager::getInstance()->isThisTheMessageThread()) - { - if (isMessageThread) - ++insideVSTCallback; - } - - ~IdleCallRecursionPreventer() - { - if (isMessageThread) - --insideVSTCallback; - } - - const bool isMessageThread; - JUCE_DECLARE_NON_COPYABLE (IdleCallRecursionPreventer) - }; - - #if JUCE_MAC - static bool makeFSRefFromPath (FSRef* destFSRef, const String& path) - { - return FSPathMakeRef (reinterpret_cast (path.toRawUTF8()), destFSRef, nullptr) == noErr; - } - #endif -} - -//============================================================================== -using MainCall = Vst2::AEffect* (VSTCALLBACK*) (Vst2::audioMasterCallback); - -//============================================================================== -// Change this to disable logging of various VST activities -#ifndef VST_LOGGING - #define VST_LOGGING 1 -#endif - -#if VST_LOGGING - #define JUCE_VST_LOG(a) Logger::writeToLog(a); -#else - #define JUCE_VST_LOG(a) -#endif - -//============================================================================== #if JUCE_LINUX || JUCE_BSD -namespace +using EventProcPtr = void (*)(XEvent*); + +static Window getChildWindow (Window windowToCheck) { - using EventProcPtr = void (*)(XEvent*); + Window rootWindow, parentWindow; + Window* childWindows; + unsigned int numChildren = 0; - Window getChildWindow (Window windowToCheck) - { - Window rootWindow, parentWindow; - Window* childWindows; - unsigned int numChildren = 0; + X11Symbols::getInstance()->xQueryTree (XWindowSystem::getInstance()->getDisplay(), + windowToCheck, &rootWindow, &parentWindow, &childWindows, &numChildren); - X11Symbols::getInstance()->xQueryTree (XWindowSystem::getInstance()->getDisplay(), - windowToCheck, &rootWindow, &parentWindow, &childWindows, &numChildren); + if (numChildren > 0) + return childWindows [0]; - if (numChildren > 0) - return childWindows [0]; - - return 0; - } + return 0; } #endif -//============================================================================== -class VSTXMLInfo -{ -public: - static VSTXMLInfo* createFor (const juce::XmlElement& xml) - { - if (xml.hasTagName ("VSTParametersStructure")) - return new VSTXMLInfo (xml); - - if (const auto* x = xml.getChildByName ("VSTParametersStructure")) - return new VSTXMLInfo (*x); - - return nullptr; - } - - struct Group; - - struct Base - { - Base() noexcept {} - virtual ~Base() {} - - Group* parent = nullptr; - }; - - struct Param final : public Base - { - int paramID; - juce::String expr, name, label; - juce::StringArray shortNames; - juce::String type; - int numberOfStates; - float defaultValue; - }; - - struct Group final : public Base - { - juce::String name; - juce::OwnedArray paramTree; - }; - - struct Range - { - Range() noexcept {} - Range (const juce::String& s) { set (s); } - - void set (const juce::String& s) - { - inclusiveLow = s.startsWithChar ('['); - inclusiveHigh = s.endsWithChar (']'); - - auto str = s.removeCharacters ("[]"); - - low = str.upToFirstOccurrenceOf (",", false, false).getFloatValue(); - high = str.fromLastOccurrenceOf (",", false, false).getFloatValue(); - } - - bool contains (float f) const noexcept - { - return (inclusiveLow ? (f >= low) : (f > low)) - && (inclusiveHigh ? (f <= high) : (f < high)); - } - - float low = 0; - float high = 0; - - bool inclusiveLow = false; - bool inclusiveHigh = false; - }; - - struct Entry - { - juce::String name; - Range range; - }; - - struct ValueType - { - juce::String name, label; - juce::OwnedArray entries; - }; - - struct Template - { - juce::String name; - juce::OwnedArray params; - }; - - const Param* getParamForID (const int paramID, const Group* const grp) const - { - for (auto item : (grp != nullptr ? grp->paramTree : paramTree)) - { - if (auto param = dynamic_cast (item)) - if (param->paramID == paramID) - return param; - - if (auto group = dynamic_cast (item)) - if (auto res = getParamForID (paramID, group)) - return res; - } - - return nullptr; - } - - const ValueType* getValueType (const juce::String& name) const - { - for (auto v : valueTypes) - if (v->name == name) - return v; - - return nullptr; - } - - juce::OwnedArray paramTree; - juce::OwnedArray valueTypes; - juce::OwnedArray