From af77d45877f0a9640bba526c6fba5c628ad0ca95 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm <mail@robbertvanderhelm.nl> Date: Mon, 28 Feb 2022 20:39:15 +0100 Subject: [PATCH] Add a Send+Sync wrapper for CLAP object pointers We'll need this for the extensions. --- src/wrapper/clap.rs | 1 + src/wrapper/clap/plugin.rs | 13 ++++++------- src/wrapper/clap/util.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 src/wrapper/clap/util.rs diff --git a/src/wrapper/clap.rs b/src/wrapper/clap.rs index 8edfefa3..884b44d8 100644 --- a/src/wrapper/clap.rs +++ b/src/wrapper/clap.rs @@ -2,6 +2,7 @@ mod context; mod descriptor; mod factory; mod plugin; +mod util; /// Re-export for the wrapper. pub use self::factory::Factory; diff --git a/src/wrapper/clap/plugin.rs b/src/wrapper/clap/plugin.rs index a6f63795..7f56bff4 100644 --- a/src/wrapper/clap/plugin.rs +++ b/src/wrapper/clap/plugin.rs @@ -13,6 +13,7 @@ use std::thread::{self, ThreadId}; use super::context::WrapperProcessContext; use super::descriptor::PluginDescriptor; +use super::util::ClapPtr; use crate::event_loop::{EventLoop, MainThreadExecutor, TASK_QUEUE_CAPACITY}; use crate::plugin::{BufferConfig, BusConfig, ClapPlugin}; use crate::NoteEvent; @@ -43,7 +44,7 @@ pub struct Wrapper<P: ClapPlugin> { /// TODO: Implement the latency extension. pub current_latency: AtomicU32, - host_callback: HostCallback, + host_callback: ClapPtr<clap_host>, /// Needs to be boxed because the plugin object is supposed to contain a static reference to /// this. plugin_descriptor: Box<PluginDescriptor<P>>, @@ -88,8 +89,8 @@ impl<P: ClapPlugin> EventLoop<Task, Wrapper<P>> for Wrapper<P> { let success = self.tasks.push(task).is_ok(); if success { // CLAP lets us use the host's event loop instead of having to implement our own - let host = self.host_callback.0; - unsafe { ((*host).request_callback)(host) }; + let host = &self.host_callback; + unsafe { (host.request_callback)(&**host) }; } success @@ -108,13 +109,11 @@ impl<P: ClapPlugin> MainThreadExecutor<Task> for Wrapper<P> { } } -unsafe impl Send for HostCallback {} -unsafe impl Sync for HostCallback {} - impl<P: ClapPlugin> Wrapper<P> { pub fn new(host_callback: *const clap_host) -> Self { let plugin_descriptor = Box::new(PluginDescriptor::default()); + assert!(!host_callback.is_null()); Self { clap_plugin: clap_plugin { // This needs to live on the heap because the plugin object contains a direct @@ -145,7 +144,7 @@ impl<P: ClapPlugin> Wrapper<P> { input_events: RwLock::new(VecDeque::with_capacity(512)), current_latency: AtomicU32::new(0), - host_callback: HostCallback(host_callback), + host_callback: unsafe { ClapPtr::new(host_callback) }, plugin_descriptor, tasks: ArrayQueue::new(TASK_QUEUE_CAPACITY), diff --git a/src/wrapper/clap/util.rs b/src/wrapper/clap/util.rs new file mode 100644 index 00000000..6c36caf5 --- /dev/null +++ b/src/wrapper/clap/util.rs @@ -0,0 +1,28 @@ +use std::ops::Deref; + +/// Send+Sync wrapper around CLAP host extension pointers. +pub struct ClapPtr<T> { + inner: *const T, +} + +impl<T> Deref for ClapPtr<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { &*self.inner } + } +} + +unsafe impl<T> Send for ClapPtr<T> {} +unsafe impl<T> Sync for ClapPtr<T> {} + +impl<T> ClapPtr<T> { + /// Create a wrapper around a CLAP object pointer. + /// + /// # Safety + /// + /// The pointer must point to a valid object with a lifetime that exceeds this object. + pub unsafe fn new(ptr: *const T) -> Self { + Self { inner: ptr } + } +}