diff --git a/src/common/serialization/clap/plugin.cpp b/src/common/serialization/clap/plugin.cpp index 8485fc12..8f6ddc62 100644 --- a/src/common/serialization/clap/plugin.cpp +++ b/src/common/serialization/clap/plugin.cpp @@ -43,7 +43,7 @@ descriptor::descriptor(const clap_plugin_descriptor_t& original) } } -clap_plugin_descriptor_t descriptor::get() const { +const clap_plugin_descriptor_t* descriptor::get() const { // This should be the minimum of yabridge's supported CLAP version and // the plugin's supported CLAP version clap_version_t supported_clap_version = clap_version; @@ -55,14 +55,15 @@ clap_plugin_descriptor_t descriptor::get() const { supported_clap_version = CLAP_VERSION; } - // `features_ptrs` needs to be populated as envp-style null terminated array + // `features_ptrs` needs to be populated as an envp-style null terminated + // array features_ptrs.resize(features.size() + 1); for (size_t i = 0; i < features.size(); i++) { features_ptrs[i] = features[i].c_str(); } features_ptrs[features.size()] = nullptr; - return clap_plugin_descriptor_t{ + clap_descriptor = clap_plugin_descriptor_t{ .clap_version = supported_clap_version, .id = id.c_str(), .name = name.c_str(), @@ -74,6 +75,8 @@ clap_plugin_descriptor_t descriptor::get() const { .description = description ? description->c_str() : nullptr, .features = features_ptrs.data(), }; + + return &clap_descriptor; } } // namespace plugin diff --git a/src/common/serialization/clap/plugin.h b/src/common/serialization/clap/plugin.h index 23fa8ac9..8a6b4ffc 100644 --- a/src/common/serialization/clap/plugin.h +++ b/src/common/serialization/clap/plugin.h @@ -68,7 +68,7 @@ struct descriptor { * to this object's fields, so this descriptor is only valid as long as this * object is alive and doesn't get moved. */ - clap_plugin_descriptor_t get() const; + const clap_plugin_descriptor_t* get() const; template void serialize(S& s) { @@ -98,6 +98,10 @@ struct descriptor { * Populated as part of `get()`. */ mutable std::vector features_ptrs; + /** + * The CLAP descriptor populated and returned from `get()`. + */ + mutable clap_plugin_descriptor_t clap_descriptor; }; } // namespace plugin diff --git a/src/plugin/bridges/clap-impls/plugin-factory-proxy.cpp b/src/plugin/bridges/clap-impls/plugin-factory-proxy.cpp new file mode 100644 index 00000000..5bdcb734 --- /dev/null +++ b/src/plugin/bridges/clap-impls/plugin-factory-proxy.cpp @@ -0,0 +1,61 @@ +// 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 . + +#include "plugin-factory-proxy.h" + +#include "../clap.h" + +clap_plugin_factory_proxy::clap_plugin_factory_proxy( + ClapPluginBridge& bridge, + std::vector descriptors) + : plugin_factory_vtable(clap_plugin_factory_t{ + .get_plugin_count = plugin_factory_get_plugin_count, + .get_plugin_descriptor = plugin_factory_get_plugin_descriptor, + .create_plugin = plugin_factory_create_plugin, + }), + bridge_(bridge), + descriptors_(std::move(descriptors)){}; + +uint32_t CLAP_ABI clap_plugin_factory_proxy::plugin_factory_get_plugin_count( + const struct clap_plugin_factory* factory) { + assert(factory); + auto self = reinterpret_cast(factory); + + return self->descriptors_.size(); +} + +const clap_plugin_descriptor_t* CLAP_ABI +clap_plugin_factory_proxy::plugin_factory_get_plugin_descriptor( + const struct clap_plugin_factory* factory, + uint32_t index) { + assert(factory); + auto self = reinterpret_cast(factory); + + if (index < self->descriptors_.size()) { + return self->descriptors_[index].get(); + } else { + return nullptr; + } +} + +const clap_plugin_t* CLAP_ABI +clap_plugin_factory_proxy::plugin_factory_create_plugin( + const struct clap_plugin_factory* factory, + const clap_host_t* host, + const char* plugin_id) { + // TODO: Implement + return nullptr; +} diff --git a/src/plugin/bridges/clap-impls/plugin-factory-proxy.h b/src/plugin/bridges/clap-impls/plugin-factory-proxy.h new file mode 100644 index 00000000..d6c343b7 --- /dev/null +++ b/src/plugin/bridges/clap-impls/plugin-factory-proxy.h @@ -0,0 +1,69 @@ +// 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 . + +#pragma once + +#include + +#include + +#include "../../common/serialization/clap/plugin.h" + +// Forward declaration to avoid circular includes +class ClapPluginBridge; + +/** + * A proxy for a plugin's `clap_plugin_factory`. + */ +class clap_plugin_factory_proxy { + public: + /** + * The vtable for `clap_plugin_factory`, requires that this object is never + * moved or copied. This is positioned at the start of the struct so we can + * cast between them (with only a bit of UB). + */ + const clap_plugin_factory_t plugin_factory_vtable; + + /** + * Construct the plugin factory proxy based on the plugin descriptors + * retrieved from a `clap::plugin_factory::ListReponse`. + */ + clap_plugin_factory_proxy( + ClapPluginBridge& bridge, + std::vector descriptors); + + clap_plugin_factory_proxy(const clap_plugin_factory_proxy&) = delete; + clap_plugin_factory_proxy& operator=(const clap_plugin_factory_proxy&) = + delete; + clap_plugin_factory_proxy(clap_plugin_factory_proxy&&) = delete; + clap_plugin_factory_proxy& operator=(clap_plugin_factory_proxy&&) = delete; + + static uint32_t CLAP_ABI + plugin_factory_get_plugin_count(const struct clap_plugin_factory* factory); + static const clap_plugin_descriptor_t* CLAP_ABI + plugin_factory_get_plugin_descriptor( + const struct clap_plugin_factory* factory, + uint32_t index); + static const clap_plugin_t* CLAP_ABI + plugin_factory_create_plugin(const struct clap_plugin_factory* factory, + const clap_host_t* host, + const char* plugin_id); + + private: + ClapPluginBridge& bridge_; + + std::vector descriptors_; +}; diff --git a/src/plugin/meson.build b/src/plugin/meson.build index eaad64c5..bed9eaf3 100644 --- a/src/plugin/meson.build +++ b/src/plugin/meson.build @@ -80,6 +80,7 @@ if with_clap '../common/serialization/clap/plugin.cpp', '../common/utils.cpp', '../include/llvm/small-vector.cpp', + 'bridges/clap-impls/plugin-factory-proxy.cpp', 'bridges/clap.cpp', 'host-process.cpp', 'utils.cpp',