Add serialization for enumerating CLAP factories

This commit is contained in:
Robbert van der Helm
2022-08-30 17:03:03 +02:00
parent 653a3a88cb
commit edc0cbbe38
2 changed files with 291 additions and 0 deletions
+1
View File
@@ -22,6 +22,7 @@
#include "../bitsery/ext/message-reference.h"
#include "../utils.h"
#include "clap/plugin-factory.h"
#include "common.h"
// The CLAP communication strategy is identical to what we do for VST3.
@@ -0,0 +1,290 @@
// yabridge: a Wine plugin bridge
// Copyright (C) 2020-2022 Robbert van der Helm
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include "plugin.h"
// Serialization messages for `clap/plugin-factory.h`
namespace clap {
namespace plugin_factory {
/**
* The response to the `clap::plugin_factory::list` message defined below.
*/
struct list_response {
std::vector<clap::plugin::descriptor> descriptors;
template <typename S>
void serialize(S& s) {
s.container(descriptors, 8192);
}
};
/**
* Message combining `clap_plugin_factory::count()` with
* `clap_plugin_factory::get()` to get all plugin descriptors in one go.
*/
struct list {
using Response = list_response;
// Since we send this to a specific CLAP plugin library, there are no
// parameters here
template <typename S>
void serialize(S&) {}
};
} // namespace plugin_factory
} // namespace clap
// #include <bitsery/traits/string.h>
// #include <pluginterfaces/base/ipluginbase.h>
// #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<Steinberg::FUnknown> 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<Steinberg::PFactoryInfo> 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<std::optional<Steinberg::PClassInfo>> class_infos_1;
// /**
// * For `IPluginFactory2::getClassInfo2`, works the same way as the
// * above.
// */
// std::vector<std::optional<Steinberg::PClassInfo2>> class_infos_2;
// /**
// * For `IPluginFactory3::getClassInfoUnicode`, works the same way as
// the
// * above.
// */
// std::vector<std::optional<Steinberg::PClassInfoW>>
// class_infos_unicode;
// template <typename S>
// 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<Steinberg::PClassInfo>& info)
// {
// s.ext(info, bitsery::ext::InPlaceOptional{});
// });
// s.container(class_infos_2, 2048,
// [](S& s, std::optional<Steinberg::PClassInfo2>& info)
// {
// s.ext(info, bitsery::ext::InPlaceOptional{});
// });
// s.container(class_infos_unicode, 2048,
// [](S& s, std::optional<Steinberg::PClassInfoW>& 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 <typename S>
// 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 <typename S>
// 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 <typename S>
// 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 <typename S>
// 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<wchar_t>::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 <typename S>
// 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