Add a basic CLAP plugin factory implementation

Which can only list plugins without creating them.
This commit is contained in:
Robbert van der Helm
2022-09-05 17:37:12 +02:00
parent 1339c20fc1
commit c36590abf5
5 changed files with 142 additions and 4 deletions
+6 -3
View File
@@ -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 // This should be the minimum of yabridge's supported CLAP version and
// the plugin's supported CLAP version // the plugin's supported CLAP version
clap_version_t supported_clap_version = 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; 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); features_ptrs.resize(features.size() + 1);
for (size_t i = 0; i < features.size(); i++) { for (size_t i = 0; i < features.size(); i++) {
features_ptrs[i] = features[i].c_str(); features_ptrs[i] = features[i].c_str();
} }
features_ptrs[features.size()] = nullptr; features_ptrs[features.size()] = nullptr;
return clap_plugin_descriptor_t{ clap_descriptor = clap_plugin_descriptor_t{
.clap_version = supported_clap_version, .clap_version = supported_clap_version,
.id = id.c_str(), .id = id.c_str(),
.name = name.c_str(), .name = name.c_str(),
@@ -74,6 +75,8 @@ clap_plugin_descriptor_t descriptor::get() const {
.description = description ? description->c_str() : nullptr, .description = description ? description->c_str() : nullptr,
.features = features_ptrs.data(), .features = features_ptrs.data(),
}; };
return &clap_descriptor;
} }
} // namespace plugin } // namespace plugin
+5 -1
View File
@@ -68,7 +68,7 @@ struct descriptor {
* to this object's fields, so this descriptor is only valid as long as this * to this object's fields, so this descriptor is only valid as long as this
* object is alive and doesn't get moved. * object is alive and doesn't get moved.
*/ */
clap_plugin_descriptor_t get() const; const clap_plugin_descriptor_t* get() const;
template <typename S> template <typename S>
void serialize(S& s) { void serialize(S& s) {
@@ -98,6 +98,10 @@ struct descriptor {
* Populated as part of `get()`. * Populated as part of `get()`.
*/ */
mutable std::vector<const char*> features_ptrs; mutable std::vector<const char*> features_ptrs;
/**
* The CLAP descriptor populated and returned from `get()`.
*/
mutable clap_plugin_descriptor_t clap_descriptor;
}; };
} // namespace plugin } // namespace plugin
@@ -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 <https://www.gnu.org/licenses/>.
#include "plugin-factory-proxy.h"
#include "../clap.h"
clap_plugin_factory_proxy::clap_plugin_factory_proxy(
ClapPluginBridge& bridge,
std::vector<clap::plugin::descriptor> 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<const clap_plugin_factory_proxy*>(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<const clap_plugin_factory_proxy*>(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;
}
@@ -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 <https://www.gnu.org/licenses/>.
#pragma once
#include <vector>
#include <clap/plugin-factory.h>
#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<clap::plugin::descriptor> 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<clap::plugin::descriptor> descriptors_;
};
+1
View File
@@ -80,6 +80,7 @@ if with_clap
'../common/serialization/clap/plugin.cpp', '../common/serialization/clap/plugin.cpp',
'../common/utils.cpp', '../common/utils.cpp',
'../include/llvm/small-vector.cpp', '../include/llvm/small-vector.cpp',
'bridges/clap-impls/plugin-factory-proxy.cpp',
'bridges/clap.cpp', 'bridges/clap.cpp',
'host-process.cpp', 'host-process.cpp',
'utils.cpp', 'utils.cpp',