From ea2c1159bd1c1f211edc085685b1c52d8a6b4e01 Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Wed, 28 Aug 2024 11:26:49 -0500 Subject: [PATCH] introduce EditorHost type; move param gesture methods from Host to EditorHost --- examples/gain/src/lib.rs | 2 +- src/editor.rs | 36 ++++++++++++++++++++++++ src/format/clap/gui.rs | 16 +++++++++-- src/format/clap/host.rs | 7 +---- src/format/vst3/component.rs | 13 ++++++--- src/format/vst3/host.rs | 46 ++----------------------------- src/format/vst3/view.rs | 53 +++++++++++++++++++++++++++++++++--- src/host.rs | 24 ++-------------- src/plugin.rs | 4 +-- 9 files changed, 118 insertions(+), 83 deletions(-) diff --git a/examples/gain/src/lib.rs b/examples/gain/src/lib.rs index df27ffa..02672a4 100644 --- a/examples/gain/src/lib.rs +++ b/examples/gain/src/lib.rs @@ -86,7 +86,7 @@ impl Plugin for Gain { } } - fn editor(&mut self, parent: &ParentWindow) -> Self::Editor { + fn editor(&mut self, _host: EditorHost, parent: &ParentWindow) -> Self::Editor { GainEditor::open(parent).unwrap() } } diff --git a/src/editor.rs b/src/editor.rs index 1e0bee0..c4a366e 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -1,7 +1,43 @@ use std::ffi::{c_ulong, c_void}; +use std::marker::PhantomData; +use std::rc::Rc; use crate::params::{ParamId, ParamValue}; +pub trait EditorHostInner { + fn begin_gesture(&self, id: ParamId); + fn end_gesture(&self, id: ParamId); + fn set_param(&self, id: ParamId, value: ParamValue); +} + +#[derive(Clone)] +pub struct EditorHost { + inner: Rc, + // Ensure !Send and !Sync + _marker: PhantomData<*mut ()>, +} + +impl EditorHost { + pub fn from_inner(inner: Rc) -> EditorHost { + EditorHost { + inner, + _marker: PhantomData, + } + } + + pub fn begin_gesture(&self, id: ParamId) { + self.inner.begin_gesture(id); + } + + pub fn end_gesture(&self, id: ParamId) { + self.inner.end_gesture(id); + } + + pub fn set_param(&self, id: ParamId, value: ParamValue) { + self.inner.set_param(id, value); + } +} + #[derive(Copy, Clone)] pub enum RawParent { Win32(*mut c_void), diff --git a/src/format/clap/gui.rs b/src/format/clap/gui.rs index 2fb69f1..3d9df10 100644 --- a/src/format/clap/gui.rs +++ b/src/format/clap/gui.rs @@ -1,12 +1,22 @@ use std::ffi::{c_char, CStr}; +use std::rc::Rc; use clap_sys::ext::gui::*; use clap_sys::plugin::*; use super::instance::Instance; -use crate::editor::{Editor, ParentWindow, RawParent}; +use crate::editor::{Editor, EditorHost, EditorHostInner, ParentWindow, RawParent}; +use crate::params::{ParamId, ParamValue}; use crate::plugin::Plugin; +struct ClapEditorHost {} + +impl EditorHostInner for ClapEditorHost { + fn begin_gesture(&self, _id: ParamId) {} + fn end_gesture(&self, _id: ParamId) {} + fn set_param(&self, _id: ParamId, _value: ParamValue) {} +} + impl Instance

