mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Add a way to run functions on host main thread
From the plugin side.
This commit is contained in:
@@ -39,7 +39,10 @@ clap_plugin_proxy::clap_plugin_proxy(ClapPluginBridge& bridge,
|
||||
.get_extension = plugin_get_extension,
|
||||
.on_main_thread = plugin_on_main_thread,
|
||||
}),
|
||||
host_(host) {}
|
||||
host_(host),
|
||||
// These function objects are relatively large, and we probably won't be
|
||||
// getting that many of them
|
||||
pending_callbacks_(128) {}
|
||||
|
||||
bool CLAP_ABI clap_plugin_proxy::plugin_init(const struct clap_plugin* plugin) {
|
||||
assert(plugin && plugin->plugin_data);
|
||||
@@ -153,7 +156,12 @@ clap_plugin_proxy::plugin_get_extension(const struct clap_plugin* plugin,
|
||||
void CLAP_ABI
|
||||
clap_plugin_proxy::plugin_on_main_thread(const struct clap_plugin* plugin) {
|
||||
assert(plugin && plugin->plugin_data);
|
||||
auto self = static_cast<const clap_plugin_proxy*>(plugin->plugin_data);
|
||||
auto self = static_cast<clap_plugin_proxy*>(plugin->plugin_data);
|
||||
|
||||
// TODO: Use this for spooling main thread callbacks
|
||||
// Functions are pushed to this queue so they can be run on the host's main
|
||||
// thread
|
||||
HostCallback callback;
|
||||
while (self->pending_callbacks_.try_pop(callback)) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <future>
|
||||
#include <vector>
|
||||
|
||||
#include <clap/plugin.h>
|
||||
#include <rigtorp/MPMCQueue.h>
|
||||
#include <function2/function2.hpp>
|
||||
|
||||
#include "../../common/serialization/clap/plugin.h"
|
||||
|
||||
@@ -30,6 +33,17 @@ class ClapPluginBridge;
|
||||
*/
|
||||
class clap_plugin_proxy {
|
||||
public:
|
||||
/**
|
||||
* A function that can be called on the host's main thread through a
|
||||
* combination of `clap_host::request_callback()` and
|
||||
* `clap_plugin::on_main_thread()`. This is identical to
|
||||
* `fu2::unique_function<void()>` except that it doesn't throw and is
|
||||
* noexcept move assignable. That is a requirement for using these in the
|
||||
* MPMC queue.
|
||||
*/
|
||||
using HostCallback = fu2::
|
||||
function_base<true, false, fu2::capacity_default, false, true, void()>;
|
||||
|
||||
/**
|
||||
* Construct a proxy for a plugin that has already been created on the Wine
|
||||
* side. This is done in our `clap_plugin_factory::create()` implementation.
|
||||
@@ -53,6 +67,7 @@ class clap_plugin_proxy {
|
||||
inline const clap_plugin_t* plugin_vtable() const {
|
||||
return &plugin_vtable_;
|
||||
}
|
||||
|
||||
/**
|
||||
* The instance ID of the plugin instance this proxy belongs to.
|
||||
*/
|
||||
@@ -78,6 +93,34 @@ class clap_plugin_proxy {
|
||||
static void CLAP_ABI
|
||||
plugin_on_main_thread(const struct clap_plugin* plugin);
|
||||
|
||||
/**
|
||||
* Asynchronously run a function on the host's main thread, returning the
|
||||
* result as a future.
|
||||
*/
|
||||
template <std::invocable F>
|
||||
std::future<std::invoke_result_t<F>> run_on_main_thread(F&& fn) {
|
||||
using Result = std::invoke_result_t<F>;
|
||||
|
||||
std::promise<Result> response_promise{};
|
||||
std::future<Result> response_future = response_promise.get_future();
|
||||
pending_callbacks_.push(HostCallback(
|
||||
[fn = std::forward<F>(fn),
|
||||
response_promise = std::move(response_promise)]() mutable {
|
||||
if constexpr (std::is_void_v<Result>) {
|
||||
fn();
|
||||
response_promise.set_value();
|
||||
} else {
|
||||
response_promise.set_value(fn());
|
||||
}
|
||||
}));
|
||||
|
||||
// In theory the host will now call `clap_plugin::on_main_thread()`,
|
||||
// where we can pop the function from the queue
|
||||
host_->request_callback(host_);
|
||||
|
||||
return response_future;
|
||||
}
|
||||
|
||||
private:
|
||||
ClapPluginBridge& bridge_;
|
||||
size_t instance_id_;
|
||||
@@ -102,4 +145,10 @@ class clap_plugin_proxy {
|
||||
* by the proxied plugin instance must go through ere.
|
||||
*/
|
||||
const clap_host_t* host_;
|
||||
|
||||
/**
|
||||
* Pending callbacks that must be sent to the host on the main thread. If a
|
||||
* socket needs to make a main thread function call, it will
|
||||
*/
|
||||
rigtorp::MPMCQueue<HostCallback> pending_callbacks_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user