mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
VST3: Allow manifest helper to run independently
This commit is contained in:
parent
80116d60da
commit
f3d7c74ea1
46 changed files with 1299 additions and 1519 deletions
|
|
@ -32,6 +32,28 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
//==============================================================================
|
||||
// This suppresses a warning caused by some of the Steinberg source code
|
||||
#ifndef _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
//==============================================================================
|
||||
// This suppresses a warning in juce_TargetPlatform.h
|
||||
#ifndef JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED
|
||||
#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1
|
||||
|
|
@ -40,6 +62,7 @@
|
|||
#include <juce_core/system/juce_CompilerWarnings.h>
|
||||
#include <juce_core/system/juce_CompilerSupport.h>
|
||||
|
||||
//==============================================================================
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wc++98-compat-extra-semi",
|
||||
"-Wdeprecated-declarations",
|
||||
"-Wexpansion-to-defined",
|
||||
|
|
@ -56,36 +79,12 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wc++98-compat-extra-semi",
|
|||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6387 6031)
|
||||
|
||||
// As of at least 3.7.12 there is a bug in fplatform.h that leads to SMTG_CPP20
|
||||
// having the wrong value when the /Zc:__cplusplus is not enabled. This work
|
||||
// around prevents needing to provide that flag
|
||||
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/pluginterfaces/base/fplatform.h>
|
||||
|
||||
#ifdef SMTG_CPP20
|
||||
#undef SMTG_CPP20
|
||||
#define SMTG_CPP20 JUCE_CXX20_IS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifndef _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX 1
|
||||
#endif
|
||||
|
||||
#if JUCE_MAC
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/hosting/module_mac.mm>
|
||||
#elif JUCE_WINDOWS
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/hosting/module_win32.cpp>
|
||||
#elif JUCE_LINUX
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/hosting/module_linux.cpp>
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/pluginterfaces/base/coreiids.cpp>
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/pluginterfaces/base/funknown.cpp>
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/samples/vst-utilities/moduleinfotool/source/main.cpp>
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/source/common/commonstringconvert.cpp>
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/source/common/memorystream.cpp>
|
||||
#include <juce_audio_processors/format_types/VST3_SDK/public.sdk/source/common/readfile.cpp>
|
||||
|
|
@ -97,3 +96,93 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6387 6031)
|
|||
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
//==============================================================================
|
||||
#if JucePlugin_Enable_ARA
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wpragma-pack")
|
||||
#include <ARA_API/ARAVST3.h>
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
#endif // JucePlugin_Enable_ARA
|
||||
|
||||
//==============================================================================
|
||||
#define jassert(x) assert ((x))
|
||||
#define jassertfalse assert (false)
|
||||
#define DBG(x)
|
||||
#define JUCE_DECLARE_NON_COPYABLE(x)
|
||||
#define JUCE_API
|
||||
|
||||
#if __has_include ("JucePluginDefines.h")
|
||||
#include "JucePluginDefines.h"
|
||||
#endif
|
||||
|
||||
#include <juce_audio_processors/format_types/juce_VST3Utilities.h>
|
||||
#include <juce_audio_processors/utilities/juce_VST3Interface.h>
|
||||
#include "juce_VST3ModuleInfo.h"
|
||||
|
||||
//==============================================================================
|
||||
class JucePluginModule : public VST3::Hosting::Module
|
||||
{
|
||||
public:
|
||||
JucePluginModule()
|
||||
{
|
||||
using namespace Steinberg;
|
||||
using namespace VST3::Hosting;
|
||||
PluginFactory tmp { owned (new juce::JucePluginFactoryBase()) };
|
||||
factory = std::move (tmp);
|
||||
}
|
||||
|
||||
private:
|
||||
bool load (const std::string&, std::string&) final { return {}; }
|
||||
};
|
||||
|
||||
std::optional<Steinberg::ModuleInfo::CompatibilityList> loadCompatibilityFromModule (const VST3::Hosting::Module& pluginModule)
|
||||
{
|
||||
const auto& factory = pluginModule.getFactory();
|
||||
const auto& infos = factory.classInfos();
|
||||
|
||||
const auto iter = std::find_if (infos.begin(), infos.end(), [&] (const auto& info)
|
||||
{
|
||||
return info.category() == kPluginCompatibilityClass;
|
||||
});
|
||||
|
||||
if (iter == infos.end())
|
||||
return {};
|
||||
|
||||
const auto compatibility = factory.createInstance<Steinberg::IPluginCompatibility> (iter->ID());
|
||||
|
||||
if (compatibility == nullptr)
|
||||
return {};
|
||||
|
||||
Steinberg::MemoryStream stream;
|
||||
|
||||
if (compatibility->getCompatibilityJSON (&stream) != Steinberg::kResultOk)
|
||||
return {};
|
||||
|
||||
const std::string_view streamView (stream.getData(), stream.getSize());
|
||||
|
||||
return Steinberg::ModuleInfoLib::parseCompatibilityJson (streamView, nullptr);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int main()
|
||||
{
|
||||
const JucePluginModule pluginModule;
|
||||
|
||||
auto moduleInfo = Steinberg::ModuleInfoLib::createModuleInfo (pluginModule, false);
|
||||
|
||||
if (auto compatibility = loadCompatibilityFromModule (pluginModule))
|
||||
moduleInfo.compatibility = *compatibility;
|
||||
|
||||
std::stringstream output;
|
||||
Steinberg::ModuleInfoLib::outputJson (moduleInfo, output);
|
||||
std::cout << output.str() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
namespace VST3::Hosting
|
||||
{
|
||||
Module::SnapshotList Module::getSnapshots (const std::string&) { return {}; }
|
||||
Optional<std::string> Module::getModuleInfoPath (const std::string&) { return {}; }
|
||||
Module::Ptr Module::create (const std::string&, std::string&) { return {}; }
|
||||
} // namespace VST3::Hosting
|
||||
|
|
|
|||
386
modules/juce_audio_plugin_client/VST3/juce_VST3ModuleInfo.h
Normal file
386
modules/juce_audio_plugin_client/VST3/juce_VST3ModuleInfo.h
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
[[maybe_unused]] static Steinberg::FUID toSteinbergUID (const VST3Interface::Id& uid)
|
||||
{
|
||||
return Steinberg::FUID::fromTUID ((const char*) (uid.data()));
|
||||
}
|
||||
|
||||
[[maybe_unused]] static VST3Interface::Id toVST3InterfaceId (const Steinberg::TUID uid)
|
||||
{
|
||||
VST3Interface::Id iid;
|
||||
std::memcpy (iid.data(), uid, iid.size());
|
||||
return iid;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static VST3Interface::Id getVST3InterfaceId (VST3Interface::Type interfaceType)
|
||||
{
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
if (interfaceType == VST3Interface::Type::controller || interfaceType == VST3Interface::Type::component)
|
||||
return VST3Interface::vst2PluginId (JucePlugin_VSTUniqueID, JucePlugin_Name, interfaceType);
|
||||
#endif
|
||||
|
||||
return VST3Interface::jucePluginId (JucePlugin_ManufacturerCode, JucePlugin_PluginCode, interfaceType);
|
||||
}
|
||||
|
||||
[[maybe_unused]] static std::vector<VST3Interface::Id> getAllVST3CompatibleClasses()
|
||||
{
|
||||
return
|
||||
{
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
getVST3InterfaceId (VST3Interface::Type::component),
|
||||
#endif
|
||||
|
||||
#ifdef JUCE_VST3_COMPATIBLE_CLASSES
|
||||
JUCE_VST3_COMPATIBLE_CLASSES
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// See https://steinbergmedia.github.io/vst3_dev_portal/pages/FAQ/Compatibility+with+VST+2.x+or+VST+1.html
|
||||
|
||||
#ifdef JUCE_VST3_COMPATIBLE_CLASSES
|
||||
class JucePluginCompatibility final : public Steinberg::IPluginCompatibility
|
||||
{
|
||||
public:
|
||||
virtual ~JucePluginCompatibility() = default;
|
||||
|
||||
JUCE_DECLARE_VST3_COM_REF_METHODS
|
||||
|
||||
Steinberg::tresult PLUGIN_API getCompatibilityJSON (Steinberg::IBStream* stream) override
|
||||
{
|
||||
// We must avoid relying on any dependencies here including anything in juce_core
|
||||
std::string json = std::invoke ([]
|
||||
{
|
||||
static const auto newId = toSteinbergUID (getVST3InterfaceId (VST3Interface::Type::component));
|
||||
static const auto oldIds = getAllVST3CompatibleClasses();
|
||||
|
||||
std::stringstream str;
|
||||
str << "[{"
|
||||
<< "\"New\": \"" << VST3::UID { newId }.toString() << "\", "
|
||||
<< "\"Old\": [";
|
||||
|
||||
for (int i = 0; i < oldIds.size(); ++i)
|
||||
{
|
||||
str << "\""
|
||||
<< std::hex
|
||||
<< std::setw (2)
|
||||
<< std::setfill ('0')
|
||||
<< std::uppercase;
|
||||
|
||||
for (auto byte : oldIds[i])
|
||||
str << (int) byte;
|
||||
|
||||
str.clear();
|
||||
str << "\"";
|
||||
|
||||
if (i < oldIds.size() - 1)
|
||||
str << ", ";
|
||||
}
|
||||
|
||||
str << "]}]";
|
||||
return str.str();
|
||||
});
|
||||
|
||||
return stream->write (json.data(), (Steinberg::int32) json.size());
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID targetIID,
|
||||
void** obj) override
|
||||
{
|
||||
const auto result = testForMultiple (*this,
|
||||
targetIID,
|
||||
UniqueBase<IPluginCompatibility>{},
|
||||
UniqueBase<FUnknown>{});
|
||||
|
||||
if (result.isOk())
|
||||
return result.extract (obj);
|
||||
|
||||
jassertfalse; // Something new?
|
||||
*obj = nullptr;
|
||||
return Steinberg::kNotImplemented;
|
||||
}
|
||||
|
||||
inline static const Steinberg::FUID iid = toSteinbergUID (getVST3InterfaceId (VST3Interface::Type::compatibility));
|
||||
|
||||
private:
|
||||
std::atomic<int> refCount { 1 };
|
||||
};
|
||||
#endif // JUCE_VST3_COMPATIBLE_CLASSES
|
||||
|
||||
//==============================================================================
|
||||
class JucePluginFactoryBase : public Steinberg::IPluginFactory3
|
||||
{
|
||||
public:
|
||||
JucePluginFactoryBase() = default;
|
||||
virtual ~JucePluginFactoryBase() = default;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_VST3_COM_REF_METHODS
|
||||
|
||||
Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID targetIID, void** obj) final
|
||||
{
|
||||
const auto result = testForMultiple (*this,
|
||||
targetIID,
|
||||
UniqueBase<IPluginFactory3>{},
|
||||
UniqueBase<IPluginFactory2>{},
|
||||
UniqueBase<IPluginFactory>{},
|
||||
UniqueBase<FUnknown>{});
|
||||
|
||||
if (result.isOk())
|
||||
return result.extract (obj);
|
||||
|
||||
jassertfalse; // Something new?
|
||||
*obj = nullptr;
|
||||
return Steinberg::kNotImplemented;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Steinberg::int32 PLUGIN_API countClasses() final
|
||||
{
|
||||
return (Steinberg::int32) getClassEntries().size;
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API getFactoryInfo (Steinberg::PFactoryInfo* info) final
|
||||
{
|
||||
if (info == nullptr)
|
||||
return Steinberg::kInvalidArgument;
|
||||
|
||||
std::memcpy (info, &factoryInfo, sizeof (factoryInfo));
|
||||
return Steinberg::kResultOk;
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API getClassInfo (Steinberg::int32 index,
|
||||
Steinberg::PClassInfo* info) final
|
||||
{
|
||||
return getPClassInfo (index, info, &ClassEntry::info2);
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API getClassInfo2 (Steinberg::int32 index,
|
||||
Steinberg::PClassInfo2* info) final
|
||||
{
|
||||
return getPClassInfo (index, info, &ClassEntry::info2);
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API getClassInfoUnicode (Steinberg::int32 index,
|
||||
Steinberg::PClassInfoW* info) final
|
||||
{
|
||||
return getPClassInfo (index, info, &ClassEntry::infoW);
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API setHostContext (Steinberg::FUnknown*) override
|
||||
{
|
||||
jassertfalse;
|
||||
return Steinberg::kNotImplemented;
|
||||
}
|
||||
|
||||
Steinberg::tresult PLUGIN_API createInstance (Steinberg::FIDString cid,
|
||||
Steinberg::FIDString sourceIid,
|
||||
void** obj) override
|
||||
{
|
||||
*obj = nullptr;
|
||||
|
||||
Steinberg::TUID tuid;
|
||||
std::memcpy (tuid, sourceIid, sizeof (tuid));
|
||||
|
||||
#if VST_VERSION >= 0x030608
|
||||
auto sourceFuid = Steinberg::FUID::fromTUID (tuid);
|
||||
#else
|
||||
FUID sourceFuid;
|
||||
sourceFuid = tuid;
|
||||
#endif
|
||||
|
||||
if (cid == nullptr || sourceIid == nullptr || ! sourceFuid.isValid())
|
||||
{
|
||||
jassertfalse; // The host you're running in has severe implementation issues!
|
||||
return Steinberg::kInvalidArgument;
|
||||
}
|
||||
|
||||
Steinberg::TUID iidToQuery;
|
||||
sourceFuid.toTUID (iidToQuery);
|
||||
|
||||
for (auto& entry : getClassEntries())
|
||||
{
|
||||
if (doUIDsMatch (entry.infoW.cid, cid))
|
||||
{
|
||||
if (auto instance = becomeVSTComSmartPtrOwner (createInstance (entry)))
|
||||
{
|
||||
if (instance->queryInterface (iidToQuery, obj) == Steinberg::kResultOk)
|
||||
return Steinberg::kResultOk;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Steinberg::kNoInterface;
|
||||
}
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
struct ClassEntry
|
||||
{
|
||||
#ifndef JucePlugin_Vst3ComponentFlags
|
||||
#if JucePlugin_IsSynth
|
||||
#define JucePlugin_Vst3ComponentFlags Steinberg::Vst::kSimpleModeSupported
|
||||
#else
|
||||
#define JucePlugin_Vst3ComponentFlags 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_Vst3Category
|
||||
#if JucePlugin_IsSynth
|
||||
#define JucePlugin_Vst3Category Steinberg::Vst::PlugType::kInstrumentSynth
|
||||
#else
|
||||
#define JucePlugin_Vst3Category Steinberg::Vst::PlugType::kFx
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ClassEntry (VST3Interface::Type interfaceType,
|
||||
const char* name,
|
||||
bool includeFlagsAndCategory) noexcept
|
||||
: ClassEntry (getVST3InterfaceId (interfaceType), name, includeFlagsAndCategory)
|
||||
{}
|
||||
|
||||
ClassEntry (VST3Interface::Id interfaceId,
|
||||
const char* name,
|
||||
bool includeFlagsAndCategory) noexcept
|
||||
: info2 ((const char*) interfaceId.data(),
|
||||
Steinberg::PClassInfo::kManyInstances,
|
||||
name,
|
||||
JucePlugin_Name,
|
||||
includeFlagsAndCategory ? JucePlugin_Vst3ComponentFlags : 0,
|
||||
includeFlagsAndCategory ? JucePlugin_Vst3Category : "",
|
||||
JucePlugin_Manufacturer,
|
||||
JucePlugin_VersionString,
|
||||
kVstVersionString)
|
||||
{
|
||||
infoW.fromAscii (info2);
|
||||
}
|
||||
|
||||
Steinberg::PClassInfo2 info2;
|
||||
Steinberg::PClassInfoW infoW;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (ClassEntry)
|
||||
};
|
||||
|
||||
struct ClassEntrySpan
|
||||
{
|
||||
const ClassEntry* data{};
|
||||
size_t size{};
|
||||
|
||||
const ClassEntry* begin() const { return data; }
|
||||
const ClassEntry* end() const { return data + size; }
|
||||
};
|
||||
|
||||
static ClassEntrySpan getClassEntries()
|
||||
{
|
||||
static const ClassEntry classEntries[]
|
||||
{
|
||||
#ifdef JUCE_VST3_COMPATIBLE_CLASSES
|
||||
{ VST3Interface::Type::compatibility, kPluginCompatibilityClass, false },
|
||||
#endif
|
||||
{ VST3Interface::Type::component, kVstAudioEffectClass, true },
|
||||
{ VST3Interface::Type::controller, kVstComponentControllerClass, true },
|
||||
#if JucePlugin_Enable_ARA
|
||||
{ VST3Interface::Type::ara, kARAMainFactoryClass, true }
|
||||
#endif
|
||||
};
|
||||
|
||||
return { classEntries, std::size (classEntries) };
|
||||
}
|
||||
|
||||
virtual Steinberg::FUnknown* createInstance (const ClassEntry& entry)
|
||||
{
|
||||
#ifdef JUCE_VST3_COMPATIBLE_CLASSES
|
||||
if (doUIDsMatch (entry.info2.cid, JucePluginCompatibility::iid.toTUID()))
|
||||
return new JucePluginCompatibility();
|
||||
#else
|
||||
(void) entry;
|
||||
#endif
|
||||
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
const ClassEntry& getClassEntry (Steinberg::int32 index) const
|
||||
{
|
||||
return getClassEntries().data[index];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename PClassInfoTargetType, typename PClassInfoSourceType>
|
||||
Steinberg::tresult PLUGIN_API getPClassInfo (Steinberg::int32 index,
|
||||
PClassInfoTargetType* info,
|
||||
PClassInfoSourceType ClassEntry::*source)
|
||||
{
|
||||
if (info == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return Steinberg::kInvalidArgument;
|
||||
}
|
||||
|
||||
std::memcpy (info, &(getClassEntry (index).*source), sizeof (*info));
|
||||
return Steinberg::kResultOk;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
std::atomic<int> refCount { 1 };
|
||||
const Steinberg::PFactoryInfo factoryInfo
|
||||
{
|
||||
JucePlugin_Manufacturer,
|
||||
JucePlugin_ManufacturerWebsite,
|
||||
JucePlugin_ManufacturerEmail,
|
||||
Steinberg::Vst::kDefaultFactoryFlags
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// no leak detector here to prevent it firing on shutdown when running in hosts that
|
||||
// don't release the factory object correctly...
|
||||
JUCE_DECLARE_NON_COPYABLE (JucePluginFactoryBase)
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#endif // DOXYGEN
|
||||
|
|
@ -68,12 +68,13 @@
|
|||
|
||||
Enable this if you want your VST3 plug-in to load and save VST2 compatible
|
||||
state. This allows hosts to replace VST2 plug-ins with VST3 plug-ins. If
|
||||
you change this option then your VST3 plug-in will, by default, be incompatible
|
||||
with previous versions.
|
||||
you change this option then your VST3 plug-in will, by default, be
|
||||
incompatible with previous versions.
|
||||
|
||||
If you've already released a VST2 and VST3 with this flag set to 0, you can still enable
|
||||
migration from VST2 to VST3 on newer hosts. See VST3ClientExtensions::getCompatibleClasses()
|
||||
and VST3ClientExtensions::getCompatibleParameterIds() for more details.
|
||||
If you've already released a VST2 and VST3 with this flag set to 0, you can
|
||||
still enable migration from VST2 to VST3 on newer hosts by defining the
|
||||
JUCE_VST3_COMPATIBLE_CLASSES preprocessor and implementing the
|
||||
VST3ClientExtensions::getCompatibleParameterIds() method.
|
||||
*/
|
||||
#ifndef JUCE_VST3_CAN_REPLACE_VST2
|
||||
#define JUCE_VST3_CAN_REPLACE_VST2 1
|
||||
|
|
@ -81,10 +82,12 @@
|
|||
|
||||
/** Config: JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
|
||||
Enable this if you want to force JUCE to use a continuous parameter
|
||||
index to identify a parameter in a DAW (this was the default in old
|
||||
versions of JUCE). This is index is usually used by the DAW to save
|
||||
automation data and enabling this may mess up user's DAW projects.
|
||||
Enable this if you want to force JUCE to use a continuous parameter index to
|
||||
identify a parameter in a DAW (this was the default in old versions of JUCE,
|
||||
and is always the default for VST2 plugins). This index is usually used by
|
||||
the DAW to save automation data. Changing this setting may mess up user's
|
||||
DAW projects, see VST3ClientExtensions::getCompatibleParameterIds() for a
|
||||
way to overcome this issue on newer VST3 hosts.
|
||||
*/
|
||||
#ifndef JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
#define JUCE_FORCE_USE_LEGACY_PARAM_IDS 0
|
||||
|
|
|
|||
|
|
@ -1814,9 +1814,9 @@ private:
|
|||
if (args.ptr == nullptr)
|
||||
return 0;
|
||||
|
||||
const auto uid = VST3ClientExtensions::convertVST2PluginId (JucePlugin_VSTUniqueID,
|
||||
JucePlugin_Name,
|
||||
VST3ClientExtensions::InterfaceType::component);
|
||||
const auto uid = VST3Interface::vst2PluginId (JucePlugin_VSTUniqueID,
|
||||
JucePlugin_Name,
|
||||
VST3Interface::Type::component);
|
||||
std::copy (uid.begin(), uid.end(), reinterpret_cast<std::byte*> (args.ptr));
|
||||
return 1;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -60,9 +60,12 @@ JUCE_BEGIN_NO_SANITIZE ("vptr")
|
|||
#include <juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h>
|
||||
#include <juce_gui_basics/native/juce_WindowsHooks_windows.h>
|
||||
|
||||
//==============================================================================
|
||||
#include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
|
||||
#include <juce_audio_processors/utilities/juce_FlagCache.h>
|
||||
#include <juce_audio_processors/format_types/juce_VST3Utilities.h>
|
||||
#include <juce_audio_processors/format_types/juce_VST3Common.h>
|
||||
#include <juce_audio_plugin_client/VST3/juce_VST3ModuleInfo.h>
|
||||
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2 && ! JUCE_FORCE_USE_LEGACY_PARAM_IDS && ! JUCE_IGNORE_VST3_MISMATCHED_PARAMETER_ID_WARNING
|
||||
|
||||
|
|
@ -111,51 +114,11 @@ JUCE_BEGIN_NO_SANITIZE ("vptr")
|
|||
#include <juce_core/native/juce_CFHelpers_mac.h>
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JucePlugin_Enable_ARA
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wpragma-pack")
|
||||
#include <ARA_API/ARAVST3.h>
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
|
||||
#if ARA_SUPPORT_VERSION_1
|
||||
#error "Unsupported ARA version - only ARA version 2 and onward are supported by the current implementation"
|
||||
#endif
|
||||
|
||||
DEF_CLASS_IID (ARA::IPlugInEntryPoint)
|
||||
DEF_CLASS_IID (ARA::IPlugInEntryPoint2)
|
||||
DEF_CLASS_IID (ARA::IMainFactory)
|
||||
#endif
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
using VST3InterfaceType = VST3ClientExtensions::InterfaceType;
|
||||
using VST3InterfaceId = VST3ClientExtensions::InterfaceId;
|
||||
|
||||
using namespace Steinberg;
|
||||
|
||||
static FUID toSteinbergUID (const VST3InterfaceId& uid)
|
||||
{
|
||||
return FUID::fromTUID ((const char*) (uid.data()));
|
||||
}
|
||||
|
||||
static VST3InterfaceId toVST3InterfaceId (const TUID uid)
|
||||
{
|
||||
VST3InterfaceId iid;
|
||||
std::memcpy (iid.data(), uid, iid.size());
|
||||
return iid;
|
||||
}
|
||||
|
||||
static VST3InterfaceId getInterfaceId (VST3InterfaceType interfaceType)
|
||||
{
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
if (interfaceType == VST3InterfaceType::controller || interfaceType == VST3InterfaceType::component)
|
||||
return VST3ClientExtensions::convertVST2PluginId (JucePlugin_VSTUniqueID, JucePlugin_Name, interfaceType);
|
||||
#endif
|
||||
|
||||
return VST3ClientExtensions::convertJucePluginId (JucePlugin_ManufacturerCode, JucePlugin_PluginCode, interfaceType);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
double getScaleFactorForWindow (HWND);
|
||||
|
|
@ -623,7 +586,7 @@ public:
|
|||
|
||||
bool isUsingManagedParameters() const noexcept { return juceParameters.isUsingManagedParameters(); }
|
||||
|
||||
std::map<Vst::ParamID, AudioProcessorParameter*> getParameterMap (const VST3InterfaceId& pluginId) const
|
||||
std::map<Vst::ParamID, AudioProcessorParameter*> getParameterMap (const VST3Interface::Id& pluginId) const
|
||||
{
|
||||
const auto iter = compatibleParameterIdMap.find (pluginId);
|
||||
return iter != compatibleParameterIdMap.end() ? iter->second
|
||||
|
|
@ -638,7 +601,7 @@ public:
|
|||
|
||||
void updateParameterMapping()
|
||||
{
|
||||
static const auto currentPluginId = getInterfaceId (VST3InterfaceType::component);
|
||||
static const auto currentPluginId = getVST3InterfaceId (VST3Interface::Type::component);
|
||||
|
||||
compatibleParameterIdMap = {};
|
||||
compatibleParameterIdMap[currentPluginId] = paramMap;
|
||||
|
|
@ -649,7 +612,7 @@ public:
|
|||
if (ext == nullptr)
|
||||
return;
|
||||
|
||||
for (const auto& compatibleClass : getAllCompatibleClasses (*audioProcessor))
|
||||
for (const auto& compatibleClass : getAllVST3CompatibleClasses())
|
||||
{
|
||||
auto& parameterIdMap = compatibleParameterIdMap[compatibleClass];
|
||||
for (auto [oldParamId, newParamId] : ext->getCompatibleParameterIds (compatibleClass))
|
||||
|
|
@ -678,28 +641,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/* Includes all compatible classes declared in the client extensions, along with
|
||||
our own ID in the case that JUCE_VST3_CAN_REPLACE_VST2 is set.
|
||||
*/
|
||||
static std::vector<VST3ClientExtensions::InterfaceId> getAllCompatibleClasses (AudioProcessor& processor)
|
||||
{
|
||||
auto result = std::invoke ([&]
|
||||
{
|
||||
if (auto* ext = processor.getVST3ClientExtensions())
|
||||
return ext->getCompatibleClasses();
|
||||
|
||||
return std::vector<VST3ClientExtensions::InterfaceId>{};
|
||||
});
|
||||
|
||||
#if JUCE_VST3_CAN_REPLACE_VST2
|
||||
result.push_back (getInterfaceId (VST3InterfaceType::component));
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
inline static const FUID iid = toSteinbergUID (getInterfaceId (VST3InterfaceType::processor));
|
||||
inline static const FUID iid = toSteinbergUID (getVST3InterfaceId (VST3Interface::Type::processor));
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
@ -810,7 +753,7 @@ private:
|
|||
CachedParamValues cachedParamValues;
|
||||
Vst::ParamID bypassParamID = 0, programParamID = static_cast<Vst::ParamID> (paramPreset);
|
||||
bool bypassIsRegularParameter = false;
|
||||
std::map<VST3InterfaceId, std::map<Vst::ParamID, AudioProcessorParameter*>> compatibleParameterIdMap;
|
||||
std::map<VST3Interface::Id, std::map<Vst::ParamID, AudioProcessorParameter*>> compatibleParameterIdMap;
|
||||
std::map<String, AudioProcessorParameter*> juceIdParameterMap;
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -917,7 +860,7 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
inline static const FUID iid = toSteinbergUID (getInterfaceId (VST3InterfaceType::controller));
|
||||
inline static const FUID iid = toSteinbergUID (getVST3InterfaceId (VST3Interface::Type::controller));
|
||||
|
||||
//==============================================================================
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Winconsistent-missing-override")
|
||||
|
|
@ -1273,7 +1216,7 @@ public:
|
|||
setParamNormalized (vstParamId, paramValue);
|
||||
}
|
||||
|
||||
if (! JuceAudioProcessor::getAllCompatibleClasses (*pluginInstance).empty())
|
||||
if (! getAllVST3CompatibleClasses().empty())
|
||||
{
|
||||
restartFlags |= Vst::kParamIDMappingChanged;
|
||||
audioProcessor->updateParameterMapping();
|
||||
|
|
@ -2688,7 +2631,7 @@ private:
|
|||
return createARAFactory();
|
||||
}
|
||||
|
||||
inline static const FUID iid = toSteinbergUID (getInterfaceId (VST3InterfaceType::ara));
|
||||
inline static const FUID iid = toSteinbergUID (getVST3InterfaceId (VST3Interface::Type::ara));
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
@ -2761,7 +2704,7 @@ public:
|
|||
AudioProcessor& getPluginInstance() const noexcept { return *pluginInstance; }
|
||||
|
||||
//==============================================================================
|
||||
inline static const FUID iid = toSteinbergUID (getInterfaceId (VST3InterfaceType::component));
|
||||
inline static const FUID iid = toSteinbergUID (getVST3InterfaceId (VST3Interface::Type::component));
|
||||
|
||||
JUCE_DECLARE_VST3_COM_REF_METHODS
|
||||
|
||||
|
|
@ -2985,7 +2928,7 @@ public:
|
|||
//==============================================================================
|
||||
bool shouldTryToLoadVst2State()
|
||||
{
|
||||
return ! JuceAudioProcessor::getAllCompatibleClasses (*pluginInstance).empty();
|
||||
return ! getAllVST3CompatibleClasses().empty();
|
||||
}
|
||||
|
||||
bool shouldWriteStateWithVst2Compatibility()
|
||||
|
|
@ -4138,182 +4081,21 @@ bool shutdownModule()
|
|||
}
|
||||
#endif
|
||||
|
||||
// See https://steinbergmedia.github.io/vst3_dev_portal/pages/FAQ/Compatibility+with+VST+2.x+or+VST+1.html
|
||||
class JucePluginCompatibility final : public IPluginCompatibility
|
||||
//==============================================================================
|
||||
class JucePluginFactory final : public JucePluginFactoryBase
|
||||
{
|
||||
public:
|
||||
virtual ~JucePluginCompatibility() = default;
|
||||
JucePluginFactory() = default;
|
||||
|
||||
JUCE_DECLARE_VST3_COM_REF_METHODS
|
||||
|
||||
tresult PLUGIN_API getCompatibilityJSON (IBStream* stream) override
|
||||
{
|
||||
const ScopedJuceInitialiser_GUI libraryInitialiser;
|
||||
|
||||
auto filter = createPluginFilterOfType (AudioProcessor::WrapperType::wrapperType_VST3);
|
||||
|
||||
const auto compatibilityObjects = std::invoke ([&]
|
||||
{
|
||||
const auto compatibleClasses = JuceAudioProcessor::getAllCompatibleClasses (*filter);
|
||||
|
||||
if (compatibleClasses.empty())
|
||||
return Array<var>();
|
||||
|
||||
DynamicObject::Ptr object { new DynamicObject };
|
||||
|
||||
// New iid is the ID of our Audio Effect class
|
||||
object->setProperty ("New", String (VST3::UID (JuceVST3Component::iid).toString()));
|
||||
object->setProperty ("Old", std::invoke ([&]
|
||||
{
|
||||
Array<var> oldArray;
|
||||
|
||||
for (const auto& uid : compatibleClasses)
|
||||
oldArray.add (String::toHexString (uid.data(), (int) uid.size(), 0));
|
||||
|
||||
return oldArray;
|
||||
}));
|
||||
|
||||
return Array<var> { object.get() };
|
||||
});
|
||||
|
||||
MemoryOutputStream memory;
|
||||
JSON::writeToStream (memory, var { compatibilityObjects });
|
||||
return stream->write (memory.getMemoryBlock().getData(), (Steinberg::int32) memory.getDataSize());
|
||||
}
|
||||
|
||||
tresult PLUGIN_API queryInterface (const TUID targetIID, void** obj) override
|
||||
{
|
||||
const auto result = testForMultiple (*this,
|
||||
targetIID,
|
||||
UniqueBase<IPluginCompatibility>{},
|
||||
UniqueBase<FUnknown>{});
|
||||
|
||||
if (result.isOk())
|
||||
return result.extract (obj);
|
||||
|
||||
jassertfalse; // Something new?
|
||||
*obj = nullptr;
|
||||
return kNotImplemented;
|
||||
}
|
||||
|
||||
inline static const FUID iid = toSteinbergUID (getInterfaceId (VST3InterfaceType::compatibility));
|
||||
|
||||
private:
|
||||
std::atomic<int> refCount { 1 };
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
using CreateFunction = FUnknown* (*) (const VSTComSmartPtr<Vst::IHostApplication>&,
|
||||
const RunLoop&);
|
||||
|
||||
//==============================================================================
|
||||
struct JucePluginFactory final : public IPluginFactory3
|
||||
{
|
||||
JucePluginFactory()
|
||||
: factoryInfo (JucePlugin_Manufacturer, JucePlugin_ManufacturerWebsite,
|
||||
JucePlugin_ManufacturerEmail, Vst::kDefaultFactoryFlags) {}
|
||||
|
||||
virtual ~JucePluginFactory() = default;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_VST3_COM_REF_METHODS
|
||||
|
||||
tresult PLUGIN_API queryInterface (const TUID targetIID, void** obj) override
|
||||
{
|
||||
const auto result = testForMultiple (*this,
|
||||
targetIID,
|
||||
UniqueBase<IPluginFactory3>{},
|
||||
UniqueBase<IPluginFactory2>{},
|
||||
UniqueBase<IPluginFactory>{},
|
||||
UniqueBase<FUnknown>{});
|
||||
|
||||
if (result.isOk())
|
||||
return result.extract (obj);
|
||||
|
||||
jassertfalse; // Something new?
|
||||
*obj = nullptr;
|
||||
return kNotImplemented;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Steinberg::int32 PLUGIN_API countClasses() override
|
||||
{
|
||||
return (Steinberg::int32) getClassEntries().size();
|
||||
}
|
||||
|
||||
tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) override
|
||||
{
|
||||
if (info == nullptr)
|
||||
return kInvalidArgument;
|
||||
|
||||
memcpy (info, &factoryInfo, sizeof (PFactoryInfo));
|
||||
return kResultOk;
|
||||
}
|
||||
|
||||
tresult PLUGIN_API getClassInfo (Steinberg::int32 index, PClassInfo* info) override
|
||||
{
|
||||
return getPClassInfo<PClassInfo> (index, info);
|
||||
}
|
||||
|
||||
tresult PLUGIN_API getClassInfo2 (Steinberg::int32 index, PClassInfo2* info) override
|
||||
{
|
||||
return getPClassInfo<PClassInfo2> (index, info);
|
||||
}
|
||||
|
||||
tresult PLUGIN_API getClassInfoUnicode (Steinberg::int32 index, PClassInfoW* info) override
|
||||
{
|
||||
if (info != nullptr)
|
||||
{
|
||||
memcpy (info, &getClassEntries()[static_cast<size_t> (index)].infoW, sizeof (PClassInfoW));
|
||||
return kResultOk;
|
||||
}
|
||||
|
||||
return kInvalidArgument;
|
||||
}
|
||||
|
||||
tresult PLUGIN_API createInstance (FIDString cid, FIDString sourceIid, void** obj) override
|
||||
Steinberg::tresult PLUGIN_API createInstance (Steinberg::FIDString cid,
|
||||
Steinberg::FIDString sourceIid,
|
||||
void** obj) override
|
||||
{
|
||||
const ScopedRunLoop scope { runLoop };
|
||||
|
||||
*obj = nullptr;
|
||||
|
||||
TUID tuid;
|
||||
memcpy (tuid, sourceIid, sizeof (TUID));
|
||||
|
||||
#if VST_VERSION >= 0x030608
|
||||
auto sourceFuid = FUID::fromTUID (tuid);
|
||||
#else
|
||||
FUID sourceFuid;
|
||||
sourceFuid = tuid;
|
||||
#endif
|
||||
|
||||
if (cid == nullptr || sourceIid == nullptr || ! sourceFuid.isValid())
|
||||
{
|
||||
jassertfalse; // The host you're running in has severe implementation issues!
|
||||
return kInvalidArgument;
|
||||
}
|
||||
|
||||
TUID iidToQuery;
|
||||
sourceFuid.toTUID (iidToQuery);
|
||||
|
||||
for (auto& entry : getClassEntries())
|
||||
{
|
||||
if (doUIDsMatch (entry.infoW.cid, cid))
|
||||
{
|
||||
if (auto instance = becomeVSTComSmartPtrOwner (entry.createFunction (host, runLoop)))
|
||||
{
|
||||
if (instance->queryInterface (iidToQuery, obj) == kResultOk)
|
||||
return kResultOk;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return kNoInterface;
|
||||
return JucePluginFactoryBase::createInstance (cid, sourceIid, obj);
|
||||
}
|
||||
|
||||
tresult PLUGIN_API setHostContext (FUnknown* context) override
|
||||
Steinberg::tresult PLUGIN_API setHostContext (Steinberg::FUnknown* context) override
|
||||
{
|
||||
runLoop.loadFrom (context);
|
||||
host.loadFrom (context);
|
||||
|
|
@ -4330,136 +4112,24 @@ struct JucePluginFactory final : public IPluginFactory3
|
|||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
std::atomic<int> refCount { 1 };
|
||||
const PFactoryInfo factoryInfo;
|
||||
VSTComSmartPtr<Vst::IHostApplication> host;
|
||||
RunLoop runLoop;
|
||||
|
||||
//==============================================================================
|
||||
struct ClassEntry
|
||||
FUnknown* createInstance (const ClassEntry& entry) final
|
||||
{
|
||||
ClassEntry (const PClassInfo2& info, CreateFunction fn) noexcept
|
||||
: info2 (info), createFunction (fn)
|
||||
{
|
||||
infoW.fromAscii (info);
|
||||
}
|
||||
if (doUIDsMatch (entry.info2.cid, JuceVST3Component::iid))
|
||||
return static_cast<Vst::IAudioProcessor*> (new JuceVST3Component (host, runLoop));
|
||||
|
||||
PClassInfo2 info2;
|
||||
PClassInfoW infoW;
|
||||
CreateFunction createFunction = {};
|
||||
if (doUIDsMatch (entry.info2.cid, JuceVST3EditController::iid))
|
||||
return static_cast<Vst::IEditController*> (new JuceVST3EditController (host, runLoop));
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE (ClassEntry)
|
||||
};
|
||||
|
||||
static Span<const ClassEntry> getClassEntries()
|
||||
{
|
||||
#ifndef JucePlugin_Vst3ComponentFlags
|
||||
#if JucePlugin_IsSynth
|
||||
#define JucePlugin_Vst3ComponentFlags Vst::kSimpleModeSupported
|
||||
#else
|
||||
#define JucePlugin_Vst3ComponentFlags 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_Vst3Category
|
||||
#if JucePlugin_IsSynth
|
||||
#define JucePlugin_Vst3Category Vst::PlugType::kInstrumentSynth
|
||||
#else
|
||||
#define JucePlugin_Vst3Category Vst::PlugType::kFx
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const PClassInfo2 compatibilityClass { JucePluginCompatibility::iid,
|
||||
PClassInfo::kManyInstances,
|
||||
kPluginCompatibilityClass,
|
||||
JucePlugin_Name,
|
||||
0,
|
||||
"",
|
||||
JucePlugin_Manufacturer,
|
||||
JucePlugin_VersionString,
|
||||
kVstVersionString };
|
||||
|
||||
static const PClassInfo2 componentClass { JuceVST3Component::iid,
|
||||
PClassInfo::kManyInstances,
|
||||
kVstAudioEffectClass,
|
||||
JucePlugin_Name,
|
||||
JucePlugin_Vst3ComponentFlags,
|
||||
JucePlugin_Vst3Category,
|
||||
JucePlugin_Manufacturer,
|
||||
JucePlugin_VersionString,
|
||||
kVstVersionString };
|
||||
|
||||
static const PClassInfo2 controllerClass { JuceVST3EditController::iid,
|
||||
PClassInfo::kManyInstances,
|
||||
kVstComponentControllerClass,
|
||||
JucePlugin_Name,
|
||||
JucePlugin_Vst3ComponentFlags,
|
||||
JucePlugin_Vst3Category,
|
||||
JucePlugin_Manufacturer,
|
||||
JucePlugin_VersionString,
|
||||
kVstVersionString };
|
||||
#if JucePlugin_Enable_ARA
|
||||
static const PClassInfo2 araFactoryClass { JuceARAFactory::iid,
|
||||
PClassInfo::kManyInstances,
|
||||
kARAMainFactoryClass,
|
||||
JucePlugin_Name,
|
||||
JucePlugin_Vst3ComponentFlags,
|
||||
JucePlugin_Vst3Category,
|
||||
JucePlugin_Manufacturer,
|
||||
JucePlugin_VersionString,
|
||||
kVstVersionString };
|
||||
if (doUIDsMatch (entry.info2.cid, JuceARAFactory::iid))
|
||||
return static_cast<ARA::IMainFactory*> (new JuceARAFactory());
|
||||
#endif
|
||||
|
||||
static const ClassEntry classEntries[]
|
||||
{
|
||||
ClassEntry { componentClass, [] (const VSTComSmartPtr<Vst::IHostApplication>& h,
|
||||
const RunLoop& l) -> FUnknown*
|
||||
{
|
||||
return static_cast<Vst::IAudioProcessor*> (new JuceVST3Component (h, l));
|
||||
} },
|
||||
ClassEntry { controllerClass, [] (const VSTComSmartPtr<Vst::IHostApplication>& h,
|
||||
const RunLoop& l) -> FUnknown*
|
||||
{
|
||||
return static_cast<Vst::IEditController*> (new JuceVST3EditController (h, l));
|
||||
} },
|
||||
ClassEntry { compatibilityClass, [] (const VSTComSmartPtr<Vst::IHostApplication>&,
|
||||
const RunLoop&) -> FUnknown*
|
||||
{
|
||||
return new JucePluginCompatibility;
|
||||
} },
|
||||
#if JucePlugin_Enable_ARA
|
||||
ClassEntry { araFactoryClass, [] (const VSTComSmartPtr<Vst::IHostApplication>&,
|
||||
const RunLoop&) -> FUnknown*
|
||||
{
|
||||
return static_cast<ARA::IMainFactory*> (new JuceARAFactory);
|
||||
} },
|
||||
#endif
|
||||
};
|
||||
|
||||
return Span { classEntries };
|
||||
return JucePluginFactoryBase::createInstance (entry);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <class PClassInfoType>
|
||||
tresult PLUGIN_API getPClassInfo (Steinberg::int32 index, PClassInfoType* info)
|
||||
{
|
||||
if (info != nullptr)
|
||||
{
|
||||
zerostruct (*info);
|
||||
memcpy (info, (PClassInfoType*) &getClassEntries()[static_cast<size_t> (index)].info2, sizeof (PClassInfoType));
|
||||
return kResultOk;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return kInvalidArgument;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// no leak detector here to prevent it firing on shutdown when running in hosts that
|
||||
// don't release the factory object correctly...
|
||||
JUCE_DECLARE_NON_COPYABLE (JucePluginFactory)
|
||||
RunLoop runLoop;
|
||||
VSTComSmartPtr<Vst::IHostApplication> host;
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue