1
0
Fork 0

Add a SysExMessage type to Plugin

This is needed to enable sending and receiving SysEx #54. Because
associated type defaults still are not stable, this requires every
plugin that doesn't need this to set this to the unit type:

```rust
type SysExMessage = ();
```
This commit is contained in:
Robbert van der Helm 2023-01-31 17:58:54 +01:00
parent 978d466019
commit c8ed795524
20 changed files with 44 additions and 2 deletions

View file

@ -6,6 +6,18 @@ new and what's changed, this document lists all breaking changes in reverse
chronological order. If a new feature did not require any changes to existing chronological order. If a new feature did not require any changes to existing
code then it will not be listed here. code then it will not be listed here.
## [2023-01-31]
- NIH-plug has gained support MIDI SysEx in a simple, type-safe, and
realtime-safe way. This sadly does mean that every `Plugin` instance now needs
to define a `SysExMessage` 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 SysExMessage = ();
```
## [2023-01-12] ## [2023-01-12]
- The Vizia dependency has been updated. This updated version uses a new text - The Vizia dependency has been updated. This updated version uses a new text

View file

@ -141,6 +141,9 @@ Scroll down for more information on the underlying plugin framework.
- Full support for receiving and outputting both modern polyphonic note - Full support for receiving and outputting both modern polyphonic note
expression events as well as MIDI CCs, channel pressure, and pitch bend for expression events as well as MIDI CCs, channel pressure, and pitch bend for
CLAP and VST3. CLAP and VST3.
- MIDI SysEx is also supported. Plugins can define their own structs or sum
types to wrap around those messages so they don't need to interact with raw
byte buffers in the process function.
- Support for flexible dynamic buffer configurations, including multiple input - Support for flexible dynamic buffer configurations, including multiple input
and output busses. and output busses.
- A plugin bundler accessible through the - A plugin bundler accessible through the

View file

@ -186,6 +186,7 @@ impl Plugin for BuffrGlitch {
const MIDI_INPUT: MidiConfig = MidiConfig::Basic; const MIDI_INPUT: MidiConfig = MidiConfig::Basic;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -306,6 +306,7 @@ impl Plugin for Crisp {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

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

View file

@ -118,6 +118,7 @@ impl Plugin for Diopser {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -134,6 +134,10 @@ impl Plugin for Gain {
// splits. // splits.
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
// If the plugin can send or receive SysEx messages, it can define a type to wrap around those
// messages here. The type implements the `SysExMessage` trait, which allows conversion to and
// from plain byte buffers.
type SysExMessage = ();
// More advanced plugins can use this to run expensive background tasks. See the field's // More advanced plugins can use this to run expensive background tasks. See the field's
// documentation for more information. `()` means that the plugin does not have any background // documentation for more information. `()` means that the plugin does not have any background
// tasks. // tasks.

View file

@ -83,6 +83,7 @@ impl Plugin for Gain {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -80,6 +80,7 @@ impl Plugin for Gain {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -79,6 +79,7 @@ impl Plugin for Gain {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -33,6 +33,7 @@ impl Plugin for MidiInverter {
const MIDI_OUTPUT: MidiConfig = MidiConfig::MidiCCs; const MIDI_OUTPUT: MidiConfig = MidiConfig::MidiCCs;
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -155,6 +155,7 @@ impl Plugin for PolyModSynth {
const MIDI_INPUT: MidiConfig = MidiConfig::Basic; const MIDI_INPUT: MidiConfig = MidiConfig::Basic;
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -111,6 +111,7 @@ impl Plugin for Sine {
const MIDI_INPUT: MidiConfig = MidiConfig::Basic; const MIDI_INPUT: MidiConfig = MidiConfig::Basic;
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -95,6 +95,7 @@ impl Plugin for Stft {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -123,6 +123,7 @@ impl Plugin for LoudnessWarWinner {
const DEFAULT_INPUT_CHANNELS: u32 = 2; const DEFAULT_INPUT_CHANNELS: u32 = 2;
const DEFAULT_OUTPUT_CHANNELS: u32 = 2; const DEFAULT_OUTPUT_CHANNELS: u32 = 2;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -168,6 +168,7 @@ impl Plugin for PubertySimulator {
const DEFAULT_INPUT_CHANNELS: u32 = 2; const DEFAULT_INPUT_CHANNELS: u32 = 2;
const DEFAULT_OUTPUT_CHANNELS: u32 = 2; const DEFAULT_OUTPUT_CHANNELS: u32 = 2;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -158,6 +158,7 @@ impl Plugin for SafetyLimiter {
const DEFAULT_INPUT_CHANNELS: u32 = 2; const DEFAULT_INPUT_CHANNELS: u32 = 2;
const DEFAULT_OUTPUT_CHANNELS: u32 = 2; const DEFAULT_OUTPUT_CHANNELS: u32 = 2;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -265,6 +265,7 @@ impl Plugin for SpectralCompressor {
const SAMPLE_ACCURATE_AUTOMATION: bool = true; const SAMPLE_ACCURATE_AUTOMATION: bool = true;
type SysExMessage = ();
type BackgroundTask = (); type BackgroundTask = ();
fn params(&self) -> Arc<dyn Params> { fn params(&self) -> Arc<dyn Params> {

View file

@ -3,12 +3,13 @@
use std::sync::Arc; use std::sync::Arc;
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::context::gui::AsyncExecutor;
use crate::context::init::InitContext; use crate::context::init::InitContext;
use crate::context::process::ProcessContext; use crate::context::process::ProcessContext;
use crate::editor::Editor; use crate::editor::Editor;
use crate::midi::sysex::SysExMessage;
use crate::midi::MidiConfig; use crate::midi::MidiConfig;
use crate::params::Params; use crate::params::Params;
use crate::prelude::AsyncExecutor;
use crate::wrapper::clap::features::ClapFeature; use crate::wrapper::clap::features::ClapFeature;
use crate::wrapper::state::PluginState; use crate::wrapper::state::PluginState;
@ -26,7 +27,7 @@ pub type TaskExecutor<P> = Box<dyn Fn(<P as Plugin>::BackgroundTask) + Send>;
/// ///
/// Some notable not yet implemented features include: /// Some notable not yet implemented features include:
/// ///
/// - MIDI SysEx and MIDI2 for CLAP, note expressions, polyphonic modulation and MIDI1 are already /// - MIDI2 for CLAP, note expressions, polyphonic modulation and MIDI1, and MIDI SysEx are already
/// supported /// supported
/// - Audio thread thread pools (with host integration in CLAP) /// - Audio thread thread pools (with host integration in CLAP)
#[allow(unused_variables)] #[allow(unused_variables)]
@ -96,6 +97,12 @@ pub trait Plugin: Default + Send + 'static {
/// to do offline processing. /// to do offline processing.
const HARD_REALTIME_ONLY: bool = false; const HARD_REALTIME_ONLY: bool = false;
/// The plugin's SysEx message type if it supports sending or receiving MIDI SysEx messages, or
/// `()` if it does not. This type can be a struct or enum wrapping around one or more message
/// types, and the [`SysExMessage`] trait is then used to convert between this type and basic
/// byte buffers.
type SysExMessage: SysExMessage;
/// A type encoding the different background tasks this plugin wants to run, or `()` if it /// A type encoding the different background tasks this plugin wants to run, or `()` if it
/// doesn't have any background tasks. This is usually set to an enum type. The task type should /// doesn't have any background tasks. This is usually set to an enum type. The task type should
/// not contain any heap allocated data like [`Vec`]s and [`Box`]es. Tasks can be send using the /// not contain any heap allocated data like [`Vec`]s and [`Box`]es. Tasks can be send using the

View file

@ -16,6 +16,7 @@ pub use crate::context::init::InitContext;
pub use crate::context::process::ProcessContext; pub use crate::context::process::ProcessContext;
// This also includes the derive macro // This also includes the derive macro
pub use crate::editor::{Editor, ParentWindowHandle}; pub use crate::editor::{Editor, ParentWindowHandle};
pub use crate::midi::sysex::SysExMessage;
pub use crate::midi::{control_change, MidiConfig, NoteEvent}; pub use crate::midi::{control_change, MidiConfig, NoteEvent};
pub use crate::params::enums::{Enum, EnumParam}; pub use crate::params::enums::{Enum, EnumParam};
pub use crate::params::internals::ParamPtr; pub use crate::params::internals::ParamPtr;