1
0
Fork 0

Add an AsyncExecutor associated type to Plugin

This will make it possible to run background tasks in a type safe way.
Sadly, this does mean that every plugin now needs to define the type
alias and constructor function since Rust does not yet support defaults
for associated types.
This commit is contained in:
Robbert van der Helm 2022-10-21 23:52:46 +02:00
parent 25d20f1950
commit 297ad2a83e
17 changed files with 74 additions and 0 deletions

View file

@ -8,6 +8,17 @@ code then it will not be listed here.
## [2022-10-21]
- NIH-plug has gained support for asynchronously running background tasks in a
simple, type-safe, and realtime-safe way. This sadly does mean that every
`Plugin` instance now needs to define an `AsyncExecutor` type definition and
constructor function as Rust does not yet support defaults for associated
types (Rust issue [#29661](https://github.com/rust-lang/rust/issues/29661)):
```rust
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
```
- The `Editor` trait and the `ParentWindowHandle` struct have been moved from
`nih_plug::plugin` to a new `nih_plug::editor` module.

View file

@ -307,6 +307,9 @@ impl Plugin for Crisp {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -183,6 +183,9 @@ impl Plugin for Crossover {
aux_outputs: Some(&["Band 1", "Band 2", "Band 3", "Band 4", "Band 5"]),
};
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -252,6 +252,9 @@ impl Plugin for Diopser {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -132,6 +132,12 @@ impl Plugin for Gain {
// splits.
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
// More advanced plugins can use this to run expensive background tasks. See the `AsyncExecutor`
// trait's documentation for more information. `()` means that the plugin does not have any
// background tasks.
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -83,6 +83,9 @@ impl Plugin for Gain {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -80,6 +80,9 @@ impl Plugin for Gain {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -79,6 +79,9 @@ impl Plugin for Gain {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -33,6 +33,9 @@ impl Plugin for MidiInverter {
const MIDI_OUTPUT: MidiConfig = MidiConfig::MidiCCs;
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -155,6 +155,9 @@ impl Plugin for PolyModSynth {
const MIDI_INPUT: MidiConfig = MidiConfig::Basic;
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -111,6 +111,9 @@ impl Plugin for Sine {
const MIDI_INPUT: MidiConfig = MidiConfig::Basic;
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -95,6 +95,9 @@ impl Plugin for Stft {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -123,6 +123,9 @@ impl Plugin for LoudnessWarWinner {
const DEFAULT_INPUT_CHANNELS: u32 = 2;
const DEFAULT_OUTPUT_CHANNELS: u32 = 2;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -168,6 +168,9 @@ impl Plugin for PubertySimulator {
const DEFAULT_INPUT_CHANNELS: u32 = 2;
const DEFAULT_OUTPUT_CHANNELS: u32 = 2;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -157,6 +157,9 @@ impl Plugin for SafetyLimiter {
const DEFAULT_INPUT_CHANNELS: u32 = 2;
const DEFAULT_OUTPUT_CHANNELS: u32 = 2;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -272,6 +272,9 @@ impl Plugin for SpectralCompressor {
const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type AsyncExecutor = ();
fn async_executor(&self) -> Self::AsyncExecutor {}
fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

View file

@ -2,6 +2,7 @@
use std::sync::Arc;
use crate::async_executor::AsyncExecutor;
use crate::buffer::Buffer;
use crate::context::{InitContext, ProcessContext};
use crate::editor::Editor;
@ -89,6 +90,20 @@ pub trait Plugin: Default + Send + 'static {
/// to do offline processing.
const HARD_REALTIME_ONLY: bool = false;
/// The plugin's [`AsyncExecutor`] type. Use `()` if the plugin does not need to perform
/// expensive background tasks.
//
// This needs to be an associated type so we can have a nice type safe interface in the
// `*Context` traits.
//
// NOTE: Sadly it's not yet possible to default this and the `async_executor()` function to
// `()`: https://github.com/rust-lang/rust/issues/29661
type AsyncExecutor: AsyncExecutor;
/// The plugin's background task executor. Use `()` if the plugin does not need this
/// functinlality.
fn async_executor(&self) -> Self::AsyncExecutor;
/// The plugin's parameters. The host will update the parameter values before calling
/// `process()`. These parameters are identified by strings that should never change when the
/// plugin receives an update.