1
0
Fork 0

Take a reference to the component handler

This commit is contained in:
Robbert van der Helm 2022-02-01 16:52:55 +01:00
parent d47aac25a1
commit 223d0c3a90

View file

@ -34,7 +34,8 @@ use vst3_sys::base::{kInvalidArgument, kNoInterface, kResultFalse, kResultOk, tr
use vst3_sys::base::{IBStream, IPluginBase, IPluginFactory, IPluginFactory2, IPluginFactory3}; use vst3_sys::base::{IBStream, IPluginBase, IPluginFactory, IPluginFactory2, IPluginFactory3};
use vst3_sys::utils::SharedVstPtr; use vst3_sys::utils::SharedVstPtr;
use vst3_sys::vst::{ use vst3_sys::vst::{
IAudioProcessor, IComponent, IEditController, IParamValueQueue, IParameterChanges, TChar, IAudioProcessor, IComponent, IComponentHandler, IEditController, IParamValueQueue,
IParameterChanges, TChar,
}; };
use vst3_sys::VST3; use vst3_sys::VST3;
use widestring::U16CStr; use widestring::U16CStr;
@ -85,6 +86,10 @@ struct WrapperInner<'a, P: Plugin> {
/// The wrapped plugin instance. /// The wrapped plugin instance.
plugin: Pin<Box<RwLock<P>>>, plugin: Pin<Box<RwLock<P>>>,
/// The host's `IComponentHandler` instance, if passed through
/// `IEditController::set_component_handler`.
component_handler: RwLock<Option<VstPtr<dyn IComponentHandler>>>,
/// A realtime-safe task queue so the plugin can schedule tasks that need to be run later on the /// A realtime-safe task queue so the plugin can schedule tasks that need to be run later on the
/// GUI thread. /// GUI thread.
/// ///
@ -140,6 +145,31 @@ enum Task {
TriggerRestart(u32), TriggerRestart(u32),
} }
/// Send+Sync wrapper for these interface pointers.
#[repr(transparent)]
struct VstPtr<T: vst3_sys::ComInterface + ?Sized> {
ptr: vst3_sys::VstPtr<T>,
}
impl<T: vst3_sys::ComInterface + ?Sized> std::ops::Deref for VstPtr<T> {
type Target = vst3_sys::VstPtr<T>;
fn deref(&self) -> &Self::Target {
&self.ptr
}
}
impl<T: vst3_sys::ComInterface + ?Sized> From<vst3_sys::VstPtr<T>> for VstPtr<T> {
fn from(ptr: vst3_sys::VstPtr<T>) -> Self {
Self { ptr }
}
}
/// SAFETY: Sharing these pointers across thread is s safe as they have internal atomic reference
/// counting, so as long as a `VstPtr<T>` handle exists the object will stay alive.
unsafe impl<T: vst3_sys::ComInterface + ?Sized> Send for VstPtr<T> {}
unsafe impl<T: vst3_sys::ComInterface + ?Sized> Sync for VstPtr<T> {}
impl<P: Plugin> WrapperInner<'_, P> { impl<P: Plugin> WrapperInner<'_, P> {
// XXX: The unsafe blocks in this function are unnecessary. but rust-analyzer gets a bit // XXX: The unsafe blocks in this function are unnecessary. but rust-analyzer gets a bit
// confused by all of these vtables // confused by all of these vtables
@ -148,6 +178,8 @@ impl<P: Plugin> WrapperInner<'_, P> {
let mut wrapper = Self { let mut wrapper = Self {
plugin: Box::pin(RwLock::default()), plugin: Box::pin(RwLock::default()),
component_handler: RwLock::new(None),
event_loop: RwLock::new(MaybeUninit::uninit()), event_loop: RwLock::new(MaybeUninit::uninit()),
is_processing: AtomicBool::new(false), is_processing: AtomicBool::new(false),
@ -720,9 +752,10 @@ impl<P: Plugin> IEditController for Wrapper<'_, P> {
unsafe fn set_component_handler( unsafe fn set_component_handler(
&self, &self,
_handler: SharedVstPtr<dyn vst3_sys::vst::IComponentHandler>, handler: SharedVstPtr<dyn vst3_sys::vst::IComponentHandler>,
) -> tresult { ) -> tresult {
// TODO: Use this when we add GUI support *self.inner.component_handler.write() = handler.upgrade().map(VstPtr::from);
kResultOk kResultOk
} }