From b31bee24b6dca53a5c5498a52c58338e18312d1b Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 12 Sep 2022 18:36:02 +0200 Subject: [PATCH] Store plugin and host extension struct pointers --- .../bridges/clap-impls/plugin-proxy.cpp | 12 +++++++ src/plugin/bridges/clap-impls/plugin-proxy.h | 31 ++++++++++++++++++- src/wine-host/bridges/clap.cpp | 21 ++++++++++--- src/wine-host/bridges/clap.h | 12 +++++-- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/plugin/bridges/clap-impls/plugin-proxy.cpp b/src/plugin/bridges/clap-impls/plugin-proxy.cpp index 3508d58a..cea16f37 100644 --- a/src/plugin/bridges/clap-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/clap-impls/plugin-proxy.cpp @@ -18,6 +18,12 @@ #include "../clap.h" +ClapHostExtensions::ClapHostExtensions(const clap_host& host) noexcept + : audio_ports(static_cast( + host.get_extension(&host, CLAP_EXT_AUDIO_PORTS))) {} + +ClapHostExtensions::ClapHostExtensions() noexcept {} + clap_plugin_proxy::clap_plugin_proxy(ClapPluginBridge& bridge, size_t instance_id, clap::plugin::Descriptor descriptor, @@ -52,6 +58,12 @@ bool CLAP_ABI clap_plugin_proxy::plugin_init(const struct clap_plugin* plugin) { assert(plugin && plugin->plugin_data); auto self = static_cast(plugin->plugin_data); + // At this point we are allowed to query the host for extension structs. + // We'll store pointers to the host's extensions vtables, and then send + // whether or not those extensions were supported as booleans to the Wine + // plugin host so it can expose the same interfaces there. + self->extensions_ = ClapHostExtensions(*self->host_); + const clap::plugin::InitResponse response = self->bridge_.send_main_thread_message( clap::plugin::Init{.instance_id = self->instance_id(), diff --git a/src/plugin/bridges/clap-impls/plugin-proxy.h b/src/plugin/bridges/clap-impls/plugin-proxy.h index 3d059fa5..68616215 100644 --- a/src/plugin/bridges/clap-impls/plugin-proxy.h +++ b/src/plugin/bridges/clap-impls/plugin-proxy.h @@ -29,6 +29,29 @@ // Forward declaration to avoid circular includes class ClapPluginBridge; +/** + * Pointers to all of a CLAP host's extension structs. These will be null if the + * host doesn't support the extensions. + * + * @relates clap_plugin_proxy + */ +struct ClapHostExtensions { + /** + * Query all of the host's extensions. This can only be done after the + * call to init. + */ + ClapHostExtensions(const clap_host& host) noexcept; + + /** + * The default constructor that assumes the host doesn't support any + * extensions. We may only query the extensions after the plugin has called + * `clap_plugin::init()`. + */ + ClapHostExtensions() noexcept; + + const clap_host_audio_ports_t* audio_ports = nullptr; +}; + /** * A proxy for a `clap_plugin`. */ @@ -131,10 +154,16 @@ class clap_plugin_proxy { /** * The `clap_host_t*` passed when creating the instance. Any callbacks made - * by the proxied plugin instance must go through ere. + * by the proxied plugin instance must go through here. */ const clap_host_t* host_; + /** + * The host's supported extensions. These will be populated in the + * `clap_plugin::init()` call. + */ + ClapHostExtensions extensions_; + private: ClapPluginBridge& bridge_; size_t instance_id_; diff --git a/src/wine-host/bridges/clap.cpp b/src/wine-host/bridges/clap.cpp index 307362c8..fd1b393e 100644 --- a/src/wine-host/bridges/clap.cpp +++ b/src/wine-host/bridges/clap.cpp @@ -26,16 +26,20 @@ namespace fs = ghc::filesystem; -// TODO: Query extensions in the initializer list -ClapPluginExtensions::ClapPluginExtensions(const clap_plugin& plugin) noexcept { -} +ClapPluginExtensions::ClapPluginExtensions(const clap_plugin& plugin) noexcept + : audio_ports(static_cast( + plugin.get_extension(&plugin, CLAP_EXT_AUDIO_PORTS))) {} + +ClapPluginExtensions::ClapPluginExtensions() noexcept {} ClapPluginInstance::ClapPluginInstance( const clap_plugin* plugin, std::unique_ptr host_proxy) noexcept : host_proxy(std::move(host_proxy)), plugin((assert(plugin), plugin), plugin->destroy), - extensions(*plugin) {} + // We may only query the supported extensions after initializing the + // plugin + extensions() {} ClapBridge::ClapBridge(MainContext& main_context, // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) @@ -223,6 +227,15 @@ void ClapBridge::run() { const bool result = instance.plugin->init(instance.plugin.get()); if (result) { + // At this point we should also get the extension + // pointers for the plugin's supported extensions. + // In addition we'll send whether or not the plugin + // supports these extensions as booleans to the + // native plugin side so we can expose these same + // extensions to the host. + instance.extensions = + ClapPluginExtensions(*instance.plugin); + // This mimics the same behavior we had to implement // for VST2 and VST3. The Win32 message loop is // completely blocked while a plugin instance has diff --git a/src/wine-host/bridges/clap.h b/src/wine-host/bridges/clap.h index 2a8266a5..b311766e 100644 --- a/src/wine-host/bridges/clap.h +++ b/src/wine-host/bridges/clap.h @@ -49,12 +49,18 @@ struct ClapPluginExtensions { /** * Query all of the plugin's extensions. This can only be done after the * call to init. - * - * TODO: Return the supported extensions along with the init call. */ ClapPluginExtensions(const clap_plugin& plugin) noexcept; - // TODO: Supported extensions + /** + * The default constructor that assumes the plugin doesn't support any + * extensions. We may only query the extensions after the plugin has been + * initialized, so this is used when creating the `ClapPluginInstance` + * object. + */ + ClapPluginExtensions() noexcept; + + const clap_plugin_audio_ports_t* audio_ports = nullptr; }; /**