2022-04-12 01:38:20 +10:00
|
|
|
//! NIH-plug can handle floating point, integer, boolean, and enum parameters. Parameters are
|
2022-10-20 21:10:35 +11:00
|
|
|
//! managed by creating a struct deriving the [`Params`][Params] trait containing fields
|
2022-04-25 02:34:40 +10:00
|
|
|
//! for those parameter types, and then returning a reference to that object from your
|
2022-04-12 01:38:20 +10:00
|
|
|
//! [`Plugin::params()`][crate::prelude::Plugin::params()] method. See the `Params` trait for more
|
|
|
|
//! information.
|
2022-01-31 03:16:12 +11:00
|
|
|
|
2022-10-20 21:10:35 +11:00
|
|
|
use std::collections::BTreeMap;
|
2022-01-25 12:17:30 +11:00
|
|
|
use std::fmt::Display;
|
2022-10-20 21:10:35 +11:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use self::internals::ParamPtr;
|
|
|
|
|
|
|
|
// The proc-macro for deriving `Params`
|
|
|
|
pub use nih_plug_derive::Params;
|
2022-01-25 06:59:46 +11:00
|
|
|
|
2022-02-15 00:19:46 +11:00
|
|
|
// Parameter types
|
2022-02-15 00:27:40 +11:00
|
|
|
mod boolean;
|
2022-02-15 00:35:57 +11:00
|
|
|
pub mod enums;
|
2022-03-04 05:24:40 +11:00
|
|
|
mod float;
|
|
|
|
mod integer;
|
2022-02-02 07:06:13 +11:00
|
|
|
|
2022-02-02 07:01:28 +11:00
|
|
|
pub mod internals;
|
2022-10-20 21:11:04 +11:00
|
|
|
pub mod persist;
|
2022-02-02 07:06:13 +11:00
|
|
|
pub mod range;
|
2022-02-03 07:08:23 +11:00
|
|
|
pub mod smoothing;
|
2022-02-02 07:01:28 +11:00
|
|
|
|
2022-02-15 00:27:40 +11:00
|
|
|
pub use boolean::BoolParam;
|
2022-02-15 00:35:57 +11:00
|
|
|
pub use enums::EnumParam;
|
2022-03-04 05:24:40 +11:00
|
|
|
pub use float::FloatParam;
|
|
|
|
pub use integer::IntParam;
|
2022-02-14 12:04:17 +11:00
|
|
|
|
2022-03-23 23:02:54 +11:00
|
|
|
bitflags::bitflags! {
|
|
|
|
/// Flags for controlling a parameter's behavior.
|
|
|
|
#[repr(transparent)]
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct ParamFlags: u32 {
|
2022-03-24 03:36:58 +11:00
|
|
|
/// When applied to a [`BoolParam`], this will cause the parameter to be linked to the
|
|
|
|
/// host's bypass control. Only a single parameter can be marked as a bypass parameter. If
|
|
|
|
/// you don't have a bypass parameter, then NIH-plug will add one for you. You will need to
|
|
|
|
/// implement this yourself if your plugin introduces latency.
|
|
|
|
const BYPASS = 1 << 0;
|
2022-05-22 20:37:30 +10:00
|
|
|
/// The parameter cannot be changed from an automation lane. The parameter can however still
|
|
|
|
/// be manually changed by the user from either the plugin's own GUI or from the host's
|
|
|
|
/// generic UI.
|
2022-03-24 03:36:58 +11:00
|
|
|
const NON_AUTOMATABLE = 1 << 1;
|
2022-05-22 20:37:30 +10:00
|
|
|
/// Hides the parameter in the host's generic UI for this plugin. This also implies
|
|
|
|
/// `NON_AUTOMATABLE`. Setting this does not prevent you from changing the parameter in the
|
|
|
|
/// plugin's editor GUI.
|
|
|
|
const HIDDEN = 1 << 2;
|
2022-03-23 23:02:54 +11:00
|
|
|
/// Don't show this parameter when generating a generic UI for the plugin using one of
|
|
|
|
/// NIH-plug's generic UI widgets.
|
2022-05-22 20:37:30 +10:00
|
|
|
const HIDE_IN_GENERIC_UI = 1 << 3;
|
2022-03-23 23:02:54 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-02 00:40:18 +10:00
|
|
|
/// Describes a single parameter of any type. Most parameter implementations also have a field
|
|
|
|
/// called `value` that and a field called `smoothed`. The former stores the latest unsmoothed
|
|
|
|
/// value, and the latter can be used to access the smoother. These two fields should be used in DSP
|
|
|
|
/// code to either get the parameter's current (smoothed) value. In UI code the getters from this
|
|
|
|
/// trait should be used instead.
|
2022-02-10 05:45:16 +11:00
|
|
|
pub trait Param: Display {
|
2022-02-02 07:02:58 +11:00
|
|
|
/// The plain parameter type.
|
2022-03-06 05:50:12 +11:00
|
|
|
type Plain: PartialEq;
|
2022-02-02 07:02:58 +11:00
|
|
|
|
2022-03-03 23:55:54 +11:00
|
|
|
/// Get the human readable name for this parameter.
|
2022-04-12 07:27:36 +10:00
|
|
|
fn name(&self) -> &str;
|
2022-03-03 23:55:54 +11:00
|
|
|
|
|
|
|
/// Get the unit label for this parameter, if any.
|
|
|
|
fn unit(&self) -> &'static str;
|
|
|
|
|
2022-07-06 03:39:18 +10:00
|
|
|
/// Get this parameter's polyphonic modulation ID. If this is set for a parameter in a CLAP
|
|
|
|
/// plugin, then polyphonic modulation will be enabled for that parameter. Polyphonic modulation
|
2022-07-06 21:37:47 +10:00
|
|
|
/// is communicated to the plugin through
|
2022-10-20 21:21:24 +11:00
|
|
|
/// [`NoteEvent::PolyModulation`][crate::prelude::NoteEvent::PolyModulation] and
|
|
|
|
/// [`NoteEvent::MonoAutomation`][crate::prelude::NoteEvent::MonoAutomation] events. See the
|
2022-07-06 21:37:47 +10:00
|
|
|
/// documentation on those events for more information.
|
2022-07-06 03:39:18 +10:00
|
|
|
///
|
|
|
|
/// # Important
|
|
|
|
///
|
|
|
|
/// After enabling polyphonic modulation, the plugin **must** start sending
|
2022-10-20 21:21:24 +11:00
|
|
|
/// [`NoteEvent::VoiceTerminated`][crate::prelude::NoteEvent::VoiceTerminated] events to the
|
|
|
|
/// host when a voice has fully ended. This allows the host to reuse its modulation resources.
|
2022-07-06 03:39:18 +10:00
|
|
|
fn poly_modulation_id(&self) -> Option<u32>;
|
|
|
|
|
2022-03-20 02:09:31 +11:00
|
|
|
/// Get the unnormalized value for this parameter.
|
2022-11-07 23:03:44 +11:00
|
|
|
fn modulated_plain_value(&self) -> Self::Plain;
|
2022-03-20 02:09:31 +11:00
|
|
|
|
|
|
|
/// Get the normalized `[0, 1]` value for this parameter.
|
2022-11-07 23:03:44 +11:00
|
|
|
fn modulated_normalized_value(&self) -> f32;
|
2022-03-20 02:09:31 +11:00
|
|
|
|
2022-05-02 02:30:30 +10:00
|
|
|
/// Get the unnormalized value for this parameter before any (monophonic) modulation coming from
|
|
|
|
/// the host has been applied. If the host is not currently modulating this parameter than this
|
2022-11-07 23:03:44 +11:00
|
|
|
/// will be the same as [`modulated_plain_value()`][Self::modulated_plain_value()]. This may be
|
|
|
|
/// useful for displaying modulation differently in plugin GUIs. Right now only CLAP plugins in
|
|
|
|
/// Bitwig Studio use modulation.
|
2022-05-02 02:30:30 +10:00
|
|
|
fn unmodulated_plain_value(&self) -> Self::Plain;
|
|
|
|
|
|
|
|
/// Get the normalized `[0, 1]` value for this parameter before any (monophonic) modulation
|
|
|
|
/// coming from the host has been applied. If the host is not currently modulating this
|
2022-11-07 23:03:44 +11:00
|
|
|
/// parameter than this will be the same as
|
|
|
|
/// [`modulated_normalized_value()`][Self::modulated_normalized_value()]. This may be useful for
|
|
|
|
/// displaying modulation differently in plugin GUIs. Right now only CLAP plugins in Bitwig
|
|
|
|
/// Studio use modulation.
|
2022-05-02 02:30:30 +10:00
|
|
|
fn unmodulated_normalized_value(&self) -> f32;
|
|
|
|
|
2022-03-21 22:49:59 +11:00
|
|
|
/// Get the unnormalized default value for this parameter.
|
|
|
|
fn default_plain_value(&self) -> Self::Plain;
|
|
|
|
|
|
|
|
/// Get the normalized `[0, 1]` default value for this parameter.
|
2022-05-02 00:32:01 +10:00
|
|
|
#[inline]
|
2022-03-21 22:49:59 +11:00
|
|
|
fn default_normalized_value(&self) -> f32 {
|
|
|
|
self.preview_normalized(self.default_plain_value())
|
|
|
|
}
|
|
|
|
|
2022-09-29 20:28:56 +10:00
|
|
|
/// Get the number of steps for this parameter, if it is discrete. Used for the host's generic
|
2022-03-20 02:06:20 +11:00
|
|
|
/// UI.
|
2022-03-03 23:55:54 +11:00
|
|
|
fn step_count(&self) -> Option<usize>;
|
|
|
|
|
2022-04-27 03:39:03 +10:00
|
|
|
/// Returns the previous step from a specific value for this parameter. This can be the same as
|
2022-03-20 02:06:20 +11:00
|
|
|
/// `from` if the value is at the start of its range. This is mainly used for scroll wheel
|
|
|
|
/// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one
|
|
|
|
/// hundredth of the normalized range instead.
|
2022-11-09 08:03:26 +11:00
|
|
|
///
|
|
|
|
/// If `finer` is true, then the step size should be decreased if the parameter is continuous.
|
|
|
|
fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain;
|
2022-03-20 02:06:20 +11:00
|
|
|
|
2022-04-27 03:39:03 +10:00
|
|
|
/// Returns the next step from a specific value for this parameter. This can be the same as
|
2022-03-20 02:06:20 +11:00
|
|
|
/// `from` if the value is at the end of its range. This is mainly used for scroll wheel
|
|
|
|
/// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one
|
|
|
|
/// hundredth of the normalized range instead.
|
2022-11-09 08:03:26 +11:00
|
|
|
///
|
|
|
|
/// If `finer` is true, then the step size should be decreased if the parameter is continuous.
|
|
|
|
fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain;
|
2022-03-20 02:06:20 +11:00
|
|
|
|
2022-03-20 02:12:10 +11:00
|
|
|
/// The same as [`previous_step()`][Self::previous_step()], but for normalized values. This is
|
|
|
|
/// mostly useful for GUI widgets.
|
2022-11-09 08:03:26 +11:00
|
|
|
fn previous_normalized_step(&self, from: f32, finer: bool) -> f32 {
|
|
|
|
self.preview_normalized(self.previous_step(self.preview_plain(from), finer))
|
2022-03-20 02:12:10 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The same as [`next_step()`][Self::next_step()], but for normalized values. This is mostly
|
|
|
|
/// useful for GUI widgets.
|
2022-11-09 08:03:26 +11:00
|
|
|
fn next_normalized_step(&self, from: f32, finer: bool) -> f32 {
|
|
|
|
self.preview_normalized(self.next_step(self.preview_plain(from), finer))
|
2022-03-20 02:12:10 +11:00
|
|
|
}
|
|
|
|
|
2022-02-02 07:02:58 +11:00
|
|
|
/// Get the string representation for a normalized value. Used as part of the wrappers. Most
|
|
|
|
/// plugin formats already have support for units, in which case it shouldn't be part of this
|
|
|
|
/// string or some DAWs may show duplicate units.
|
|
|
|
fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String;
|
|
|
|
|
|
|
|
/// Get the string representation for a normalized value. Used as part of the wrappers.
|
|
|
|
fn string_to_normalized_value(&self, string: &str) -> Option<f32>;
|
|
|
|
|
2022-02-06 03:31:45 +11:00
|
|
|
/// Get the normalized value for a plain, unnormalized value, as a float. Used as part of the
|
|
|
|
/// wrappers.
|
|
|
|
fn preview_normalized(&self, plain: Self::Plain) -> f32;
|
|
|
|
|
|
|
|
/// Get the plain, unnormalized value for a normalized value, as a float. Used as part of the
|
2022-03-04 09:05:01 +11:00
|
|
|
/// wrappers. This **does** snap to step sizes for continuous parameters (i.e. [`FloatParam`]).
|
2022-02-06 03:31:45 +11:00
|
|
|
fn preview_plain(&self, normalized: f32) -> Self::Plain;
|
|
|
|
|
2022-07-07 02:55:42 +10:00
|
|
|
/// Get the plain, unnormalized value for this parameter after polyphonic modulation has been
|
|
|
|
/// applied. This is a convenience method for calling [`preview_plain()`][Self::preview_plain()]
|
|
|
|
/// with `unmodulated_normalized_value() + normalized_offset`.`
|
|
|
|
#[inline]
|
|
|
|
fn preview_modulated(&self, normalized_offset: f32) -> Self::Plain {
|
|
|
|
self.preview_plain(self.unmodulated_normalized_value() + normalized_offset)
|
|
|
|
}
|
|
|
|
|
2022-03-23 23:02:54 +11:00
|
|
|
/// Flags to control the parameter's behavior. See [`ParamFlags`].
|
|
|
|
fn flags(&self) -> ParamFlags;
|
|
|
|
|
2022-10-20 21:10:35 +11:00
|
|
|
/// Internal implementation detail for implementing [`Params`][Params]. This should
|
2022-03-04 09:05:01 +11:00
|
|
|
/// not be used directly.
|
2022-02-02 07:02:58 +11:00
|
|
|
fn as_ptr(&self) -> internals::ParamPtr;
|
|
|
|
}
|
2022-05-02 02:45:35 +10:00
|
|
|
|
|
|
|
/// Contains the setters for parameters. These should not be exposed to plugins to avoid confusion.
|
|
|
|
pub(crate) trait ParamMut: Param {
|
2022-05-02 02:53:16 +10:00
|
|
|
/// Set this parameter based on a plain, unnormalized value. This does not snap to step sizes
|
2022-05-02 23:46:57 +10:00
|
|
|
/// for continuous parameters (i.e. [`FloatParam`]). If
|
|
|
|
/// [`modulate_value()`][Self::modulate_value()] has previously been called with a non zero
|
|
|
|
/// value then this offset is taken into account to form the effective value.
|
2022-05-02 02:45:35 +10:00
|
|
|
///
|
|
|
|
/// This does **not** update the smoother.
|
2022-09-07 05:55:14 +10:00
|
|
|
fn set_plain_value(&self, plain: Self::Plain);
|
2022-05-02 02:45:35 +10:00
|
|
|
|
2022-05-02 02:53:16 +10:00
|
|
|
/// Set this parameter based on a normalized value. The normalized value will be snapped to the
|
2022-05-02 23:46:57 +10:00
|
|
|
/// step size for continuous parameters (i.e. [`FloatParam`]). If
|
|
|
|
/// [`modulate_value()`][Self::modulate_value()] has previously been called with a non zero
|
|
|
|
/// value then this offset is taken into account to form the effective value.
|
2022-05-02 02:45:35 +10:00
|
|
|
///
|
|
|
|
/// This does **not** update the smoother.
|
2022-09-07 05:55:14 +10:00
|
|
|
fn set_normalized_value(&self, normalized: f32);
|
2022-05-02 02:45:35 +10:00
|
|
|
|
2022-05-02 23:46:57 +10:00
|
|
|
/// Add a modulation offset to the value's unmodulated value. This value sticks until this
|
|
|
|
/// function is called again with a 0.0 value. Out of bound values will be clamped to the
|
|
|
|
/// parameter's range. The normalized value will be snapped to the step size for continuous
|
|
|
|
/// parameters (i.e. [`FloatParam`]).
|
2022-05-02 02:53:16 +10:00
|
|
|
///
|
|
|
|
/// This does **not** update the smoother.
|
2022-09-07 05:55:14 +10:00
|
|
|
fn modulate_value(&self, modulation_offset: f32);
|
2022-05-02 02:53:16 +10:00
|
|
|
|
2022-05-02 02:45:35 +10:00
|
|
|
/// Update the smoother state to point to the current value. Also used when initializing and
|
|
|
|
/// restoring a plugin so everything is in sync. In that case the smoother should completely
|
|
|
|
/// reset to the current value.
|
2022-09-07 05:55:14 +10:00
|
|
|
fn update_smoother(&self, sample_rate: f32, reset: bool);
|
2022-05-02 02:45:35 +10:00
|
|
|
}
|
2022-10-20 21:10:35 +11:00
|
|
|
|
|
|
|
/// Describes a struct containing parameters and other persistent fields.
|
|
|
|
///
|
|
|
|
/// # Deriving `Params` and `#[id = "stable"]`
|
|
|
|
///
|
2022-10-20 21:21:24 +11:00
|
|
|
/// This trait can be derived on a struct containing [`FloatParam`] and other parameter fields by
|
|
|
|
/// adding `#[derive(Params)]`. When deriving this trait, any of those parameter fields should have
|
|
|
|
/// the `#[id = "stable"]` attribute, where `stable` is an up to 6 character long string (to avoid
|
|
|
|
/// collisions) that will be used to identify the parameter internally so you can safely move it
|
|
|
|
/// around and rename the field without breaking compatibility with old presets.
|
2022-10-20 21:10:35 +11:00
|
|
|
///
|
|
|
|
/// ## `#[persist = "key"]`
|
|
|
|
///
|
|
|
|
/// The struct can also contain other fields that should be persisted along with the rest of the
|
2022-10-20 21:21:24 +11:00
|
|
|
/// preset data. These fields should be [`PersistentField`][persist::PersistentField]s annotated
|
|
|
|
/// with the `#[persist = "key"]` attribute containing types that can be serialized and deserialized
|
|
|
|
/// with [Serde](https://serde.rs/).
|
2022-10-20 21:10:35 +11:00
|
|
|
///
|
|
|
|
/// ## `#[nested]`, `#[nested(group_name = "group name")]`
|
|
|
|
///
|
|
|
|
/// Finally, the `Params` object may include parameters from other objects. Setting a group name is
|
|
|
|
/// optional, but some hosts can use this information to display the parameters in a tree structure.
|
|
|
|
/// Parameter IDs and persisting keys still need to be **unique** when using nested parameter
|
|
|
|
/// structs. This currently has the following caveats:
|
|
|
|
///
|
|
|
|
/// - Enforcing that parameter IDs and persist keys are unique does not work across nested structs.
|
|
|
|
/// - Deserializing persisted fields will give false positives about fields not existing.
|
|
|
|
///
|
|
|
|
/// Take a look at the example gain example plugin to see how this is used.
|
|
|
|
///
|
|
|
|
/// ## `#[nested(id_prefix = "foo", group_name = "Foo")]`
|
|
|
|
///
|
|
|
|
/// Adding this attribute to a `Params` sub-object works similarly to the regular `#[nested]`
|
|
|
|
/// attribute, but it also adds an ID to all parameters from the nested object. If a parameter in
|
|
|
|
/// the nested nested object normally has parameter ID `bar`, the parameter's ID will now be renamed
|
|
|
|
/// to `foo_bar`. _This makes it possible to reuse same parameter struct with different names and
|
|
|
|
/// parameter indices._
|
|
|
|
///
|
|
|
|
/// This does **not** support persistent fields.
|
|
|
|
///
|
|
|
|
/// ## `#[nested(array, group_name = "Foo")]`
|
|
|
|
///
|
|
|
|
/// This can be applied to an array-like data structure and it works similar to a `nested` attribute
|
|
|
|
/// with an `id_name`, except that it will iterate over the array and create unique indices for all
|
|
|
|
/// nested parameters. If the nested parameters object has a parameter called `bar`, then that
|
|
|
|
/// parameter will belong to the group `Foo {array_index + 1}`, and it will have the renamed
|
|
|
|
/// parameter ID `bar_{array_index + 1}`.
|
|
|
|
///
|
|
|
|
/// This does **not** support persistent fields.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// This implementation is safe when using from the wrapper because the plugin's returned `Params`
|
|
|
|
/// object lives in an `Arc`, and the wrapper also holds a reference to this `Arc`.
|
|
|
|
pub unsafe trait Params: 'static + Send + Sync {
|
|
|
|
/// Create a mapping from unique parameter IDs to parameter pointers along with the name of the
|
|
|
|
/// group/unit/module they are in, as a `(param_id, param_ptr, group)` triple. The order of the
|
|
|
|
/// `Vec` determines the display order in the (host's) generic UI. The group name is either an
|
|
|
|
/// empty string for top level parameters, or a slash/delimited `"group name 1/Group Name 2"` if
|
|
|
|
/// this `Params` object contains nested child objects. All components of a group path must
|
|
|
|
/// exist or you may encounter panics. The derive macro does this for every parameter field
|
|
|
|
/// marked with `#[id = "stable"]`, and it also inlines all fields from nested child `Params`
|
|
|
|
/// structs marked with `#[nested(...)]` while prefixing that group name before the parameter's
|
|
|
|
/// original group name. Dereferencing the pointers stored in the values is only valid as long
|
|
|
|
/// as this object is valid.
|
|
|
|
///
|
|
|
|
/// # Note
|
|
|
|
///
|
|
|
|
/// This uses `String` even though for the `Params` derive macro `&'static str` would have been
|
|
|
|
/// fine to be able to support custom reusable Params implementations.
|
|
|
|
fn param_map(&self) -> Vec<(String, ParamPtr, String)>;
|
|
|
|
|
|
|
|
/// Serialize all fields marked with `#[persist = "stable_name"]` into a hash map containing
|
|
|
|
/// JSON-representations of those fields so they can be written to the plugin's state and
|
2022-10-20 21:21:24 +11:00
|
|
|
/// recalled later. This uses [`persist::serialize_field()`] under the hood.
|
2022-10-20 21:10:35 +11:00
|
|
|
fn serialize_fields(&self) -> BTreeMap<String, String> {
|
|
|
|
BTreeMap::new()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Restore all fields marked with `#[persist = "stable_name"]` from a hashmap created by
|
|
|
|
/// [`serialize_fields()`][Self::serialize_fields()]. All of these fields should be wrapped in a
|
2022-10-20 21:21:24 +11:00
|
|
|
/// [`persist::PersistentField`] with thread safe interior mutability, like an `RwLock` or a
|
|
|
|
/// `Mutex`. This gets called when the plugin's state is being restored. This uses
|
|
|
|
/// [`persist::deserialize_field()`] under the hood.
|
2022-10-20 21:10:35 +11:00
|
|
|
#[allow(unused_variables)]
|
|
|
|
fn deserialize_fields(&self, serialized: &BTreeMap<String, String>) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This may be useful when building generic UIs using nested `Params` objects.
|
|
|
|
unsafe impl<P: Params> Params for Arc<P> {
|
|
|
|
fn param_map(&self) -> Vec<(String, ParamPtr, String)> {
|
|
|
|
self.as_ref().param_map()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn serialize_fields(&self) -> BTreeMap<String, String> {
|
|
|
|
self.as_ref().serialize_fields()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn deserialize_fields(&self, serialized: &BTreeMap<String, String>) {
|
|
|
|
self.as_ref().deserialize_fields(serialized)
|
|
|
|
}
|
|
|
|
}
|