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}