diff --git a/src/common/serialization/clap/README.md b/src/common/serialization/clap/README.md index a509462a..0c739ec9 100644 --- a/src/common/serialization/clap/README.md +++ b/src/common/serialization/clap/README.md @@ -12,12 +12,6 @@ Yabridge currently tracks CLAP 1.1.1. The implementation status for CLAP's core | `clap.plugin-factory` | :heavy_check_mark: | | `clap.plugin-invalidation-factory/draft0` | :x: Not supported yet | -| extension | status | -| ----------------------------------------- | --------------------- | -| Core plugin and host functionality | :x: Work in progress | -| `clap.plugin-factory` | :x: Work in progress | -| `clap.plugin-invalidation-factory/draft0` | :x: Not supported yet | - | extension | status | | ------------------------- | --------------------- | | `clap.audio-ports` | :x: Not supported yet | diff --git a/src/common/serialization/clap/plugin-factory.h b/src/common/serialization/clap/plugin-factory.h index 72757ad5..227e923a 100644 --- a/src/common/serialization/clap/plugin-factory.h +++ b/src/common/serialization/clap/plugin-factory.h @@ -16,6 +16,8 @@ #pragma once +#include "../common.h" +#include "host.h" #include "plugin.h" // Serialization messages for `clap/plugin-factory.h` @@ -24,7 +26,7 @@ namespace clap { namespace plugin_factory { /** - * The response to the `clap::plugin_factory::list` message defined below. + * The response to the `clap::plugin_factory::List` message defined below. */ struct ListResponse { /** @@ -54,243 +56,47 @@ struct List { void serialize(S&) {} }; +/** + * The response to the `clap::plugin_factory::Create` message defined below. + */ +struct CreateResponse { + /** + * The new plugin instance's ID, if it was initialized correctly. We'll + * assume the instance's plugin descriptor is the same as the one from the + * factory. + */ + std::optional instance_id; + + template + void serialize(S& s) { + s.ext(instance_id, bitsery::ext::InPlaceOptional{}, + [](S& s, auto& v) { s.value8b(v); }); + } +}; + +/** + * Message struct for `clap_plugin_factory::create()`. Contains information + * about the host for the `clap_host_t*`. If the plugin instance was created + * successfully, then the Wine host side will generate a unique identifier for + * the instance that is used to refer to it in further messages. + */ +struct Create { + using Response = CreateResponse; + + /** + * Information about the native host that can be used to construct a + * `clap_host_t*` proxy. + */ + clap::host::Host host; + + std::string plugin_id; + + template + void serialize(S& s) { + s.object(host); + s.text1b(plugin_id, 4096); + } +}; + } // namespace plugin_factory } // namespace clap - -// #include -// #include - -// #include "../../../bitsery/ext/in-place-optional.h" -// #include "../base.h" -// #include "../host-context-proxy.h" - -// #pragma GCC diagnostic push -// #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" - -// /** -// * Wraps around `IPluginFactory{1,2,3}` for serialization purposes. This is -// * instantiated as part of `Vst3PluginFactoryProxy`. -// */ -// class YaPluginFactory3 : public Steinberg::IPluginFactory3 { -// public: -// /** -// * These are the arguments for creating a `YaPluginFactory3`. All class -// * infos in all available formats are read from the plugin so the host -// can -// * query them. -// */ -// struct ConstructArgs { -// ConstructArgs() noexcept; - -// /** -// * Check whether an existing implementation implements -// * `IPluginFactory1`, `IPluginFactory2`, and ``IPluginFactory3`` and -// * read arguments from it. -// */ -// ConstructArgs(Steinberg::IPtr object); - -// /** -// * Whether the object supported `IPluginFactory`. -// */ -// bool supports_plugin_factory = false; - -// /** -// * Whether the object supported `IPluginFactory2`. -// */ -// bool supports_plugin_factory_2 = false; - -// /** -// * Whether the object supported `IPluginFactory3`. -// */ -// bool supports_plugin_factory_3 = false; - -// /** -// * For `IPluginFactory::getFactoryInfo`. -// */ -// std::optional factory_info; - -// /** -// * For `IPluginFactory::countClasses`. -// */ -// int num_classes; - -// /** -// * For `IPluginFactory::getClassInfo`. We need to store all four -// class -// * 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 `WineUID::to_native_uid()` for -// cross-platform -// * compatibility. This applies to all `class_info_*` fields -// here. -// */ -// std::vector> class_infos_1; - -// /** -// * For `IPluginFactory2::getClassInfo2`, works the same way as the -// * above. -// */ -// std::vector> class_infos_2; - -// /** -// * For `IPluginFactory3::getClassInfoUnicode`, works the same way as -// the -// * above. -// */ -// std::vector> -// class_infos_unicode; - -// template -// void serialize(S& s) { -// s.value1b(supports_plugin_factory); -// s.value1b(supports_plugin_factory_2); -// s.value1b(supports_plugin_factory_3); -// s.ext(factory_info, bitsery::ext::InPlaceOptional{}); -// s.value4b(num_classes); -// s.container(class_infos_1, 2048, -// [](S& s, std::optional& info) -// { -// s.ext(info, bitsery::ext::InPlaceOptional{}); -// }); -// s.container(class_infos_2, 2048, -// [](S& s, std::optional& info) -// { -// s.ext(info, bitsery::ext::InPlaceOptional{}); -// }); -// s.container(class_infos_unicode, 2048, -// [](S& s, std::optional& info) -// { -// s.ext(info, bitsery::ext::InPlaceOptional{}); -// }); -// } -// }; - -// /** -// * Instantiate this instance with arguments read from the Windows VST3 -// * plugin's plugin factory. -// */ -// YaPluginFactory3(ConstructArgs&& args) noexcept; - -// virtual ~YaPluginFactory3() noexcept = default; - -// inline bool supports_plugin_factory() const noexcept { -// return arguments_.supports_plugin_factory; -// } - -// inline bool supports_plugin_factory_2() const noexcept { -// return arguments_.supports_plugin_factory_2; -// } - -// inline bool supports_plugin_factory_3() const noexcept { -// return arguments_.supports_plugin_factory_3; -// } - -// // All of these functiosn returning class information are fetched once on -// // the Wine side since they'll be static so we can just copy over the -// // responses - -// // From `IPluginFactory` -// tresult PLUGIN_API getFactoryInfo(Steinberg::PFactoryInfo* info) -// override; int32 PLUGIN_API countClasses() override; tresult PLUGIN_API -// getClassInfo(Steinberg::int32 index, -// Steinberg::PClassInfo* info) override; -// /** -// * See the implementation in `Vst3PluginFactoryProxyImpl` for how this is -// * handled. We'll create new managed `Vst3PluginProxy` objects from here. -// */ -// virtual tresult PLUGIN_API createInstance(Steinberg::FIDString cid, -// Steinberg::FIDString _iid, -// void** obj) override = 0; - -// // From `IPluginFactory2` -// tresult PLUGIN_API getClassInfo2(int32 index, -// Steinberg::PClassInfo2* info) override; - -// // From `IPluginFactory3` -// tresult PLUGIN_API -// getClassInfoUnicode(int32 index, Steinberg::PClassInfoW* info) override; - -// /** -// * Message to pass through a call to `IPluginFactory3::setHostContext()` -// to -// * the Wine plugin host. A `Vst3HostContextProxy` should be created on -// the -// * Wine plugin host and then passed as an argument to -// * `IPluginFactory3::setHostContext()`. -// */ -// struct SetHostContext { -// using Response = UniversalTResult; - -// Vst3HostContextProxy::ConstructArgs host_context_args; - -// template -// void serialize(S& s) { -// s.object(host_context_args); -// } -// }; - -// virtual tresult PLUGIN_API -// setHostContext(Steinberg::FUnknown* context) override = 0; - -// protected: -// ConstructArgs arguments_; -// }; - -// #pragma GCC diagnostic pop - -// // Serialization functions have to live in the same namespace as the objects -// // they're serializing -// namespace Steinberg { -// template -// void serialize(S& s, PClassInfo& class_info) { -// s.container1b(class_info.cid); -// s.value4b(class_info.cardinality); -// s.text1b(class_info.category); -// s.text1b(class_info.name); -// } - -// template -// void serialize(S& s, PClassInfo2& class_info) { -// s.container1b(class_info.cid); -// s.value4b(class_info.cardinality); -// s.text1b(class_info.category); -// s.text1b(class_info.name); -// s.value4b(class_info.classFlags); -// s.text1b(class_info.subCategories); -// s.text1b(class_info.vendor); -// s.text1b(class_info.version); -// s.text1b(class_info.sdkVersion); -// } - -// template -// void serialize(S& s, PClassInfoW& class_info) { -// s.container1b(class_info.cid); -// s.value4b(class_info.cardinality); -// s.text1b(class_info.category); -// // FIXME: Bitsery uses `std::char_traits::length()` under the hood -// // for `text2b()` on the Wine side, and under winegcc this function -// // this length is incorrect. As a workaround we're just serializing -// // the entire container. This applies to every place where we use -// // `container2b()` to serialize a `String128`, so if we end up fixing -// // this we should replace all of the instances of `container2b()` -// // that serialize a `String128`. -// s.container2b(class_info.name); -// s.value4b(class_info.classFlags); -// s.text1b(class_info.subCategories); -// s.container2b(class_info.vendor); -// s.container2b(class_info.version); -// s.container2b(class_info.sdkVersion); -// } - -// template -// void serialize(S& s, PFactoryInfo& factory_info) { -// s.text1b(factory_info.vendor); -// s.text1b(factory_info.url); -// s.text1b(factory_info.email); -// s.value4b(factory_info.flags); -// } -// } // namespace Steinberg