{ pub(super) const GUI: clap_plugin_gui = clap_plugin_gui { is_api_supported: Some(Self::gui_is_api_supported), @@ -151,7 +161,9 @@ impl Instance

{ let instance = &*(plugin as *const Self); let main_thread_state = &mut *instance.main_thread_state.get(); - let editor = main_thread_state.plugin.editor(&ParentWindow::from_raw(raw_parent)); + let host = EditorHost::from_inner(Rc::new(ClapEditorHost {})); + let parent = ParentWindow::from_raw(raw_parent); + let editor = main_thread_state.plugin.editor(host, &parent); main_thread_state.editor = Some(editor); true diff --git a/src/format/clap/host.rs b/src/format/clap/host.rs index 58c4f87..0c93086 100644 --- a/src/format/clap/host.rs +++ b/src/format/clap/host.rs @@ -1,10 +1,5 @@ use crate::host::HostInner; -use crate::params::{ParamId, ParamValue}; pub struct ClapHost {} -impl HostInner for ClapHost { - fn begin_gesture(&self, _id: ParamId) {} - fn end_gesture(&self, _id: ParamId) {} - fn set_param(&self, _id: ParamId, _value: ParamValue) {} -} +impl HostInner for ClapHost {} diff --git a/src/format/vst3/component.rs b/src/format/vst3/component.rs index 91c413a..ffaafb9 100644 --- a/src/format/vst3/component.rs +++ b/src/format/vst3/component.rs @@ -2,6 +2,7 @@ use std::cell::UnsafeCell; use std::collections::{HashMap, HashSet}; use std::ffi::{c_void, CStr}; use std::ptr; +use std::rc::Rc; use std::sync::Arc; use vst3::{Class, ComRef, ComWrapper, Steinberg::Vst::*, Steinberg::*}; @@ -9,7 +10,7 @@ use vst3::{Class, ComRef, ComWrapper, Steinberg::Vst::*, Steinberg::*}; use super::buffers::ScratchBuffers; use super::host::Vst3Host; use super::util::{copy_wstring, utf16_from_ptr}; -use super::view::View; +use super::view::{View, Vst3EditorHost}; use crate::bus::{BusDir, Format, Layout}; use crate::editor::Editor; use crate::events::{Data, Event, Events}; @@ -39,6 +40,7 @@ pub struct MainThreadState { pub config: Config, pub plugin: P, pub editor_params: Vec, + pub editor_host: Rc, pub editor: Option, } @@ -57,7 +59,7 @@ pub struct Component { param_map: HashMap, plugin_params: ParamValues, processor_params: ParamValues, - host: Arc, + _host: Arc, main_thread_state: Arc>>, // When the audio processor is *not* active, references to ProcessState may only be formed from // the main thread. When the audio processor *is* active, references to ProcessState may only @@ -107,11 +109,12 @@ impl Component

{ param_map, plugin_params: ParamValues::new(&info.params), processor_params: ParamValues::new(&info.params), - host: host.clone(), + _host: host.clone(), main_thread_state: Arc::new(UnsafeCell::new(MainThreadState { config: config.clone(), plugin: P::new(Host::from_inner(host)), editor_params, + editor_host: Rc::new(Vst3EditorHost::new()), editor: None, })), process_state: UnsafeCell::new(ProcessState { @@ -693,7 +696,9 @@ impl IEditControllerTrait for Component

{ } unsafe fn setComponentHandler(&self, handler: *mut IComponentHandler) -> tresult { - let mut current_handler = self.host.handler.write().unwrap(); + let main_thread_state = &mut *self.main_thread_state.get(); + + let mut current_handler = main_thread_state.editor_host.handler.borrow_mut(); if let Some(handler) = ComRef::from_raw(handler) { *current_handler = Some(handler.to_com_ptr()); } else { diff --git a/src/format/vst3/host.rs b/src/format/vst3/host.rs index de628a5..29efb51 100644 --- a/src/format/vst3/host.rs +++ b/src/format/vst3/host.rs @@ -1,51 +1,11 @@ -use std::sync::RwLock; - -use vst3::ComPtr; -use vst3::Steinberg::Vst::{IComponentHandler, IComponentHandlerTrait}; - use crate::host::HostInner; -use crate::params::{ParamId, ParamValue}; -pub struct Vst3Host { - pub handler: RwLock>>, -} +pub struct Vst3Host {} impl Vst3Host { pub fn new() -> Vst3Host { - Vst3Host { - handler: RwLock::new(None), - } + Vst3Host {} } } -impl HostInner for Vst3Host { - fn begin_gesture(&self, id: ParamId) { - let handler = self.handler.read().unwrap(); - if let Some(handler) = &*handler { - // TODO: only call this on main thread - unsafe { - handler.beginEdit(id); - } - } - } - - fn end_gesture(&self, id: ParamId) { - let handler = self.handler.read().unwrap(); - if let Some(handler) = &*handler { - // TODO: only call this on main thread - unsafe { - handler.endEdit(id); - } - } - } - - fn set_param(&self, id: ParamId, value: ParamValue) { - let handler = self.handler.read().unwrap(); - if let Some(handler) = &*handler { - // TODO: only call this on main thread - unsafe { - handler.performEdit(id, value); - } - } - } -} +impl HostInner for Vst3Host {} diff --git a/src/format/vst3/view.rs b/src/format/vst3/view.rs index 3380dc5..aeb5ba8 100644 --- a/src/format/vst3/view.rs +++ b/src/format/vst3/view.rs @@ -1,13 +1,56 @@ -use std::cell::UnsafeCell; +use std::cell::{RefCell, UnsafeCell}; use std::ffi::{c_void, CStr}; use std::sync::Arc; -use vst3::{Class, Steinberg::*}; +use vst3::Steinberg::Vst::{IComponentHandler, IComponentHandlerTrait}; +use vst3::{Class, ComPtr, Steinberg::*}; use super::component::MainThreadState; -use crate::editor::{Editor, ParentWindow, RawParent}; +use crate::editor::{Editor, EditorHost, EditorHostInner, ParentWindow, RawParent}; +use crate::params::{ParamId, ParamValue}; use crate::plugin::Plugin; +pub struct Vst3EditorHost { + pub handler: RefCell>>, +} + +impl Vst3EditorHost { + pub fn new() -> Vst3EditorHost { + Vst3EditorHost { + handler: RefCell::new(None), + } + } +} + +impl EditorHostInner for Vst3EditorHost { + fn begin_gesture(&self, id: ParamId) { + let handler = self.handler.borrow(); + if let Some(handler) = &*handler { + unsafe { + handler.beginEdit(id); + } + } + } + + fn end_gesture(&self, id: ParamId) { + let handler = self.handler.borrow(); + if let Some(handler) = &*handler { + unsafe { + handler.endEdit(id); + } + } + } + + fn set_param(&self, id: ParamId, value: ParamValue) { + let handler = self.handler.borrow(); + if let Some(handler) = &*handler { + unsafe { + handler.performEdit(id, value); + } + } + } +} + pub struct View { main_thread_state: Arc>>, } @@ -60,7 +103,9 @@ impl IPlugViewTrait for View

{ let main_thread_state = &mut *self.main_thread_state.get(); - let editor = main_thread_state.plugin.editor(&ParentWindow::from_raw(raw_parent)); + let host = EditorHost::from_inner(main_thread_state.editor_host.clone()); + let parent = ParentWindow::from_raw(raw_parent); + let editor = main_thread_state.plugin.editor(host, &parent); main_thread_state.editor = Some(editor); kResultOk diff --git a/src/host.rs b/src/host.rs index 7f3b5c0..2df0458 100644 --- a/src/host.rs +++ b/src/host.rs @@ -1,32 +1,14 @@ use std::sync::Arc; -use crate::params::{ParamId, ParamValue}; - -pub trait HostInner { - fn begin_gesture(&self, id: ParamId); - fn end_gesture(&self, id: ParamId); - fn set_param(&self, id: ParamId, value: ParamValue); -} +pub trait HostInner {} #[derive(Clone)] pub struct Host { - inner: Arc, + _inner: Arc, } impl Host { pub fn from_inner(inner: Arc) -> Host { - Host { inner } - } - - pub fn begin_gesture(&self, id: ParamId) { - self.inner.begin_gesture(id); - } - - pub fn end_gesture(&self, id: ParamId) { - self.inner.end_gesture(id); - } - - pub fn set_param(&self, id: ParamId, value: ParamValue) { - self.inner.set_param(id, value); + Host { _inner: inner } } } diff --git a/src/plugin.rs b/src/plugin.rs index 030bfff..6b2cc57 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,7 +1,7 @@ use std::io::{self, Read, Write}; use crate::bus::{BusInfo, Layout}; -use crate::editor::{Editor, ParentWindow}; +use crate::editor::{Editor, EditorHost, ParentWindow}; use crate::host::Host; use crate::params::{ParamId, ParamInfo, ParamValue}; use crate::process::{Config, Processor}; @@ -46,7 +46,7 @@ pub trait Plugin: Send + Sized + 'static { fn save(&self, output: &mut impl Write) -> io::Result<()>; fn load(&mut self, input: &mut impl Read) -> io::Result<()>; fn processor(&mut self, config: Config) -> Self::Processor; - fn editor(&mut self, parent: &ParentWindow) -> Self::Editor; + fn editor(&mut self, host: EditorHost, parent: &ParentWindow) -> Self::Editor; #[allow(unused_variables)] fn latency(&self, config: &Config) -> u64 {