ot_tools_io/
common_options.rs

1//! Common options -- mostly those related to [`crate::SampleSettingsFile`] and
2//! [`crate::projects::slots::SlotAttributes`] types.
3
4use crate::{OptionEnumValueConvert, OtToolsIoErrors, RBoxErr};
5use serde::{Deserialize, Serialize};
6
7/// Sample Timestrech options.
8/// See Octatrack Manaul section 13.2.4 ATTRIBUTES
9#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq)]
10pub enum TimestrechMode {
11    /// No timestreching applied.
12    Off = 0,
13
14    /// Regular timestreching.
15    #[default]
16    Normal = 2,
17
18    /// Drum / Rythmic specific algorithm
19    Beat = 3,
20}
21
22impl OptionEnumValueConvert<u32> for TimestrechMode {
23    fn from_value(v: &u32) -> RBoxErr<Self> {
24        match v {
25            0 => Ok(TimestrechMode::Off),
26            2 => Ok(TimestrechMode::Normal),
27            3 => Ok(TimestrechMode::Beat),
28            _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
29        }
30    }
31
32    fn value(&self) -> RBoxErr<u32> {
33        Ok(*self as u32)
34    }
35}
36
37/// Sample attributes Loop mode options.
38/// See Octatrack Manaul section 13.2.4 ATTRIBUTES
39
40#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq)]
41pub enum LoopMode {
42    /// Loop points are ignored and sample will never loop.
43    #[default]
44    Off = 0,
45
46    /// Loop by starting again at the loop start position once playback of the sample reaches loop end.
47    Normal = 1,
48
49    /// Loop by continuously reversing once playback of the sample reaches loop end/loop start.
50    PingPong = 2,
51}
52
53impl OptionEnumValueConvert<u32> for LoopMode {
54    fn from_value(v: &u32) -> RBoxErr<Self> {
55        match v {
56            0 => Ok(LoopMode::Off),
57            1 => Ok(LoopMode::Normal),
58            2 => Ok(LoopMode::PingPong),
59            _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
60        }
61    }
62
63    fn value(&self) -> RBoxErr<u32> {
64        Ok(*self as u32)
65    }
66}
67
68/// Sample attributes Trig Quantization options
69/// (quantization when manually triggering samples via track buttons).
70/// See Octatrack Manaul section 13.2.4 ATTRIBUTES
71
72#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq)]
73#[repr(u32)]
74pub enum TrigQuantizationMode {
75    /// Play back immediately, no quantization.
76    #[default]
77    Direct = 255,
78
79    /// Play once the pattern ends
80    PatternLength = 0,
81
82    /// Play after 1 sequencer step(s).
83    OneStep = 1,
84
85    /// Play after 2 sequencer step(s).
86    TwoSteps = 2,
87
88    /// Play after 3 sequencer step(s).
89    ThreeSteps = 3,
90
91    /// Play after 4 sequencer step(s).
92    FourSteps = 4,
93
94    /// Play after 6 sequencer step(s).
95    SixSteps = 5,
96
97    /// Play after 8 sequencer step(s).
98    EightSteps = 6,
99
100    /// Play after 12 sequencer step(s).
101    TwelveSteps = 7,
102
103    /// Play after 16 sequencer step(s).
104    SixteenSteps = 8,
105
106    /// Play after 24 sequencer step(s).
107    TwentyFourSteps = 9,
108
109    /// Play after 32 sequencer step(s).
110    ThirtyTwoSteps = 10,
111
112    /// Play after 48 sequencer step(s).
113    FourtyEightSteps = 11,
114
115    /// Play after 64 sequencer step(s).
116    SixtyFourSteps = 12,
117
118    /// Play after 96 sequencer step(s).
119    NinetySixSteps = 13,
120
121    /// Play after 128 sequencer step(s).
122    OneTwentyEightSteps = 14,
123
124    /// Play after 192 sequencer step(s).
125    OneNinetyTwoSteps = 15,
126
127    /// Play after 256 sequencer step(s).
128    TwoFiveSixSteps = 16,
129}
130
131impl OptionEnumValueConvert<u32> for TrigQuantizationMode {
132    fn from_value(v: &u32) -> RBoxErr<Self> {
133        match v {
134            255 => Ok(TrigQuantizationMode::Direct),
135            0 => Ok(TrigQuantizationMode::PatternLength),
136            1 => Ok(TrigQuantizationMode::OneStep),
137            2 => Ok(TrigQuantizationMode::TwoSteps),
138            3 => Ok(TrigQuantizationMode::ThreeSteps),
139            4 => Ok(TrigQuantizationMode::FourSteps),
140            5 => Ok(TrigQuantizationMode::SixSteps),
141            6 => Ok(TrigQuantizationMode::EightSteps),
142            7 => Ok(TrigQuantizationMode::TwelveSteps),
143            8 => Ok(TrigQuantizationMode::SixteenSteps),
144            9 => Ok(TrigQuantizationMode::TwentyFourSteps),
145            10 => Ok(TrigQuantizationMode::ThirtyTwoSteps),
146            11 => Ok(TrigQuantizationMode::FourtyEightSteps),
147            12 => Ok(TrigQuantizationMode::SixtyFourSteps),
148            13 => Ok(TrigQuantizationMode::NinetySixSteps),
149            14 => Ok(TrigQuantizationMode::OneTwentyEightSteps),
150            15 => Ok(TrigQuantizationMode::OneNinetyTwoSteps),
151            16 => Ok(TrigQuantizationMode::TwoFiveSixSteps),
152            _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
153        }
154    }
155
156    fn value(&self) -> RBoxErr<u32> {
157        Ok(*self as u32)
158    }
159}
160
161/// "Specification" tests ... ie. guarantee that enum values match correct values.
162#[cfg(test)]
163#[allow(unused_imports)]
164mod test_spec {
165
166    mod ot_trig_quantize_mode {
167
168        mod value {
169            use crate::OptionEnumValueConvert;
170            use crate::TrigQuantizationMode;
171
172            #[test]
173            fn test_direct() {
174                assert_eq!(TrigQuantizationMode::Direct.value().unwrap(), 255);
175            }
176            #[test]
177            fn test_patternlen() {
178                assert_eq!(TrigQuantizationMode::PatternLength.value().unwrap(), 0);
179            }
180            #[test]
181            fn test_1() {
182                assert_eq!(TrigQuantizationMode::OneStep.value().unwrap(), 1);
183            }
184            #[test]
185            fn test_2() {
186                assert_eq!(TrigQuantizationMode::TwoSteps.value().unwrap(), 2);
187            }
188            #[test]
189            fn test_3() {
190                assert_eq!(TrigQuantizationMode::ThreeSteps.value().unwrap(), 3);
191            }
192            #[test]
193            fn test_4() {
194                assert_eq!(TrigQuantizationMode::FourSteps.value().unwrap(), 4);
195            }
196            #[test]
197            fn test_6() {
198                assert_eq!(TrigQuantizationMode::SixSteps.value().unwrap(), 5);
199            }
200            #[test]
201            fn test_8() {
202                assert_eq!(TrigQuantizationMode::EightSteps.value().unwrap(), 6);
203            }
204            #[test]
205            fn test_12() {
206                assert_eq!(TrigQuantizationMode::TwelveSteps.value().unwrap(), 7);
207            }
208            #[test]
209            fn test_16() {
210                assert_eq!(TrigQuantizationMode::SixteenSteps.value().unwrap(), 8);
211            }
212            #[test]
213            fn test_24() {
214                assert_eq!(TrigQuantizationMode::TwentyFourSteps.value().unwrap(), 9);
215            }
216            #[test]
217            fn test_32() {
218                assert_eq!(TrigQuantizationMode::ThirtyTwoSteps.value().unwrap(), 10);
219            }
220            #[test]
221            fn test_48() {
222                assert_eq!(TrigQuantizationMode::FourtyEightSteps.value().unwrap(), 11);
223            }
224            #[test]
225            fn test_64() {
226                assert_eq!(TrigQuantizationMode::SixtyFourSteps.value().unwrap(), 12);
227            }
228            #[test]
229            fn test_96() {
230                assert_eq!(TrigQuantizationMode::NinetySixSteps.value().unwrap(), 13);
231            }
232            #[test]
233            fn test_128() {
234                assert_eq!(
235                    TrigQuantizationMode::OneTwentyEightSteps.value().unwrap(),
236                    14
237                );
238            }
239            #[test]
240            fn test_192() {
241                assert_eq!(TrigQuantizationMode::OneNinetyTwoSteps.value().unwrap(), 15);
242            }
243            #[test]
244            fn test_256() {
245                assert_eq!(TrigQuantizationMode::TwoFiveSixSteps.value().unwrap(), 16);
246            }
247        }
248
249        mod from_value {
250            use crate::OptionEnumValueConvert;
251            use crate::TrigQuantizationMode;
252
253            #[test]
254            fn test_error() {
255                assert!(TrigQuantizationMode::from_value(&200).is_err());
256            }
257            #[test]
258            fn test_direct() {
259                assert_eq!(
260                    TrigQuantizationMode::Direct,
261                    TrigQuantizationMode::from_value(&255).unwrap()
262                );
263            }
264            #[test]
265            fn test_patternlen() {
266                assert_eq!(
267                    TrigQuantizationMode::PatternLength,
268                    TrigQuantizationMode::from_value(&0).unwrap()
269                );
270            }
271            #[test]
272            fn test_1() {
273                assert_eq!(
274                    TrigQuantizationMode::OneStep,
275                    TrigQuantizationMode::from_value(&1).unwrap()
276                );
277            }
278            #[test]
279            fn test_2() {
280                assert_eq!(
281                    TrigQuantizationMode::TwoSteps,
282                    TrigQuantizationMode::from_value(&2).unwrap()
283                );
284            }
285            #[test]
286            fn test_3() {
287                assert_eq!(
288                    TrigQuantizationMode::ThreeSteps,
289                    TrigQuantizationMode::from_value(&3).unwrap()
290                );
291            }
292            #[test]
293            fn test_4() {
294                assert_eq!(
295                    TrigQuantizationMode::FourSteps,
296                    TrigQuantizationMode::from_value(&4).unwrap()
297                );
298            }
299            #[test]
300            fn test_6() {
301                assert_eq!(
302                    TrigQuantizationMode::SixSteps,
303                    TrigQuantizationMode::from_value(&5).unwrap()
304                );
305            }
306            #[test]
307            fn test_8() {
308                assert_eq!(
309                    TrigQuantizationMode::EightSteps,
310                    TrigQuantizationMode::from_value(&6).unwrap()
311                );
312            }
313            #[test]
314            fn test_12() {
315                assert_eq!(
316                    TrigQuantizationMode::TwelveSteps,
317                    TrigQuantizationMode::from_value(&7).unwrap()
318                );
319            }
320            #[test]
321            fn test_16() {
322                assert_eq!(
323                    TrigQuantizationMode::SixteenSteps,
324                    TrigQuantizationMode::from_value(&8).unwrap()
325                );
326            }
327            #[test]
328            fn test_24() {
329                assert_eq!(
330                    TrigQuantizationMode::TwentyFourSteps,
331                    TrigQuantizationMode::from_value(&9).unwrap()
332                );
333            }
334            #[test]
335            fn test_32() {
336                assert_eq!(
337                    TrigQuantizationMode::ThirtyTwoSteps,
338                    TrigQuantizationMode::from_value(&10).unwrap()
339                );
340            }
341            #[test]
342            fn test_48() {
343                assert_eq!(
344                    TrigQuantizationMode::FourtyEightSteps,
345                    TrigQuantizationMode::from_value(&11).unwrap()
346                );
347            }
348            #[test]
349            fn test_64() {
350                assert_eq!(
351                    TrigQuantizationMode::SixtyFourSteps,
352                    TrigQuantizationMode::from_value(&12).unwrap()
353                );
354            }
355            #[test]
356            fn test_96() {
357                assert_eq!(
358                    TrigQuantizationMode::NinetySixSteps,
359                    TrigQuantizationMode::from_value(&13).unwrap()
360                );
361            }
362            #[test]
363            fn test_128() {
364                assert_eq!(
365                    TrigQuantizationMode::OneTwentyEightSteps,
366                    TrigQuantizationMode::from_value(&14).unwrap()
367                );
368            }
369            #[test]
370            fn test_192() {
371                assert_eq!(
372                    TrigQuantizationMode::OneNinetyTwoSteps,
373                    TrigQuantizationMode::from_value(&15).unwrap()
374                );
375            }
376            #[test]
377            fn test_256() {
378                assert_eq!(
379                    TrigQuantizationMode::TwoFiveSixSteps,
380                    TrigQuantizationMode::from_value(&16).unwrap()
381                );
382            }
383        }
384    }
385
386    mod ot_timestrech_mode {
387
388        mod value {
389            use crate::OptionEnumValueConvert;
390            use crate::TimestrechMode;
391
392            #[test]
393            fn test_off_value() {
394                assert_eq!(TimestrechMode::Off.value().unwrap(), 0);
395            }
396            #[test]
397            fn test_normal_value() {
398                assert_eq!(TimestrechMode::Normal.value().unwrap(), 2);
399            }
400            #[test]
401            fn test_beat_value() {
402                assert_eq!(TimestrechMode::Beat.value().unwrap(), 3);
403            }
404        }
405
406        mod from_value {
407            use crate::OptionEnumValueConvert;
408            use crate::TimestrechMode;
409
410            #[test]
411            fn test_error() {
412                // not in a sequental range with other values
413                // dunno why they implemented it to skip value of 1, possible bug or easter egg?
414                assert!(TimestrechMode::from_value(&1).is_err());
415                // do a slightly exhausitve check, but don't test the whole u32 range
416                // as it's not worth the performance drain
417                for i in 4..u8::MAX {
418                    let b = i as u32;
419                    assert!(TimestrechMode::from_value(&b).is_err());
420                }
421            }
422            #[test]
423            fn test_off_from_value() {
424                assert_eq!(TimestrechMode::Off, TimestrechMode::from_value(&0).unwrap());
425            }
426            #[test]
427            fn test_normal_from_value() {
428                assert_eq!(
429                    TimestrechMode::Normal,
430                    TimestrechMode::from_value(&2).unwrap()
431                );
432            }
433            #[test]
434            fn test_beat_from_value() {
435                assert_eq!(
436                    TimestrechMode::Beat,
437                    TimestrechMode::from_value(&3).unwrap()
438                );
439            }
440        }
441    }
442
443    mod ot_loop_mode {
444
445        mod value {
446            use crate::LoopMode;
447            use crate::OptionEnumValueConvert;
448
449            #[test]
450            fn test_off_value() {
451                assert_eq!(LoopMode::Off.value().unwrap(), 0);
452            }
453            #[test]
454            fn test_normal_value() {
455                assert_eq!(LoopMode::Normal.value().unwrap(), 1);
456            }
457            #[test]
458            fn test_beat_value() {
459                assert_eq!(LoopMode::PingPong.value().unwrap(), 2);
460            }
461        }
462
463        mod from_value {
464            use crate::LoopMode;
465            use crate::OptionEnumValueConvert;
466
467            #[test]
468            fn test_error() {
469                // do a slightly exhausitve check, but don't test the whole u32 range
470                // as it's not worth the performance drain
471                for i in 3..u8::MAX {
472                    let x = i as u32;
473                    assert!(LoopMode::from_value(&x).is_err());
474                }
475            }
476            #[test]
477            fn test_off_from_value() {
478                assert_eq!(LoopMode::Off, LoopMode::from_value(&0).unwrap());
479            }
480            #[test]
481            fn test_normal_from_value() {
482                assert_eq!(LoopMode::Normal, LoopMode::from_value(&1).unwrap());
483            }
484            #[test]
485            fn test_beat_from_value() {
486                assert_eq!(LoopMode::PingPong, LoopMode::from_value(&2).unwrap());
487            }
488        }
489    }
490}