nice_plug_core/params/
enums.rs1use std::fmt::{Debug, Display};
4use std::marker::PhantomData;
5use std::sync::Arc;
6
7use super::internals::ParamPtr;
8use super::range::IntRange;
9use super::{IntParam, InternalParamMut, Param, ParamFlags};
10
11pub use nice_plug_derive::Enum;
13
14pub trait Enum {
49 fn variants() -> &'static [&'static str];
53
54 fn ids() -> Option<&'static [&'static str]>;
58
59 fn to_index(self) -> usize;
63
64 fn from_index(index: usize) -> Self;
68}
69
70pub struct EnumParam<T: Enum + PartialEq> {
74 inner: EnumParamInner,
77
78 _marker: PhantomData<T>,
81}
82
83pub struct EnumParamInner {
86 pub(crate) inner: IntParam,
88 variants: &'static [&'static str],
90 ids: Option<&'static [&'static str]>,
95}
96
97impl<T: Enum + PartialEq> Display for EnumParam<T> {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 Display::fmt(&self.inner, f)
100 }
101}
102
103impl Display for EnumParamInner {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 write!(
106 f,
107 "{}",
108 self.variants[self.inner.modulated_plain_value() as usize]
109 )
110 }
111}
112
113impl<T: Enum + PartialEq> Debug for EnumParam<T> {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 Debug::fmt(&self.inner, f)
116 }
117}
118
119impl Debug for EnumParamInner {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 if self.inner.modulated_plain_value() != self.inner.unmodulated_plain_value() {
123 write!(f, "{}: {} (modulated)", self.name(), self)
124 } else {
125 write!(f, "{}: {}", self.name(), self)
126 }
127 }
128}
129
130impl<T: Enum + PartialEq> super::Sealed for EnumParam<T> {}
132
133impl<T: Enum + PartialEq> Param for EnumParam<T> {
134 type Plain = T;
135
136 fn name(&self) -> &str {
137 self.inner.name()
138 }
139
140 fn unit(&self) -> &'static str {
141 self.inner.unit()
142 }
143
144 fn poly_modulation_id(&self) -> Option<u32> {
145 self.inner.poly_modulation_id()
146 }
147
148 #[inline]
149 fn modulated_plain_value(&self) -> Self::Plain {
150 T::from_index(self.inner.modulated_plain_value() as usize)
151 }
152
153 #[inline]
154 fn modulated_normalized_value(&self) -> f32 {
155 self.inner.modulated_normalized_value()
156 }
157
158 #[inline]
159 fn unmodulated_plain_value(&self) -> Self::Plain {
160 T::from_index(self.inner.unmodulated_plain_value() as usize)
161 }
162
163 #[inline]
164 fn unmodulated_normalized_value(&self) -> f32 {
165 self.inner.unmodulated_normalized_value()
166 }
167
168 #[inline]
169 fn default_plain_value(&self) -> Self::Plain {
170 T::from_index(self.inner.default_plain_value() as usize)
171 }
172
173 fn step_count(&self) -> Option<usize> {
174 self.inner.step_count()
175 }
176
177 fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
178 T::from_index(self.inner.previous_step(T::to_index(from) as i32, finer) as usize)
179 }
180
181 fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
182 T::from_index(self.inner.next_step(T::to_index(from) as i32, finer) as usize)
183 }
184
185 fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String {
186 self.inner
187 .normalized_value_to_string(normalized, include_unit)
188 }
189
190 fn string_to_normalized_value(&self, string: &str) -> Option<f32> {
191 self.inner.string_to_normalized_value(string)
192 }
193
194 #[inline]
195 fn preview_normalized(&self, plain: Self::Plain) -> f32 {
196 self.inner.preview_normalized(T::to_index(plain) as i32)
197 }
198
199 #[inline]
200 fn preview_plain(&self, normalized: f32) -> Self::Plain {
201 T::from_index(self.inner.preview_plain(normalized) as usize)
202 }
203
204 fn flags(&self) -> ParamFlags {
205 self.inner.flags()
206 }
207
208 fn as_ptr(&self) -> ParamPtr {
209 self.inner.as_ptr()
210 }
211}
212
213impl super::Sealed for EnumParamInner {}
215
216impl Param for EnumParamInner {
217 type Plain = i32;
218
219 fn name(&self) -> &str {
220 self.inner.name()
221 }
222
223 fn unit(&self) -> &'static str {
224 ""
225 }
226
227 fn poly_modulation_id(&self) -> Option<u32> {
228 self.inner.poly_modulation_id()
229 }
230
231 #[inline]
232 fn modulated_plain_value(&self) -> Self::Plain {
233 self.inner.modulated_plain_value()
234 }
235
236 #[inline]
237 fn modulated_normalized_value(&self) -> f32 {
238 self.inner.modulated_normalized_value()
239 }
240
241 #[inline]
242 fn default_plain_value(&self) -> Self::Plain {
243 self.inner.default_plain_value()
244 }
245
246 #[inline]
247 fn unmodulated_plain_value(&self) -> Self::Plain {
248 self.inner.unmodulated_plain_value()
249 }
250
251 #[inline]
252 fn unmodulated_normalized_value(&self) -> f32 {
253 self.inner.unmodulated_normalized_value()
254 }
255
256 fn step_count(&self) -> Option<usize> {
257 Some(self.len() - 1)
258 }
259
260 fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
261 self.inner.previous_step(from, finer)
262 }
263
264 fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
265 self.inner.next_step(from, finer)
266 }
267
268 fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
269 let index = self.preview_plain(normalized);
270 self.variants[index as usize].to_string()
271 }
272
273 fn string_to_normalized_value(&self, string: &str) -> Option<f32> {
274 let string = string.trim();
275 self.variants
276 .iter()
277 .position(|variant| variant == &string)
278 .map(|idx| self.preview_normalized(idx as i32))
279 }
280
281 #[inline]
282 fn preview_normalized(&self, plain: Self::Plain) -> f32 {
283 self.inner.preview_normalized(plain)
284 }
285
286 #[inline]
287 fn preview_plain(&self, normalized: f32) -> Self::Plain {
288 self.inner.preview_plain(normalized)
289 }
290
291 fn flags(&self) -> ParamFlags {
292 self.inner.flags()
293 }
294
295 fn as_ptr(&self) -> ParamPtr {
296 ParamPtr::EnumParam(self as *const EnumParamInner as *mut EnumParamInner)
297 }
298}
299
300impl<T: Enum + PartialEq> InternalParamMut for EnumParam<T> {
301 unsafe fn _internal_set_plain_value(&self, plain: Self::Plain) -> bool {
302 unsafe {
303 self.inner
304 ._internal_set_plain_value(T::to_index(plain) as i32)
305 }
306 }
307
308 unsafe fn _internal_set_normalized_value(&self, normalized: f32) -> bool {
309 unsafe { self.inner._internal_set_normalized_value(normalized) }
310 }
311
312 unsafe fn _internal_modulate_value(&self, modulation_offset: f32) -> bool {
313 unsafe { self.inner._internal_modulate_value(modulation_offset) }
314 }
315
316 unsafe fn _internal_update_smoother(&self, sample_rate: f32, reset: bool) {
317 unsafe { self.inner._internal_update_smoother(sample_rate, reset) }
318 }
319}
320
321impl InternalParamMut for EnumParamInner {
322 unsafe fn _internal_set_plain_value(&self, plain: Self::Plain) -> bool {
323 unsafe { self.inner._internal_set_plain_value(plain) }
324 }
325
326 unsafe fn _internal_set_normalized_value(&self, normalized: f32) -> bool {
327 unsafe { self.inner._internal_set_normalized_value(normalized) }
328 }
329
330 unsafe fn _internal_modulate_value(&self, modulation_offset: f32) -> bool {
331 unsafe { self.inner._internal_modulate_value(modulation_offset) }
332 }
333
334 unsafe fn _internal_update_smoother(&self, sample_rate: f32, reset: bool) {
335 unsafe { self.inner._internal_update_smoother(sample_rate, reset) }
336 }
337}
338
339impl<T: Enum + PartialEq + 'static> EnumParam<T> {
340 pub fn new(name: impl Into<String>, default: T) -> Self {
343 let variants = T::variants();
344 let ids = T::ids();
345
346 Self {
347 inner: EnumParamInner {
348 inner: IntParam::new(
349 name,
350 T::to_index(default) as i32,
351 IntRange::Linear {
352 min: 0,
353 max: variants.len() as i32 - 1,
354 },
355 ),
356 variants,
357 ids,
358 },
359 _marker: PhantomData,
360 }
361 }
362
363 #[inline]
365 pub fn value(&self) -> T {
366 self.modulated_plain_value()
367 }
368
369 pub fn with_poly_modulation_id(mut self, id: u32) -> Self {
381 self.inner.inner = self.inner.inner.with_poly_modulation_id(id);
382 self
383 }
384
385 pub fn with_callback(mut self, callback: Arc<dyn Fn(T) + Send + Sync>) -> Self {
390 self.inner.inner = self.inner.inner.with_callback(Arc::new(move |value| {
391 callback(T::from_index(value as usize))
392 }));
393 self
394 }
395
396 pub fn non_automatable(mut self) -> Self {
400 self.inner.inner = self.inner.inner.non_automatable();
401 self
402 }
403
404 pub fn hide(mut self) -> Self {
408 self.inner.inner = self.inner.inner.hide();
409 self
410 }
411
412 pub fn hide_in_generic_ui(mut self) -> Self {
415 self.inner.inner = self.inner.inner.hide_in_generic_ui();
416 self
417 }
418}
419
420impl EnumParamInner {
421 #[allow(clippy::len_without_is_empty)]
423 pub fn len(&self) -> usize {
424 self.variants.len()
425 }
426
427 pub fn unmodulated_plain_id(&self) -> Option<&'static str> {
431 let ids = &self.ids?;
432
433 Some(ids[self.unmodulated_plain_value() as usize])
435 }
436
437 pub fn set_from_id(&self, id: &str) -> bool {
440 match self
441 .ids
442 .and_then(|ids| ids.iter().position(|candidate| *candidate == id))
443 {
444 Some(index) => {
445 unsafe {
446 self._internal_set_plain_value(index as i32);
447 }
448 true
449 }
450 None => false,
451 }
452 }
453}