Skip to main content

beamer_core/
parameter_info.rs

1//! Parameter metadata types.
2//!
3//! This module provides types for describing parameter metadata:
4//! - [`ParameterInfo`] - Complete parameter description (name, range, flags, etc.)
5//! - [`ParameterFlags`] - Behavioral flags (automation, bypass, list, etc.)
6//! - [`ParameterUnit`] - Unit type hints for AU host control rendering
7
8use crate::parameter_groups::{GroupId, ROOT_GROUP_ID};
9use crate::types::{ParameterId, ParameterValue};
10
11/// AudioUnitParameterUnit values for parameter type hints.
12///
13/// These values tell AU hosts what visual control to render for a parameter:
14/// - `Boolean` → Checkbox
15/// - `Indexed` → Dropdown menu
16/// - `Decibels`, `Hertz`, etc. → Slider with appropriate unit display
17///
18/// The values match Apple's `AudioUnitParameterUnit` enum from
19/// `AudioToolbox/AudioUnitProperties.h` for direct FFI compatibility.
20///
21/// # Example
22///
23/// ```ignore
24/// // Most constructors set this automatically:
25/// let gain = FloatParameter::db("Gain", 0.0, -60.0..=12.0);  // → Decibels
26/// let enabled = BoolParameter::new("Enabled", true);         // → Boolean
27///
28/// // Override if needed:
29/// let custom = FloatParameter::new("Custom", 0.5, 0.0..=1.0)
30///     .with_unit(ParameterUnit::Percent);
31/// ```
32#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
33#[repr(u32)]
34pub enum ParameterUnit {
35    /// Generic parameter (default slider)
36    #[default]
37    Generic = 0,
38    /// Indexed parameter (dropdown menu for enums)
39    Indexed = 1,
40    /// Boolean parameter (checkbox)
41    Boolean = 2,
42    /// Percentage (0-100%)
43    Percent = 3,
44    /// Time in seconds
45    Seconds = 4,
46    /// Sample frames
47    SampleFrames = 5,
48    /// Phase (0-360 degrees or 0-1)
49    Phase = 6,
50    /// Rate multiplier
51    Rate = 7,
52    /// Frequency in Hertz
53    Hertz = 8,
54    /// Pitch in cents
55    Cents = 9,
56    /// Relative pitch in semitones
57    RelativeSemiTones = 10,
58    /// MIDI note number (0-127)
59    MidiNoteNumber = 11,
60    /// MIDI controller value (0-127)
61    MidiController = 12,
62    /// Level in decibels
63    Decibels = 13,
64    /// Linear gain (0.0-1.0+)
65    LinearGain = 14,
66    /// Angle in degrees
67    Degrees = 15,
68    /// Equal power crossfade
69    EqualPowerCrossfade = 16,
70    /// Mixer fader curve 1
71    MixerFaderCurve1 = 17,
72    /// Stereo pan (-1 to +1)
73    Pan = 18,
74    /// Distance in meters
75    Meters = 19,
76    /// Absolute pitch in cents
77    AbsoluteCents = 20,
78    /// Pitch in octaves
79    Octaves = 21,
80    /// Tempo in beats per minute
81    Bpm = 22,
82    /// Musical beats
83    Beats = 23,
84    /// Time in milliseconds
85    Milliseconds = 24,
86    /// Ratio (e.g., compression ratio)
87    Ratio = 25,
88    /// Custom unit (use `units` string for display)
89    CustomUnit = 26,
90}
91
92/// Flags controlling parameter behavior.
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct ParameterFlags {
95    /// Parameter can be automated by the host.
96    pub can_automate: bool,
97    /// Parameter is read-only (display only).
98    pub is_readonly: bool,
99    /// Parameter is the bypass switch.
100    pub is_bypass: bool,
101    /// Parameter should be displayed as a dropdown list (for enums).
102    /// When true, host shows text labels from getParameterStringByValue().
103    pub is_list: bool,
104    /// Parameter is hidden from the DAW's parameter list.
105    /// Used for internal parameters like MIDI CC emulation.
106    pub is_hidden: bool,
107}
108
109impl Default for ParameterFlags {
110    fn default() -> Self {
111        Self {
112            can_automate: true,
113            is_readonly: false,
114            is_bypass: false,
115            is_list: false,
116            is_hidden: false,
117        }
118    }
119}
120
121/// Metadata describing a single parameter.
122#[derive(Debug, Clone)]
123pub struct ParameterInfo {
124    /// Unique parameter identifier.
125    pub id: ParameterId,
126    /// Full parameter name (e.g., "Master Volume").
127    pub name: &'static str,
128    /// Short parameter name for constrained UIs (e.g., "Vol").
129    pub short_name: &'static str,
130    /// Unit label (e.g., "dB", "%", "Hz").
131    pub units: &'static str,
132    /// Unit type hint for AU hosts.
133    ///
134    /// This tells AU hosts what visual control to render (checkbox, dropdown, etc.).
135    /// Most parameter constructors set this automatically based on the parameter type.
136    pub unit: ParameterUnit,
137    /// Default value in normalized form (0.0 to 1.0).
138    pub default_normalized: ParameterValue,
139    /// Number of discrete steps. 0 = continuous, 1 = toggle, >1 = discrete.
140    pub step_count: i32,
141    /// Behavioral flags.
142    pub flags: ParameterFlags,
143    /// Parameter group ID. ROOT_GROUP_ID (0) for ungrouped parameters.
144    pub group_id: GroupId,
145}
146
147impl ParameterInfo {
148    /// Create a new continuous parameter with default flags.
149    pub const fn new(id: ParameterId, name: &'static str) -> Self {
150        Self {
151            id,
152            name,
153            short_name: name,
154            units: "",
155            unit: ParameterUnit::Generic,
156            default_normalized: 0.5,
157            step_count: 0,
158            flags: ParameterFlags {
159                can_automate: true,
160                is_readonly: false,
161                is_bypass: false,
162                is_list: false,
163                is_hidden: false,
164            },
165            group_id: ROOT_GROUP_ID,
166        }
167    }
168
169    /// Set the short name.
170    pub const fn with_short_name(mut self, short_name: &'static str) -> Self {
171        self.short_name = short_name;
172        self
173    }
174
175    /// Set the unit label.
176    pub const fn with_units(mut self, units: &'static str) -> Self {
177        self.units = units;
178        self
179    }
180
181    /// Set the default normalized value.
182    pub const fn with_default(mut self, default: ParameterValue) -> Self {
183        self.default_normalized = default;
184        self
185    }
186
187    /// Set the step count (0 = continuous).
188    pub const fn with_steps(mut self, steps: i32) -> Self {
189        self.step_count = steps;
190        self
191    }
192
193    /// Set parameter flags.
194    pub const fn with_flags(mut self, flags: ParameterFlags) -> Self {
195        self.flags = flags;
196        self
197    }
198
199    /// Create a bypass toggle parameter with standard configuration.
200    ///
201    /// This creates a parameter pre-configured as a bypass switch:
202    /// - Toggle (step_count = 1)
203    /// - Automatable
204    /// - Marked with `is_bypass = true` flag
205    /// - Default value = 0.0 (not bypassed)
206    ///
207    /// # Example
208    ///
209    /// ```ignore
210    /// const PARAM_BYPASS: u32 = 0;
211    ///
212    /// struct MyParameters {
213    ///     bypass: AtomicU64,
214    ///     bypass_info: ParameterInfo,
215    /// }
216    ///
217    /// impl MyParameters {
218    ///     fn new() -> Self {
219    ///         Self {
220    ///             bypass: AtomicU64::new(0.0f64.to_bits()),
221    ///             bypass_info: ParameterInfo::bypass(PARAM_BYPASS),
222    ///         }
223    ///     }
224    /// }
225    /// ```
226    pub const fn bypass(id: ParameterId) -> Self {
227        Self {
228            id,
229            name: "Bypass",
230            short_name: "Byp",
231            units: "",
232            unit: ParameterUnit::Boolean,
233            default_normalized: 0.0,
234            step_count: 1,
235            flags: ParameterFlags {
236                can_automate: true,
237                is_readonly: false,
238                is_bypass: true,
239                is_list: false,
240                is_hidden: false,
241            },
242            group_id: ROOT_GROUP_ID,
243        }
244    }
245
246    /// Set the unit type hint for AU hosts.
247    ///
248    /// This is typically set automatically by parameter constructors, but can be
249    /// overridden if needed.
250    pub const fn with_unit(mut self, unit: ParameterUnit) -> Self {
251        self.unit = unit;
252        self
253    }
254
255    /// Set the group ID (parameter group).
256    pub const fn with_group(mut self, group_id: GroupId) -> Self {
257        self.group_id = group_id;
258        self
259    }
260}