diff --git a/src/context/gui.rs b/src/context/gui.rs index 4f69aab8..05ae347c 100644 --- a/src/context/gui.rs +++ b/src/context/gui.rs @@ -1,8 +1,11 @@ //! A context passed to a plugin's editor. +use std::sync::Arc; + use super::PluginApi; use crate::params::internals::ParamPtr; use crate::params::Param; +use crate::plugin::Plugin; use crate::wrapper::state::PluginState; /// Callbacks the plugin can make when the user interacts with its GUI such as updating parameter @@ -65,6 +68,25 @@ pub trait GuiContext: Send + Sync + 'static { fn set_state(&self, state: PluginState); } +/// An way to run background tasks from the plugin's GUI, equivalent to +/// [`ProcessContext::execute_async()`][crate::prelude::ProcessContext::execute_async()]. This is +/// passed directly to [`Plugin::editor()`] so the plugin can move it into its editor and use it +/// later. +/// +/// # Note +/// +/// This is only intended to be used from the GUI. Use the methods on +/// [`InitContext`][crate::prelude::InitContext] and +/// [`ProcessContext`][crate::prelude::ProcessContext] to run tasks during the `initialize()` and +/// `process()` functions. +// +// NOTE: This is separate from `GuiContext` because adding a type parameter there would clutter up a +// lot of structs, and may even be incompatible with the way certain GUI libraries work. +#[derive(Clone)] +pub struct AsyncExecutor { + pub(crate) inner: Arc, +} + /// A convenience helper for setting parameter values. Any changes made here will be broadcasted to /// the host and reflected in the plugin's [`Params`][crate::params::Params] object. These /// functions should only be called from the main thread. @@ -72,6 +94,20 @@ pub struct ParamSetter<'a> { pub raw_context: &'a dyn GuiContext, } +impl AsyncExecutor

{ + /// Run a task on a background thread. This allows deferring expensive background tasks for + /// later. This task will likely still be executed on the GUI thread. + /// + /// # Note + /// + /// Scheduling the same task multiple times will cause those duplicate tasks to pile up. Try to + /// either prevent this from happening, or check whether the task still needs to be completed in + /// your task executor. + pub fn execute_async(&self, task: P::BackgroundTask) { + (self.inner)(task); + } +} + impl<'a> ParamSetter<'a> { pub fn new(context: &'a dyn GuiContext) -> Self { Self { diff --git a/src/context/process.rs b/src/context/process.rs index 8e5154e5..5e371dc5 100644 --- a/src/context/process.rs +++ b/src/context/process.rs @@ -17,13 +17,13 @@ pub trait ProcessContext { /// Get the current plugin API. fn plugin_api(&self) -> PluginApi; - /// Run a task on a background thread. This allows defering expensive background tasks for + /// Run a task on a background thread. This allows deferring expensive background tasks for /// alter. As long as creating the `task` is realtime-safe, this operation is too. /// /// # Note /// /// Scheduling the same task multiple times will cause those duplicate tasks to pile up. Try to - /// either prevnt this from happening, or check whether the task still needs to be completed in + /// either prevent this from happening, or check whether the task still needs to be completed in /// your task executor. fn execute_async(&self, task: P::BackgroundTask); diff --git a/src/prelude.rs b/src/prelude.rs index 61faf6f2..ca4f7ccc 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -11,7 +11,7 @@ pub use crate::formatters; pub use crate::util; pub use crate::buffer::Buffer; -pub use crate::context::gui::{GuiContext, ParamSetter}; +pub use crate::context::gui::{AsyncExecutor, GuiContext, ParamSetter}; pub use crate::context::init::InitContext; pub use crate::context::process::ProcessContext; // This also includes the derive macro