mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-31 03:00:05 +00:00
Added VST3->VST2 backwards compatibility, with a flag JUCE_VST3_CAN_REPLACE_VST2 to disable this if you want your VST2 + 3 versions to use different IDs and not be interchangable.
This commit is contained in:
parent
8146a6bc37
commit
bf72ff0851
1 changed files with 138 additions and 15 deletions
|
|
@ -34,6 +34,23 @@
|
|||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../../juce_audio_processors/format_types/juce_VST3Common.h"
|
||||
|
||||
#ifndef JUCE_VST3_CAN_REPLACE_VST2
|
||||
#define JUCE_VST3_CAN_REPLACE_VST2 1
|
||||
#endif
|
||||
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4514 4996)
|
||||
#endif
|
||||
|
||||
#include <pluginterfaces/vst2.x/vstfxstore.h>
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef Point
|
||||
#undef Component
|
||||
|
||||
|
|
@ -750,10 +767,30 @@ public:
|
|||
return kResultOk;
|
||||
}
|
||||
|
||||
tresult PLUGIN_API setIoMode (Vst::IoMode) override { return kNotImplemented; }
|
||||
tresult PLUGIN_API getRoutingInfo (Vst::RoutingInfo&, Vst::RoutingInfo&) override { return kNotImplemented; }
|
||||
tresult PLUGIN_API setIoMode (Vst::IoMode) override { return kNotImplemented; }
|
||||
tresult PLUGIN_API getRoutingInfo (Vst::RoutingInfo&, Vst::RoutingInfo&) override { return kNotImplemented; }
|
||||
|
||||
bool readFromMemoryStream (IBStream* state) const
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
void loadVST2CompatibleState (const char* data, int size)
|
||||
{
|
||||
const int headerLen = htonl (*(juce::int32*) (data + 4));
|
||||
const struct fxBank* bank = (const struct fxBank*) (data + (8 + headerLen));
|
||||
const int version = htonl (bank->version);
|
||||
|
||||
jassert ('VstW' == htonl (*(juce::int32*) data));
|
||||
jassert (1 == htonl (*(juce::int32*) (data + 8))); // version should be 1 according to Steinberg's docs
|
||||
jassert (cMagic == htonl (bank->chunkMagic));
|
||||
jassert (chunkBankMagic == htonl (bank->fxMagic));
|
||||
jassert (version == 1 || version == 2);
|
||||
jassert (JucePlugin_VSTUniqueID == htonl (bank->fxID));
|
||||
|
||||
pluginInstance->setStateInformation (bank->content.data.chunk,
|
||||
jmin ((int) (size - (bank->content.data.chunk - data)),
|
||||
(int) htonl (bank->content.data.size)));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool readFromMemoryStream (IBStream* state)
|
||||
{
|
||||
FUnknownPtr<MemoryStream> s (state);
|
||||
|
||||
|
|
@ -767,14 +804,19 @@ public:
|
|||
if (s->getSize() >= 5 && memcmp (s->getData(), "VC2!E", 5) == 0)
|
||||
return false;
|
||||
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
loadVST2CompatibleState (s->getData(), (int) s->getSize());
|
||||
#else
|
||||
pluginInstance->setStateInformation (s->getData(), (int) s->getSize());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readFromUnknownStream (IBStream* state) const
|
||||
bool readFromUnknownStream (IBStream* state)
|
||||
{
|
||||
MemoryOutputStream allData;
|
||||
|
||||
|
|
@ -821,16 +863,58 @@ public:
|
|||
return kResultFalse;
|
||||
}
|
||||
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
static tresult writeVST2Int (IBStream* state, int n)
|
||||
{
|
||||
juce::int32 t = (juce::int32) htonl (n);
|
||||
return state->write (&t, 4);
|
||||
}
|
||||
|
||||
static tresult writeVST2Header (IBStream* state)
|
||||
{
|
||||
tresult status = writeVST2Int (state, 'VstW');
|
||||
|
||||
if (status == kResultOk) status = writeVST2Int (state, 8); // header size
|
||||
if (status == kResultOk) status = writeVST2Int (state, 1); // version
|
||||
if (status == kResultOk) status = writeVST2Int (state, 0); // bypass
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
tresult PLUGIN_API getState (IBStream* state) override
|
||||
{
|
||||
if (state != nullptr)
|
||||
{
|
||||
juce::MemoryBlock mem;
|
||||
pluginInstance->getStateInformation (mem);
|
||||
return state->write (mem.getData(), (Steinberg::int32) mem.getSize());
|
||||
}
|
||||
if (state == nullptr)
|
||||
return kInvalidArgument;
|
||||
|
||||
return kInvalidArgument;
|
||||
juce::MemoryBlock mem;
|
||||
pluginInstance->getStateInformation (mem);
|
||||
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
tresult status = writeVST2Header (state);
|
||||
|
||||
if (status != kResultOk)
|
||||
return status;
|
||||
|
||||
const int bankBlockSize = 160;
|
||||
struct fxBank bank;
|
||||
|
||||
zerostruct (bank);
|
||||
bank.chunkMagic = htonl (cMagic);
|
||||
bank.byteSize = htonl (bankBlockSize - 8 + mem.getSize());
|
||||
bank.fxMagic = htonl (chunkBankMagic);
|
||||
bank.version = htonl (2);
|
||||
bank.fxID = htonl (JucePlugin_VSTUniqueID);
|
||||
bank.fxVersion = htonl (JucePlugin_VersionCode);
|
||||
bank.content.data.size = htonl (mem.getSize());
|
||||
|
||||
status = state->write (&bank, bankBlockSize);
|
||||
|
||||
if (status != kResultOk)
|
||||
return status;
|
||||
#endif
|
||||
|
||||
return state->write (mem.getData(), (Steinberg::int32) mem.getSize());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1241,11 +1325,50 @@ private:
|
|||
DECLARE_CLASS_IID (JuceAudioProcessor, 0x0101ABAB, 0xABCDEF01, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
|
||||
DEF_CLASS_IID (JuceAudioProcessor)
|
||||
|
||||
DECLARE_CLASS_IID (JuceVST3Component, 0xABCDEF01, 0x9182FAEB, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
|
||||
DEF_CLASS_IID (JuceVST3Component)
|
||||
#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)
|
||||
{
|
||||
char uidString[33];
|
||||
|
||||
DECLARE_CLASS_IID (JuceVST3EditController, 0xABCDEF01, 0x1234ABCD, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
|
||||
DEF_CLASS_IID (JuceVST3EditController)
|
||||
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 ? 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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
DECLARE_CLASS_IID (JuceVST3Component, 0xABCDEF01, 0x9182FAEB, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
|
||||
DEF_CLASS_IID (JuceVST3Component)
|
||||
#endif
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue