Skip to main content

Params

Trait Params 

Source
pub trait Params:
    Sealed
    + Send
    + Sync
    + 'static {
Show 18 methods // Required methods fn param_infos(&self) -> Vec<ParamInfo>; fn count(&self) -> usize; fn get_normalized(&self, id: u32) -> Option<f64>; fn set_normalized(&self, id: u32, value: f64); fn get_plain(&self, id: u32) -> Option<f64>; fn set_plain(&self, id: u32, value: f64); fn format_value(&self, id: u32, value: f64) -> Option<String>; fn parse_value(&self, id: u32, text: &str) -> Option<f64>; fn snap_smoothers(&self); fn set_sample_rate(&self, sample_rate: f64); fn collect_values(&self) -> (Vec<u32>, Vec<f64>); fn restore_values(&self, values: &[(u32, f64)]); // Provided methods fn append_param_infos(&self, into: &mut Vec<ParamInfo>) { ... } fn param_infos_static() -> Vec<ParamInfo> where Self: Sized { ... } fn meter_ids(&self) -> Vec<u32> { ... } fn set_normalized_returning_plain(&self, id: u32, value: f64) -> f64 { ... } fn set_normalized_returning_normalized(&self, id: u32, value: f64) -> f64 { ... } fn assert_no_id_collisions(&self) { ... }
}
Expand description

Trait implemented by #[derive(Params)] on a struct. Format wrappers use this to enumerate, read, and write parameters.

Stays dyn-compatible (every method dispatches through &self) so editors can pass Arc<dyn Params> into the screenshot pipeline without naming the concrete type. Generic code that needs to construct a fresh Params value should add a Default bound rather than expecting one on the trait - #[derive(Params)] emits impl Default alongside the trait impl, so that bound is free for derive users.

Required Methods§

Source

fn param_infos(&self) -> Vec<ParamInfo>

All parameter infos, in declaration order.

Source

fn count(&self) -> usize

Number of parameters.

Source

fn get_normalized(&self, id: u32) -> Option<f64>

Get normalized value (0.0–1.0) by ID.

Source

fn set_normalized(&self, id: u32, value: f64)

Set normalized value (0.0–1.0) by ID.

Takes &self, not &mut self - the per-param storage in FloatParam / BoolParam / IntParam / EnumParam is built on AtomicU32 / AtomicU64, so writes go through interior mutability. Format wrappers, GUI editors, and the audio thread all hold &Params (or Arc<Params>) concurrently and write without coordination - every implementation must be sound under concurrent &self writes from multiple threads.

Source

fn get_plain(&self, id: u32) -> Option<f64>

Get plain value by ID.

Source

fn set_plain(&self, id: u32, value: f64)

Set plain value by ID.

Same &self interior-mutability contract as Self::set_normalized.

Source

fn format_value(&self, id: u32, value: f64) -> Option<String>

Format a plain value to display string.

Source

fn parse_value(&self, id: u32, text: &str) -> Option<f64>

Parse a display string to plain value.

Source

fn snap_smoothers(&self)

Reset all smoothers to current values.

Source

fn set_sample_rate(&self, sample_rate: f64)

Update smoother sample rates.

Source

fn collect_values(&self) -> (Vec<u32>, Vec<f64>)

Collect all parameter IDs and their current plain values.

Source

fn restore_values(&self, values: &[(u32, f64)])

Restore parameter values from a list of (id, value) pairs.

Provided Methods§

Source

fn append_param_infos(&self, into: &mut Vec<ParamInfo>)

Append parameter infos onto an existing buffer. Default impl delegates to Self::param_infos and extends; the derive macro overrides for nested structs so deep trees don’t pay O(depth) intermediate Vec allocations per outer call.

Source

fn param_infos_static() -> Vec<ParamInfo>
where Self: Sized,

Static parameter metadata, available without an instance.

Format wrappers’ register_* paths call this to learn the parameter set without constructing a full plugin. The instance-based alternative would pay for any allocation the constructor does (DSP buffers, FFT plans, image atlases, etc.) at static-init time, which is fragile under AAX’s Describe running before main. The derive macro overrides this with a LazyLock-cached Vec<ParamInfo> built from the same compile-time metadata it uses for Self::param_infos, so registration becomes allocation-free after the first call.

Default impl returns an empty vec - hand-written Params impls that don’t override fall through to the runtime path inside PluginExport::param_infos_static. Gated by Self: Sized so adding the method preserves dyn-compatibility for the existing &self-method shape (&dyn Params skips this slot).

Source

fn meter_ids(&self) -> Vec<u32>

IDs of every #[meter] slot declared on the params struct (including nested subtrees), in declaration order. Default impl returns empty - only structs that declare meters need to override. The derive macro implements it automatically.

Format wrappers that expose DSP-side meters back to the UI (LV2’s output control ports, for instance) use this to know which IDs to poll each process().

Source

fn set_normalized_returning_plain(&self, id: u32, value: f64) -> f64

Set normalized value and read back the resulting plain value in one call. CLAP / AU forward the plain value to the host’s automation channel after a GUI write. The default impl is the obvious set_normalized then get_plain; concrete Params implementations that can compute both in one trait dispatch (e.g. the #[derive(Params)] output) should override for a single match-arm walk.

Source

fn set_normalized_returning_normalized(&self, id: u32, value: f64) -> f64

Set normalized value and read back the (post-clamp / post-step) normalized value in one call. VST3 / VST2 / AAX forward normalized values to the host’s automation channel. Same override-for-single-dispatch contract as Self::set_normalized_returning_plain.

Source

fn assert_no_id_collisions(&self)

Walk every parameter and meter ID reachable from self (including nested #[nested] substructs) and panic on the first duplicate.

Why this isn’t just a compile-time check: the #[derive(Params)] collision check at expansion time only sees IDs declared in the current struct. A parent param id = 5 and a nested-substruct param id = 5 both compile, because the parent derive doesn’t see into the nested type. At runtime, the set_plain / get_plain dispatcher matches at the outer level first and silently never reaches the nested one - preset round-trips would corrupt the nested value. This method makes that bug surface as a panic at plugin construction instead of as quiet state loss.

Called automatically by the derive-generated Self::new(). Plugin code shouldn’t need to invoke it directly.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§