From fe96b8572ede36d46cbe04789d7233ae020aeda8 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 5 Feb 2022 16:30:33 +0100 Subject: [PATCH] Type erase GuiContext by splitting the safe API These functions not being able to be made into an object was the whole reason why we needed the associated type in the first place. This will make everything much nicer to work with, since specialization/overlapping instances is still not possible with the stable compiler. --- src/context.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/src/context.rs b/src/context.rs index 245d016a..e9a15a10 100644 --- a/src/context.rs +++ b/src/context.rs @@ -24,6 +24,7 @@ mod linux; #[cfg(all(target_family = "unix", not(target_os = "macos")))] pub(crate) use linux::LinuxEventLoop as OsEventLoop; +use crate::param::internals::ParamPtr; use crate::param::Param; use crate::plugin::NoteEvent; @@ -63,10 +64,21 @@ pub trait ProcessContext { // // The implementing wrapper needs to be able to handle concurrent requests, and it should perform // the actual callback within [MainThreadQueue::do_maybe_async]. -pub trait GuiContext { +// +// TODO: Update documentation +// TODO: Add the safe generic setter API +pub trait GuiContext: Send + Sync { + /// TODO: Docuemnt safe API + fn setter(&self) -> ParamSetter + where + Self: Sized, + { + ParamSetter { context: self } + } + /// Inform the host that you will start automating a parmater. This needs to be called before /// calling [Self::set_parameter()] for the specified parameter. - fn begin_set_parameter(&self, param: &P); + unsafe fn begin_set_parameter(&self, param: ParamPtr); /// Set a parameter to the specified parameter value. You will need to call /// [Self::begin_set_parameter()] before and [Self::end_set_parameter()] after calling this so @@ -76,12 +88,47 @@ pub trait GuiContext { /// /// This function assumes you're already calling this from a GUI thread. Calling any of these /// functions from any other thread may result in unexpected behavior. - fn set_parameter(&self, param: &P, value: P::Plain); + // TODO: Move into helper + // fn set_parameter(&self, param: &P, value: P::Plain); + unsafe fn set_parameter_normalized(&self, param: ParamPtr, normalized: f32); /// Inform the host that you are done automating a parameter. This needs to be called after one /// or more [Self::set_parameter()] calls for a parameter so the host knows the automation /// gesture has finished. - fn end_set_parameter(&self, param: &P); + unsafe fn end_set_parameter(&self, param: ParamPtr); +} + +/// A convenience struct for setting parameter values. +// TODO: Document +pub struct ParamSetter<'a> { + context: &'a dyn GuiContext, +} + +impl ParamSetter<'_> { + /// Inform the host that you will start automating a parmater. This needs to be called before + /// calling [Self::set_parameter()] for the specified parameter. + pub fn begin_set_parameter(&self, param: &P) { + todo!() + } + + /// Set a parameter to the specified parameter value. You will need to call + /// [Self::begin_set_parameter()] before and [Self::end_set_parameter()] after calling this so + /// the host can properly record automation for the parameter. This can be called multiple times + /// in a row before calling [Self::end_set_parameter()], for instance when moving a slider + /// around. + /// + /// This function assumes you're already calling this from a GUI thread. Calling any of these + /// functions from any other thread may result in unexpected behavior. + pub fn set_parameter(&self, param: &P, value: P::Plain) { + todo!() + } + + /// Inform the host that you are done automating a parameter. This needs to be called after one + /// or more [Self::set_parameter()] calls for a parameter so the host knows the automation + /// gesture has finished. + pub fn end_set_parameter(&self, param: &P) { + todo!() + } } /// A trait describing the functionality of the platform-specific event loop that can execute tasks