Add conversions for the garbled UIDs

We'll need this to make sure the reported class IDs match up with the
actual IDs.
This commit is contained in:
Robbert van der Helm
2021-01-22 13:31:09 +01:00
parent 29410e3992
commit 249b82f846
4 changed files with 129 additions and 17 deletions
+45
View File
@@ -66,6 +66,51 @@ const Steinberg::Vst::TChar* u16string_to_tchar_pointer(
#endif
}
WineUID::WineUID() {}
WineUID::WineUID(const Steinberg::TUID& tuid) : uid(std::to_array(tuid)) {}
ArrayUID WineUID::get_native_uid() const {
// We need to shuffle the first 8 bytes around to convert between the
// COM-compatible and non COM-compatible formats described by the
// `INLINE_UID` macro. See that macro as a reference for the transformations
// we're applying here.
ArrayUID converted_uid = uid;
converted_uid[0] = uid[3];
converted_uid[1] = uid[2];
converted_uid[2] = uid[1];
converted_uid[3] = uid[0];
converted_uid[4] = uid[5];
converted_uid[5] = uid[4];
converted_uid[6] = uid[7];
converted_uid[7] = uid[6];
return converted_uid;
}
NativeUID::NativeUID() {}
NativeUID::NativeUID(const Steinberg::TUID& tuid) : uid(std::to_array(tuid)) {}
ArrayUID NativeUID::get_wine_uid() const {
// This transformation is actually the same as the one in
// `WineUID::get_native_uid()`, but we'll spell it out here in full for
// understandability's sake.
ArrayUID converted_uid = uid;
converted_uid[0] = uid[3];
converted_uid[1] = uid[2];
converted_uid[2] = uid[1];
converted_uid[3] = uid[0];
converted_uid[4] = uid[5];
converted_uid[5] = uid[4];
converted_uid[6] = uid[7];
converted_uid[7] = uid[6];
return converted_uid;
}
UniversalTResult::UniversalTResult() : universal_result(Value::kResultFalse) {}
UniversalTResult::UniversalTResult(tresult native_result)
+77 -9
View File
@@ -20,6 +20,7 @@
#include <string>
#include <vector>
#include <bitsery/traits/array.h>
#include <pluginterfaces/base/ftypes.h>
#include <pluginterfaces/base/funknown.h>
#include <pluginterfaces/vst/vsttypes.h>
@@ -31,15 +32,6 @@ using Steinberg::TBool, Steinberg::char16, Steinberg::int8, Steinberg::int16,
Steinberg::int32, Steinberg::int64, Steinberg::uint8, Steinberg::uint16,
Steinberg::uint32, Steinberg::uint64, Steinberg::tresult;
/**
* Both `TUID` (`int8_t[16]`) and `FIDString` (`char*`) are hard to work with
* because you can't just copy them. So when serializing/deserializing them
* we'll use `std::array`.
*/
using ArrayUID = std::array<
std::remove_reference_t<decltype(std::declval<Steinberg::TUID>()[0])>,
std::extent_v<Steinberg::TUID>>;
/**
* The maximum number of speakers or busses we support.
*/
@@ -86,6 +78,82 @@ struct Ack {
void serialize(S&) {}
};
/**
* Both `TUID` (`int8_t[16]`) and `FIDString` (`char*`) are hard to work with
* because you can't just copy them. So when serializing/deserializing them
* we'll use `std::array`.
*
* FIXME: Replace usages of ArrayUID everywhere with either `WineUID` or
* `NativeUID`
*/
using ArrayUID = std::array<
std::remove_reference_t<decltype(std::declval<Steinberg::TUID>()[0])>,
std::extent_v<Steinberg::TUID>>;
/**
* Store a serializable UID in the format used on the Wine host. This then has
* to be converted to the correct native format on the plugin side.
*
* NOTE: This is crucial. The `INLINE_UID` macro from the VST3 SDK uses
* different byte ordering on Windows (with COM support) versus on other
* platforms. We need to reverse this transformation manually in order for
* projects with the Windows VST3 version of plugin X, the Linux VST3
* version of plugin X, and the Windows VST3 version of plugin X running
* through yabridge to be compatible.
*/
class WineUID {
public:
WineUID();
WineUID(const Steinberg::TUID& tuid);
ArrayUID get_native_uid() const;
template <typename S>
void serialize(S& s) {
s.container1b(uid);
}
protected:
ArrayUID uid;
};
/**
* Store a serializable UID in the 'real' format as used by the Windows version
* of the VST3 plugin on Windows and the Linux version of the same plugin on
* Linux. This then has to be converted to the format reported by the plugin on
* the Wine host.
*
* NOTE: This is crucial. The `INLINE_UID` macro from the VST3 SDK uses
* different byte ordering on Windows (with COM support) versus on other
* platforms. We need to reverse this transformation manually in order for
* projects with the Windows VST3 version of plugin X, the Linux VST3
* version of plugin X, and the Windows VST3 version of plugin X running
* through yabridge to be compatible.
*/
class NativeUID {
public:
NativeUID();
NativeUID(const Steinberg::TUID& tuid);
/**
* Convert to the garbled byte order used in the Wine plugin host.
*/
ArrayUID get_wine_uid() const;
/**
* Get a reference to the proper native UID.
*/
inline const ArrayUID& native_uid() const { return uid; };
template <typename S>
void serialize(S& s) {
s.container1b(uid);
}
protected:
ArrayUID uid;
};
/**
* A simple wrapper around primitive values for serialization purposes. Bitsery
* doesn't seem to like serializing plain primitives using `s.object()` even if
@@ -25,13 +25,6 @@ YaPluginFactory::ConstructArgs::ConstructArgs() {}
YaPluginFactory::ConstructArgs::ConstructArgs(
Steinberg::IPtr<Steinberg::IPluginFactory> factory) {
// FIXME: The class IDs are incorrect! See the `INLINE_UID` macro. We need
// to shuffle the byte orders around for plugins to be compatible
// with projects saved under Windows and with native Linux versions
// of the same plugin.
// FIXME: We need to do similar translations everywhere where we encounter
// `ArrayUID`, such as `IComponent::getControllerClassId()`
// `IPluginFactory::getFactoryInfo`
if (Steinberg::PFactoryInfo info;
factory->getFactoryInfo(&info) == Steinberg::kResultOk) {
@@ -131,6 +124,13 @@ tresult PLUGIN_API YaPluginFactory::getClassInfo(Steinberg::int32 index,
return Steinberg::kInvalidArgument;
}
// FIXME: The class IDs are incorrect! See the `INLINE_UID` macro. We need
// to shuffle the byte orders around for plugins to be compatible
// with projects saved under Windows and with native Linux versions
// of the same plugin. We need to do this transformation for all of
// these functions
// FIXME: We need to do similar translations everywhere where we encounter
// `ArrayUID`, such as `IComponent::getControllerClassId()`
if (arguments.class_infos_1[index]) {
*info = *arguments.class_infos_1[index];
return Steinberg::kResultOk;
@@ -17,7 +17,6 @@
#pragma once
#include <bitsery/ext/std_optional.h>
#include <bitsery/traits/array.h>
#include <pluginterfaces/vst/ivstcomponent.h>
#include "../../../bitsery/ext/vst3.h"