From 1b804bd5ea4485cb204e40d476ef54801b1ecb38 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Fri, 22 Jan 2021 14:24:40 +0100 Subject: [PATCH] :boom: Convert between UID formats for class IDs This is a breaking change. Old projects containing VST3 plugins running through yabridge will no longer work without modifications. I'll write some scripts to convert the class IDs stored in those project files soon a migration path. The UIDs reported by the plugin were apparently wrong, which meant that the native Linux VST3 version of plugin X and the normal Windows VST3 version of plugin X used different class ideas than the Windows VST3 version of plugin X running through yabridge. Those things are supposed to be compatible, so we sadly needed to make this change at some point. --- src/common/logging/vst3.cpp | 3 ++- .../serialization/vst3/plugin-factory.cpp | 21 +++++++++++++++++++ .../serialization/vst3/plugin-factory.h | 6 ++++++ src/common/serialization/vst3/plugin-proxy.h | 4 ++-- .../bridges/vst3-impls/plugin-factory.cpp | 4 ++-- src/wine-host/bridges/vst3.cpp | 4 +++- 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index 2e4b5342..a8c197a7 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -79,7 +79,8 @@ bool Vst3Logger::log_request(bool is_host_vst, const Vst3PluginProxy::Construct& request) { return log_request_base(is_host_vst, [&](auto& message) { message << "IPluginFactory::createInstance(cid = " - << format_uid(Steinberg::FUID::fromTUID(request.cid.data())) + << format_uid(Steinberg::FUID::fromTUID( + request.cid.native_uid().data())) << ", _iid = "; switch (request.requested_interface) { case Vst3PluginProxy::Construct::Interface::IComponent: diff --git a/src/common/serialization/vst3/plugin-factory.cpp b/src/common/serialization/vst3/plugin-factory.cpp index 64307b42..c9413725 100644 --- a/src/common/serialization/vst3/plugin-factory.cpp +++ b/src/common/serialization/vst3/plugin-factory.cpp @@ -38,6 +38,13 @@ YaPluginFactory::ConstructArgs::ConstructArgs( Steinberg::PClassInfo info; if (factory->getClassInfo(i, &info) == Steinberg::kResultOk) { class_infos_1[i] = info; + + // NOTE: We'll need to do a byte order conversion to the reported + // class IDs match up with native and 'real' Windows VST3 + // plugins. See `WineUID` for more information. + ArrayUID native_uid = WineUID(info.cid).get_native_uid(); + std::copy(native_uid.begin(), native_uid.end(), + class_infos_1[i]->cid); } } @@ -53,6 +60,13 @@ YaPluginFactory::ConstructArgs::ConstructArgs( Steinberg::PClassInfo2 info; if (factory2->getClassInfo2(i, &info) == Steinberg::kResultOk) { class_infos_2[i] = info; + + // NOTE: We'll need to do a byte order conversion to the reported + // class IDs match up with native and 'real' Windows VST3 + // plugins. See `WineUID` for more information. + ArrayUID native_uid = WineUID(info.cid).get_native_uid(); + std::copy(native_uid.begin(), native_uid.end(), + class_infos_1[i]->cid); } } @@ -68,6 +82,13 @@ YaPluginFactory::ConstructArgs::ConstructArgs( Steinberg::PClassInfoW info; if (factory3->getClassInfoUnicode(i, &info) == Steinberg::kResultOk) { class_infos_unicode[i] = info; + + // NOTE: We'll need to do a byte order conversion to the reported + // class IDs match up with native and 'real' Windows VST3 + // plugins. See `WineUID` for more information. + ArrayUID native_uid = WineUID(info.cid).get_native_uid(); + std::copy(native_uid.begin(), native_uid.end(), + class_infos_1[i]->cid); } } } diff --git a/src/common/serialization/vst3/plugin-factory.h b/src/common/serialization/vst3/plugin-factory.h index baa0c62a..f472f80c 100644 --- a/src/common/serialization/vst3/plugin-factory.h +++ b/src/common/serialization/vst3/plugin-factory.h @@ -29,6 +29,8 @@ /** * Wraps around `IPluginFactory{1,2,3}` for serialization purposes. See * `docs/vst3.md` for more information on how this works. + * + * TODO: Redo this in the new 'Vst3PluginFactoryProxy' style */ class YaPluginFactory : public Steinberg::IPluginFactory3 { public: @@ -70,6 +72,10 @@ class YaPluginFactory : public Steinberg::IPluginFactory3 { * info versions if the plugin can provide them since we don't know * which version of the interface the host will use. Will be * `std::nullopt` if the plugin doesn't return a class info. + * + * NOTE: We'll have already converted all returned class IDs to native + * class IDs using `WienUID::to_native_uid()` for cross-platform + * compatibility. This applies to all `class_info_*` fields here. */ std::vector> class_infos_1; diff --git a/src/common/serialization/vst3/plugin-proxy.h b/src/common/serialization/vst3/plugin-proxy.h index e3b121aa..06eb6adb 100644 --- a/src/common/serialization/vst3/plugin-proxy.h +++ b/src/common/serialization/vst3/plugin-proxy.h @@ -173,7 +173,7 @@ class Vst3PluginProxy : public YaAudioPresentationLatency, struct Construct { using Response = std::variant; - ArrayUID cid; + NativeUID cid; /** * The interface the host was trying to instantiate an object for. @@ -189,7 +189,7 @@ class Vst3PluginProxy : public YaAudioPresentationLatency, template void serialize(S& s) { - s.container1b(cid); + s.object(cid); s.value4b(requested_interface); } }; diff --git a/src/plugin/bridges/vst3-impls/plugin-factory.cpp b/src/plugin/bridges/vst3-impls/plugin-factory.cpp index 7e92d942..ec411279 100644 --- a/src/plugin/bridges/vst3-impls/plugin-factory.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-factory.cpp @@ -35,8 +35,8 @@ YaPluginFactoryImpl::createInstance(Steinberg::FIDString cid, return Steinberg::kInvalidArgument; } - ArrayUID cid_array; - std::copy(cid, cid + std::extent_v, cid_array.begin()); + Steinberg::TUID cid_array; + std::copy(cid, cid + std::extent_v, cid_array); // FIXME: `_iid` in Bitwig Studio 3.3.1 is not null terminated, and the // comparison below will thus fail since the strings have different diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 932e95ef..e0465a0a 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -120,7 +120,9 @@ void Vst3Bridge::run() { [&](const Vst3PluginProxy::Construct& request) -> Vst3PluginProxy::Construct::Response { Steinberg::TUID cid; - std::copy(request.cid.begin(), request.cid.end(), cid); + + ArrayUID wine_cid = request.cid.get_wine_uid(); + std::copy(wine_cid.begin(), wine_cid.end(), cid); // Even though we're requesting a specific interface (to mimic // what the host is doing), we're immediately upcasting it to an