mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Implement CLAP callback requests
This commit is contained in:
@@ -65,5 +65,28 @@ clap_host_proxy::host_request_process(const struct clap_host* host) {
|
|||||||
|
|
||||||
void CLAP_ABI
|
void CLAP_ABI
|
||||||
clap_host_proxy::host_request_callback(const struct clap_host* host) {
|
clap_host_proxy::host_request_callback(const struct clap_host* host) {
|
||||||
// TODO: Implement
|
assert(host && host->host_data);
|
||||||
|
auto self = static_cast<clap_host_proxy*>(host->host_data);
|
||||||
|
|
||||||
|
// TODO: Log
|
||||||
|
|
||||||
|
// Only schedule a `clap_plugin::on_main_thread()` call if we don't already
|
||||||
|
// have a pending one. This limits the number of unnecessarily stacked
|
||||||
|
// calls.
|
||||||
|
bool expected = false;
|
||||||
|
if (self->has_pending_host_callbacks_.compare_exchange_strong(expected,
|
||||||
|
true)) {
|
||||||
|
// We're acquiring a lock on the instance and then move it into the task
|
||||||
|
// to prevent this instance from being removed before this callback has
|
||||||
|
// been run
|
||||||
|
auto instance_lock =
|
||||||
|
self->bridge_.get_instance(self->owner_instance_id());
|
||||||
|
self->bridge_.main_context_.schedule_task(
|
||||||
|
[self, instance_lock = std::move(instance_lock)]() {
|
||||||
|
const auto& [instance, _] = instance_lock;
|
||||||
|
self->has_pending_host_callbacks_.store(false);
|
||||||
|
|
||||||
|
instance.plugin->on_main_thread(instance.plugin.get());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <clap/host.h>
|
#include <clap/host.h>
|
||||||
|
|
||||||
#include "../../common/serialization/clap/plugin-factory.h"
|
#include "../../common/serialization/clap/plugin-factory.h"
|
||||||
@@ -78,4 +80,12 @@ class clap_host_proxy {
|
|||||||
* the start of the struct and directly casting the `clap_host_t*`.
|
* the start of the struct and directly casting the `clap_host_t*`.
|
||||||
*/
|
*/
|
||||||
const clap_host_t host_vtable_;
|
const clap_host_t host_vtable_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of whether there are pending host callbacks. Used to prevent
|
||||||
|
* calling `clap_plugin::on_main_thread()` multiple times in a row when the
|
||||||
|
* plugin calls `clap_host::request_callback()` multiple times before
|
||||||
|
* `clap_plugin::on_main_thread()` is called.
|
||||||
|
*/
|
||||||
|
std::atomic_bool has_pending_host_callbacks_ = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -306,10 +306,6 @@ void ClapBridge::close_sockets() {
|
|||||||
sockets_.close();
|
sockets_.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ClapBridge::generate_instance_id() noexcept {
|
|
||||||
return current_instance_id_.fetch_add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<ClapPluginInstance&, std::shared_lock<std::shared_mutex>>
|
std::pair<ClapPluginInstance&, std::shared_lock<std::shared_mutex>>
|
||||||
ClapBridge::get_instance(size_t instance_id) noexcept {
|
ClapBridge::get_instance(size_t instance_id) noexcept {
|
||||||
std::shared_lock lock(object_instances_mutex_);
|
std::shared_lock lock(object_instances_mutex_);
|
||||||
@@ -318,6 +314,10 @@ ClapBridge::get_instance(size_t instance_id) noexcept {
|
|||||||
object_instances_.at(instance_id), std::move(lock));
|
object_instances_.at(instance_id), std::move(lock));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ClapBridge::generate_instance_id() noexcept {
|
||||||
|
return current_instance_id_.fetch_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement audio processing
|
// TODO: Implement audio processing
|
||||||
// std::optional<AudioShmBuffer::Config> ClapBridge::setup_shared_audio_buffers(
|
// std::optional<AudioShmBuffer::Config> ClapBridge::setup_shared_audio_buffers(
|
||||||
// size_t instance_id) {
|
// size_t instance_id) {
|
||||||
|
|||||||
@@ -305,6 +305,15 @@ class ClapBridge : public HostBridge {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the plugin instance along with a lock valid for the instance's
|
||||||
|
* lifetime. This is mostly just to save some boilerplate everywhere. Use
|
||||||
|
* C++17's structured binding as syntactic sugar to not have to deal with
|
||||||
|
* the lock handle.
|
||||||
|
*/
|
||||||
|
std::pair<ClapPluginInstance&, std::shared_lock<std::shared_mutex>>
|
||||||
|
get_instance(size_t instance_id) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logger instance we'll use to log about failed
|
* A logger instance we'll use to log about failed
|
||||||
* `clap_host::get_extension()` calls, so they can be hidden on verbosity
|
* `clap_host::get_extension()` calls, so they can be hidden on verbosity
|
||||||
@@ -324,15 +333,6 @@ class ClapBridge : public HostBridge {
|
|||||||
*/
|
*/
|
||||||
size_t generate_instance_id() noexcept;
|
size_t generate_instance_id() noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the plugin instance along with a lock valid for the instance's
|
|
||||||
* lifetime. This is mostly just to save some boilerplate everywhere. Use
|
|
||||||
* C++17's structured binding as syntactic sugar to not have to deal with
|
|
||||||
* the lock handle.
|
|
||||||
*/
|
|
||||||
std::pair<ClapPluginInstance&, std::shared_lock<std::shared_mutex>>
|
|
||||||
get_instance(size_t instance_id) noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the shared memory audio buffers for a plugin instance plugin
|
* Sets up the shared memory audio buffers for a plugin instance plugin
|
||||||
* instance and return the configuration so the native plugin can connect to
|
* instance and return the configuration so the native plugin can connect to
|
||||||
|
|||||||
@@ -100,6 +100,13 @@ class HostBridge {
|
|||||||
*/
|
*/
|
||||||
const ghc::filesystem::path plugin_path_;
|
const ghc::filesystem::path plugin_path_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IO context used for event handling so that all events and window
|
||||||
|
* message handling can be performed from a single thread, even when hosting
|
||||||
|
* multiple plugins.
|
||||||
|
*/
|
||||||
|
MainContext& main_context_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Used as part of the watchdog that shuts down a plugin when the remote
|
* Used as part of the watchdog that shuts down a plugin when the remote
|
||||||
@@ -109,13 +116,6 @@ class HostBridge {
|
|||||||
*/
|
*/
|
||||||
virtual void close_sockets() = 0;
|
virtual void close_sockets() = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* The IO context used for event handling so that all events and window
|
|
||||||
* message handling can be performed from a single thread, even when hosting
|
|
||||||
* multiple plugins.
|
|
||||||
*/
|
|
||||||
MainContext& main_context_;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logger, just like we have on the plugin side. This is normally not
|
* A logger, just like we have on the plugin side. This is normally not
|
||||||
* needed because we can just print to STDERR, but this way we can
|
* needed because we can just print to STDERR, but this way we can
|
||||||
|
|||||||
Reference in New Issue
Block a user