|
|
@@ -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; }
|
|
|
|
|
|
|
|
#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) const
|
|
|
|
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];
|
|
|
|
|
|
|
|
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';
|
|
|
|
|
|
|
|
DECLARE_CLASS_IID (JuceVST3EditController, 0xABCDEF01, 0x1234ABCD, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
|
|
|
|
DEF_CLASS_IID (JuceVST3EditController)
|
|
|
|
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)
|
|
|
|