From f2b2fb281992584ca358e845d33c3c47d177cb27 Mon Sep 17 00:00:00 2001 From: tpoole Date: Thu, 12 Jan 2017 11:24:42 +0000 Subject: [PATCH] Fixed JUCE_VST3_CAN_REPLACE_VST2 behaviour --- .../VST/juce_VST_Wrapper.cpp | 27 +---- .../VST3/juce_VST3_Wrapper.cpp | 42 +------ .../utility/juce_PluginUtilities.cpp | 108 ++++++++++++++++++ 3 files changed, 116 insertions(+), 61 deletions(-) diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp index 6e03a72759..3616fde792 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp @@ -59,15 +59,6 @@ #include "../../juce_audio_processors/format_types/juce_VSTInterface.h" -#ifndef JUCE_VST3_CAN_REPLACE_VST2 - #define JUCE_VST3_CAN_REPLACE_VST2 1 -#endif - -#if JucePlugin_Build_VST3 && JUCE_VST3_CAN_REPLACE_VST2 - #include - namespace juce { extern Steinberg::FUID getJuceVST3ComponentIID(); } -#endif - #ifdef _MSC_VER #pragma warning (pop) #endif @@ -113,6 +104,8 @@ namespace juce #if JUCE_LINUX extern Display* display; #endif + + extern JUCE_API pointer_sized_int handleManufacturerSpecificVST2Opcode (int32, pointer_sized_int, void*, float); } @@ -1160,7 +1153,7 @@ public: case plugInOpcodeGetManufacturerProductName: return handleGetPlugInName (args); case plugInOpcodeGetManufacturerName: return handleGetManufacturerName (args); case plugInOpcodeGetManufacturerVersion: return handleGetManufacturerVersion (args); - case plugInOpcodeManufacturerSpecific: return handleManufacturerSpecific (args); + case plugInOpcodeManufacturerSpecific: return handleManufacturerSpecificVST2Opcode (args.index, args.value, args.ptr, args.opt); case plugInOpcodeCanPlugInDo: return handleCanPlugInDo (args); case plugInOpcodeGetTailSize: return handleGetTailSize (args); case plugInOpcodeKeyboardFocusRequired: return handleKeyboardFocusRequired (args); @@ -1884,20 +1877,6 @@ private: return convertHexVersionToDecimal (JucePlugin_VersionCode); } - pointer_sized_int handleManufacturerSpecific (VstOpCodeArguments args) - { - #if JucePlugin_Build_VST3 && JUCE_VST3_CAN_REPLACE_VST2 - if ((args.index == 'stCA' || args.index == 'stCa') && args.value == 'FUID' && args.ptr != nullptr) - { - memcpy (args.ptr, getJuceVST3ComponentIID(), 16); - return 1; - } - #else - ignoreUnused (args); - #endif - return 0; - } - pointer_sized_int handleCanPlugInDo (VstOpCodeArguments args) { char* text = (char*) args.ptr; diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index 2abd825fd9..f00f57b6ff 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -2250,11 +2250,6 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Component) }; -#if JucePlugin_Build_VST3 && JUCE_VST3_CAN_REPLACE_VST2 - Steinberg::FUID getJuceVST3ComponentIID(); - Steinberg::FUID getJuceVST3ComponentIID() { return JuceVST3Component::iid; } -#endif - const char* JuceVST3Component::kJucePrivateDataIdentifier = "JUCEPrivateData"; //============================================================================== @@ -2270,42 +2265,15 @@ DECLARE_CLASS_IID (JuceAudioProcessor, 0x0101ABAB, 0xABCDEF01, JucePlugin_Manufa DEF_CLASS_IID (JuceAudioProcessor) #if JUCE_VST3_CAN_REPLACE_VST2 - // NB: Nasty old-fashioned code in here because it's copied from the Steinberg example code. - static FUID getFUIDForVST2ID (bool forControllerUID) + FUID getFUIDForVST2ID (bool forControllerUID) { - char uidString[33]; - - const int vstfxid = (('V' << 16) | ('S' << 8) | (forControllerUID ? 'E' : 'T')); - char vstfxidStr[7] = { 0 }; - sprintf (vstfxidStr, "%06X", vstfxid); - strcpy (uidString, vstfxidStr); - - char uidStr[9] = { 0 }; - sprintf (uidStr, "%08X", JucePlugin_VSTUniqueID); - strcat (uidString, uidStr); - - char nameidStr[3] = { 0 }; - const size_t len = strlen (JucePlugin_Name); - - for (size_t i = 0; i <= 8; ++i) - { - juce::uint8 c = i < len ? static_cast (JucePlugin_Name[i]) : 0; - - if (c >= 'A' && c <= 'Z') - c += 'a' - 'A'; - - sprintf (nameidStr, "%02X", c); - strcat (uidString, nameidStr); - } - - FUID newOne; - newOne.fromString (uidString); - return newOne; + TUID uuid; + extern JUCE_API void getUUIDForVST2ID (bool, uint8[16]); + getUUIDForVST2ID (forControllerUID, (uint8*) uuid); + return FUID (uuid); } - const Steinberg::FUID JuceVST3Component ::iid (getFUIDForVST2ID (false)); const Steinberg::FUID JuceVST3EditController::iid (getFUIDForVST2ID (true)); - #else DECLARE_CLASS_IID (JuceVST3EditController, 0xABCDEF01, 0x1234ABCD, JucePlugin_ManufacturerCode, JucePlugin_PluginCode) DEF_CLASS_IID (JuceVST3EditController) diff --git a/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp b/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp index f9f4a2f297..8bba466064 100644 --- a/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp +++ b/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp @@ -62,6 +62,114 @@ extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD reason, LPVOID reserve #endif +//============================================================================== +namespace juce +{ +#ifndef JUCE_VST3_CAN_REPLACE_VST2 + #define JUCE_VST3_CAN_REPLACE_VST2 1 +#endif + +#if JucePlugin_Build_VST3 && (__APPLE_CPP__ || __APPLE_CC__ || _WIN32 || _WIN64) && JUCE_VST3_CAN_REPLACE_VST2 +#define VST3_REPLACEMENT_AVAILABLE 1 + +// NB: Nasty old-fashioned code in here because it's copied from the Steinberg example code. +void JUCE_API getUUIDForVST2ID (bool forControllerUID, uint8 uuid[16]) +{ + char uidString[33]; + + const int vstfxid = (('V' << 16) | ('S' << 8) | (forControllerUID ? 'E' : 'T')); + char vstfxidStr[7] = { 0 }; + sprintf (vstfxidStr, "%06X", vstfxid); + + strcpy (uidString, vstfxidStr); + + char uidStr[9] = { 0 }; + sprintf (uidStr, "%08X", JucePlugin_VSTUniqueID); + strcat (uidString, uidStr); + + char nameidStr[3] = { 0 }; + const size_t len = strlen (JucePlugin_Name); + + for (size_t i = 0; i <= 8; ++i) + { + juce::uint8 c = i < len ? static_cast (JucePlugin_Name[i]) : 0; + + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + + sprintf (nameidStr, "%02X", c); + strcat (uidString, nameidStr); + } + + unsigned long p0; + unsigned int p1, p2; + unsigned int p3[8]; + + #ifndef _MSC_VER + sscanf + #else + sscanf_s + #endif + (uidString, "%08lX%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X", + &p0, &p1, &p2, &p3[0], &p3[1], &p3[2], &p3[3], &p3[4], &p3[5], &p3[6], &p3[7]); + + union q0_u { + uint32 word; + uint8 bytes[4]; + } q0; + + union q1_u { + uint16 half; + uint8 bytes[2]; + } q1, q2; + + q0.word = static_cast (p0); + q1.half = static_cast (p1); + q2.half = static_cast (p2); + + // VST3 doesn't use COM compatible UUIDs on non windows platforms + #ifndef _WIN32 + q0.word = ByteOrder::swap (q0.word); + q1.half = ByteOrder::swap (q1.half); + q2.half = ByteOrder::swap (q2.half); + #endif + + for (int i = 0; i < 4; ++i) + uuid[i+0] = q0.bytes[i]; + + for (int i = 0; i < 2; ++i) + uuid[i+4] = q1.bytes[i]; + + for (int i = 0; i < 2; ++i) + uuid[i+6] = q2.bytes[i]; + + for (int i = 0; i < 8; ++i) + uuid[i+8] = static_cast (p3[i]); +} +#else +#define VST3_REPLACEMENT_AVAILABLE 0 +#endif + +#if JucePlugin_Build_VST +pointer_sized_int JUCE_API handleManufacturerSpecificVST2Opcode (int32 index, pointer_sized_int value, void* ptr, float) +{ + #if VST3_REPLACEMENT_AVAILABLE + if ((index == 'stCA' || index == 'stCa') && value == 'FUID' && ptr != nullptr) + { + uint8 fuid[16]; + getUUIDForVST2ID (false, fuid); + ::memcpy (ptr, fuid, 16); + return 1; + } + #else + ignoreUnused (index, value, ptr); + #endif + return 0; +} +#endif + +} // namespace juce + //============================================================================== /** Somewhere in the codebase of your plugin, you need to implement this function and make it return a new instance of the filter subclass that you're building.