Add functions for registering CLAP plugin proxies

This commit is contained in:
Robbert van der Helm
2022-09-09 14:51:59 +02:00
parent bacda47671
commit a9bb60772d
6 changed files with 79 additions and 58 deletions
+29
View File
@@ -98,3 +98,32 @@ const void* ClapPluginBridge::get_factory(const char* factory_id) {
return nullptr; return nullptr;
} }
} }
std::pair<clap_plugin_proxy&, std::shared_lock<std::shared_mutex>>
ClapPluginBridge::get_proxy(size_t instance_id) noexcept {
std::shared_lock lock(plugin_proxies_mutex_);
return std::pair<clap_plugin_proxy&, std::shared_lock<std::shared_mutex>>(
*plugin_proxies_.at(instance_id), std::move(lock));
}
void ClapPluginBridge::register_plugin_proxy(
std::unique_ptr<clap_plugin_proxy> plugin_proxy) {
std::unique_lock lock(plugin_proxies_mutex_);
assert(plugin_proxy);
plugin_proxies_.emplace(plugin_proxy->instance_id(),
std::move(plugin_proxy));
// For optimization reaons we use dedicated sockets for functions that will
// be run in the audio processing loop
sockets_.add_audio_thread_and_connect(plugin_proxy->instance_id());
}
void ClapPluginBridge::unregister_plugin_proxy(size_t instance_id) {
std::lock_guard lock(plugin_proxies_mutex_);
plugin_proxies_.erase(instance_id);
sockets_.remove_audio_thread(instance_id);
}
+44 -54
View File
@@ -23,6 +23,7 @@
#include "../../common/logging/clap.h" #include "../../common/logging/clap.h"
#include "../../common/mutual-recursion.h" #include "../../common/mutual-recursion.h"
#include "clap-impls/plugin-factory-proxy.h" #include "clap-impls/plugin-factory-proxy.h"
#include "clap-impls/plugin-proxy.h"
#include "common.h" #include "common.h"
/** /**
@@ -69,45 +70,38 @@ class ClapPluginBridge : PluginBridge<ClapSockets<std::jthread>> {
*/ */
const void* get_factory(const char* factory_id); const void* get_factory(const char* factory_id);
// TODO: /**
// /** * Fetch the plugin proxy instance along with a lock valid for the
// * Fetch the plugin proxy instance along with a lock valid for the * instance's lifetime. This is mostly just to save some boilerplate
// * instance's lifetime. This is mostly just to save some boilerplate * everywhere. Use C++17's structured binding as syntactic sugar to not have
// * everywhere. Use C++17's structured binding as syntactic sugar to not * to deal with the lock handle.
// have */
// * to deal with the lock handle. std::pair<clap_plugin_proxy&, std::shared_lock<std::shared_mutex>>
// */ get_proxy(size_t instance_id) noexcept;
// std::pair<ClapPluginProxyImpl&, std::shared_lock<std::shared_mutex>>
// get_proxy(size_t instance_id) noexcept;
// /** /**
// * Add a `ClapPluginProxyImpl` to the list of registered proxy objects so * Add a `clap_plugin_proxy` to the list of registered plugin proxies so we
// we * can handle host callbacks. This function is called in
// * can handle host callbacks. This function is called in * `clap_plugin_factory_proxy::create()`. This function also connects the
// * `ClapPluginProxyImpl`'s constructor. If the plugin supports the * instance's audio thread socket.
// * `IAudioProcessor` or `IComponent` interfaces, then we'll also connect *
// to * @param proxy_object The proxy object so we can access its host context
// * a dedicated audio processing socket. * and unique instance identifier.
// * *
// * @param proxy_object The proxy object so we can access its host context * @see plugin_proxies_
// * and unique instance identifier. */
// * void register_plugin_proxy(std::unique_ptr<clap_plugin_proxy> plugin_proxy);
// * @see plugin_proxies_
// */
// void register_plugin_proxy(ClapPluginProxyImpl& proxy_object);
// /** /**
// * Remove a previously registered `ClapPluginProxyImpl` from the list of * Remove a previously registered `clap_plugin_proxy` from the list of
// * registered proxy objects. Called during the object's destructor after * registered plugin proxies. Called in `clap_plugin_proxy::destroy()`after
// * asking the Wine plugin host to destroy the component on its side. * asking the Wine plugin host to destroy the component on its side.
// * *
// * @param proxy_object The proxy object so we can access its unique * @param instance_id The instance ID of the proxy that should be removed.
// instance *
// * identifier. * @see plugin_proxies_
// * */
// * @see plugin_proxies_ void unregister_plugin_proxy(size_t instance_id);
// */
// void unregister_plugin_proxy(ClapPluginProxyImpl& proxy_object);
/** /**
* Send a control message to the Wine plugin host and return the response. * Send a control message to the Wine plugin host and return the response.
@@ -212,28 +206,24 @@ class ClapPluginBridge : PluginBridge<ClapSockets<std::jthread>> {
*/ */
std::unique_ptr<clap_plugin_factory_proxy> plugin_factory_; std::unique_ptr<clap_plugin_factory_proxy> plugin_factory_;
// TODO: Implement /**
// /** * Proxies for all CLAP plugin instances we created for this plugin library.
// * All CLAP plugin objects we created from this plugin. We keep track of * These are all keyed by an ID created on the Wine side when initializing
// * these in case the plugin does a host callback, so we can associate * the plugin. That lets us send function calls from the host to the correct
// that * plugin instance, and callbacks from a plugin instance to the correct host
// * call with the exact host context object passed to it during a call to * instance. Instances are added here through a call by
// * `initialize()`. The IDs here are the same IDs as generated by the Wine * `register_plugin_proxy()` in `clap_plugin_factory_proxy::create()`, and
// * plugin host. An instance is added here through a call by * they are removed again by a call to `unregister_plugin_proxy()` in
// * `register_plugin_proxy()` in `ClapPluginProxyImpl`'s constructor, and * `clap_plugin_proxy::destroy()`.
// an */
// * instance is then removed through a call to `unregister_plugin_proxy()` std::unordered_map<size_t, std::unique_ptr<clap_plugin_proxy>>
// in plugin_proxies_;
// * the destructor.
// */
// std::unordered_map<size_t, std::reference_wrapper<ClapPluginProxyImpl>>
// plugin_proxies_;
/** /**
* In theory all object handling is safe iff the host also doesn't do * In theory all object handling is safe iff the host also doesn't do
* anything weird even without locks, but we'll still prevent adding or * anything weird even without locks, but we'll still prevent adding or
* removing instances while accessing other instances at the same time * removing instances while accessing other instances at the same time
* anyways. See `ClapBridge::object_instances_mutex` for more details. * anyways. See `ClapBridge::plugin_instances_mutex_` for more details.
* *
* TODO: At some point replace this with a multiple reader single writer * TODO: At some point replace this with a multiple reader single writer
* lock based by a spinlock. Because this lock is rarely contested * lock based by a spinlock. Because this lock is rarely contested
+2
View File
@@ -77,9 +77,11 @@ if with_clap
'../common/notifications.cpp', '../common/notifications.cpp',
'../common/plugins.cpp', '../common/plugins.cpp',
'../common/process.cpp', '../common/process.cpp',
'../common/serialization/clap/host.cpp',
'../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-proxy.cpp',
'bridges/clap-impls/plugin-factory-proxy.cpp', 'bridges/clap-impls/plugin-factory-proxy.cpp',
'bridges/clap.cpp', 'bridges/clap.cpp',
'host-process.cpp', 'host-process.cpp',
@@ -52,7 +52,7 @@ class clap_host_proxy {
/** /**
* The instance ID of the plugin instance this proxy belongs to. * The instance ID of the plugin instance this proxy belongs to.
*/ */
inline size_t owner_isntance_id() const { return owner_instance_id_; } inline size_t owner_instance_id() const { return owner_instance_id_; }
static const void* CLAP_ABI host_get_extension(const struct clap_host* host, static const void* CLAP_ABI host_get_extension(const struct clap_host* host,
const char* extension_id); const char* extension_id);
+2 -2
View File
@@ -406,7 +406,7 @@ void ClapBridge::register_plugin_instance(
// This instance ID has already been generated because the host proxy has to // This instance ID has already been generated because the host proxy has to
// be created before the plugin instance // be created before the plugin instance
const size_t instance_id = host_proxy->owner_isntance_id(); const size_t instance_id = host_proxy->owner_instance_id();
object_instances_.emplace( object_instances_.emplace(
instance_id, ClapPluginInstance(plugin, std::move(host_proxy))); instance_id, ClapPluginInstance(plugin, std::move(host_proxy)));
@@ -441,7 +441,7 @@ void ClapBridge::register_plugin_instance(
socket_listening_latch.get_future().wait(); socket_listening_latch.get_future().wait();
} }
void ClapBridge::unregister_object_instance(size_t instance_id) { void ClapBridge::unregister_plugin_instance(size_t instance_id) {
sockets_.remove_audio_thread(instance_id); sockets_.remove_audio_thread(instance_id);
// Remove the instance from within the main IO context so // Remove the instance from within the main IO context so
+1 -1
View File
@@ -358,7 +358,7 @@ class ClapBridge : public HostBridge {
* Remove an object from `object_instances_`. Will also tear down the * Remove an object from `object_instances_`. Will also tear down the
* instance's audio thread. * instance's audio thread.
*/ */
void unregister_object_instance(size_t instance_id); void unregister_plugin_instance(size_t instance_id);
/** /**
* The configuration for this instance of yabridge based on the path to the * The configuration for this instance of yabridge based on the path to the