Skip to main content

ot_tools_io/
settings.rs

1/*
2SPDX-License-Identifier: GPL-3.0-or-later
3Copyright © 2026 Mike Robeson [dijksterhuis]
4*/
5
6//! Settings enums. Mostly related to [`crate::SampleSettingsFile`],
7//! [`crate::projects::SlotAttributes`] and [`crate::MarkersFile`] types.
8
9use ot_tools_io_derive::{
10    enum_try_from_i32_to_signed_types, enum_try_from_u32_to_unsigned_types, AsMutDerive,
11    AsRefDerive, IntoSigneds, IntoUnsigneds,
12};
13use serde::{Deserialize, Serialize};
14use std::fmt::Display;
15use thiserror::Error;
16
17/// Errors when parsing a value with [`TryFrom`] for some Enum
18#[derive(Debug, Error)]
19pub enum InvalidValueError {
20    /// Error when parsing values with [`TimeStretchMode::try_from`]
21    #[error(
22        "invalid time stretch value, only '0' (Off), '2' (Normal) and '3' (Beat) are supported values"
23    )]
24    TimeStretchMode,
25
26    /// Error when parsing values with [`LoopMode::try_from`]
27    #[error(
28        "invalid loop mode value, only '0' (Off), '1' (Normal) and '2' (PingPong) are supported values"
29    )]
30    LoopMode,
31
32    /// Error when parsing values with [`TrigQuantizationMode::try_from`]
33    #[error("invalid trig quantization value")]
34    TrigQuantizationMode,
35
36    /// Error when parsing values with [`TrigCondition::try_from`]
37    #[error("invalid trig condition value")]
38    TrigCondition,
39
40    /// Error when parsing values with [`ProgChMidiChannel::try_from`]
41    #[error("invalid Program Change MIDI Channel value")]
42    ProgChMidiChannel,
43
44    /// Error when parsing values with [`SlotType::try_from`]
45    #[error("invalid slot type value, only 'FLEX' and 'STATIC' are supported values")]
46    SlotType,
47}
48
49/// Sample Time Stretch options.
50/// See Octatrack Manual section 13.2.4 ATTRIBUTES
51#[derive(
52    Copy,
53    Clone,
54    Debug,
55    Default,
56    Eq,
57    Hash,
58    Ord,
59    PartialEq,
60    PartialOrd,
61    Serialize,
62    Deserialize,
63    AsMutDerive,
64    AsRefDerive,
65    IntoUnsigneds,
66)]
67#[repr(u8)]
68pub enum TimeStretchMode {
69    /// No time-stretching applied.
70    Off = 0,
71
72    /// Regular time-stretching.
73    #[default]
74    Normal = 2,
75
76    /// Drum / Rhythmic specific algorithm
77    Beat = 3,
78}
79
80#[enum_try_from_u32_to_unsigned_types]
81impl TryFrom<u32> for TimeStretchMode {
82    type Error = InvalidValueError;
83    fn try_from(value: u32) -> Result<Self, Self::Error> {
84        match value {
85            0 => Ok(TimeStretchMode::Off),
86            2 => Ok(TimeStretchMode::Normal),
87            3 => Ok(TimeStretchMode::Beat),
88            _ => Err(InvalidValueError::TimeStretchMode),
89        }
90    }
91}
92
93#[cfg(test)]
94mod ot_time_stretch_mode {
95    mod value {
96        use crate::settings::TimeStretchMode;
97
98        #[test]
99        fn test_off_value() {
100            assert_eq!(TimeStretchMode::Off as u8, 0_u8);
101        }
102        #[test]
103        fn test_normal_value() {
104            assert_eq!(TimeStretchMode::Normal as u8, 2_u8);
105        }
106        #[test]
107        fn test_beat_value() {
108            assert_eq!(TimeStretchMode::Beat as u8, 3_u8);
109        }
110    }
111
112    mod from_value {
113        use crate::settings::TimeStretchMode;
114
115        #[test]
116        fn test_error() {
117            // not in a sequential range with other values
118            // dunno why they implemented it to skip value of 1, possible bug or easter egg?
119            assert!(TimeStretchMode::try_from(&1_u8).is_err());
120            assert_eq!(TimeStretchMode::try_from(&1_u8).unwrap_err().to_string(),  "invalid time stretch value, only '0' (Off), '2' (Normal) and '3' (Beat) are supported values");
121            for x in 4..u8::MAX {
122                assert!(TimeStretchMode::try_from(&x).is_err());
123                assert_eq!(TimeStretchMode::try_from(&x).unwrap_err().to_string(),  "invalid time stretch value, only '0' (Off), '2' (Normal) and '3' (Beat) are supported values");
124            }
125        }
126        #[test]
127        fn test_off_from_value() {
128            assert_eq!(
129                TimeStretchMode::Off,
130                TimeStretchMode::try_from(&0_u8).unwrap()
131            );
132        }
133        #[test]
134        fn test_normal_from_value() {
135            assert_eq!(
136                TimeStretchMode::Normal,
137                TimeStretchMode::try_from(&2_u8).unwrap()
138            );
139        }
140        #[test]
141        fn test_beat_from_value() {
142            assert_eq!(
143                TimeStretchMode::Beat,
144                TimeStretchMode::try_from(&3_u8).unwrap()
145            );
146        }
147    }
148}
149
150/// Sample attributes Loop mode options.
151/// See Octatrack Manual section 13.2.4 ATTRIBUTES
152#[derive(
153    Copy,
154    Clone,
155    Debug,
156    Default,
157    Eq,
158    Hash,
159    Ord,
160    PartialEq,
161    PartialOrd,
162    Serialize,
163    Deserialize,
164    AsMutDerive,
165    AsRefDerive,
166    IntoUnsigneds,
167)]
168#[repr(u8)]
169pub enum LoopMode {
170    /// Loop points are ignored and sample will never loop.
171    #[default]
172    Off = 0,
173
174    /// Loop by starting again at the loop start position once playback of the sample reaches loop end.
175    Normal = 1,
176
177    /// Loop by continuously reversing once playback of the sample reaches loop end/loop start.
178    PingPong = 2,
179}
180
181#[enum_try_from_u32_to_unsigned_types]
182impl TryFrom<u32> for LoopMode {
183    type Error = InvalidValueError;
184    fn try_from(value: u32) -> Result<Self, Self::Error> {
185        match value {
186            0 => Ok(LoopMode::Off),
187            1 => Ok(LoopMode::Normal),
188            2 => Ok(LoopMode::PingPong),
189            _ => Err(InvalidValueError::LoopMode),
190        }
191    }
192}
193
194#[cfg(test)]
195mod ot_loop_mode {
196
197    mod value {
198        use crate::settings::LoopMode;
199
200        #[test]
201        fn test_off_value() {
202            assert_eq!(LoopMode::Off as u8, 0_u8);
203        }
204        #[test]
205        fn test_normal_value() {
206            assert_eq!(LoopMode::Normal as u8, 1_u8);
207        }
208        #[test]
209        fn test_beat_value() {
210            assert_eq!(LoopMode::PingPong as u8, 2_u8);
211        }
212    }
213
214    mod from_value {
215        use crate::settings::LoopMode;
216
217        #[test]
218        fn test_error() {
219            for x in 3..u8::MAX {
220                assert!(LoopMode::try_from(&x).is_err());
221                assert_eq!(LoopMode::try_from(&x).unwrap_err().to_string(), "invalid loop mode value, only '0' (Off), '1' (Normal) and '2' (PingPong) are supported values");
222            }
223        }
224        #[test]
225        fn test_off_from_value() {
226            assert_eq!(LoopMode::Off, LoopMode::try_from(&0_u8).unwrap());
227        }
228        #[test]
229        fn test_normal_from_value() {
230            assert_eq!(LoopMode::Normal, LoopMode::try_from(&1_u8).unwrap());
231        }
232        #[test]
233        fn test_beat_from_value() {
234            assert_eq!(LoopMode::PingPong, LoopMode::try_from(&2_u8).unwrap());
235        }
236    }
237}
238
239/// Sample attributes Trig Quantization options
240/// (quantization when manually triggering samples via track buttons).
241/// See Octatrack Manual section 13.2.4 ATTRIBUTES
242#[derive(
243    Copy,
244    Clone,
245    Debug,
246    Default,
247    Eq,
248    Hash,
249    Ord,
250    PartialEq,
251    PartialOrd,
252    Serialize,
253    Deserialize,
254    AsMutDerive,
255    AsRefDerive,
256    IntoUnsigneds,
257)]
258#[repr(u8)]
259pub enum TrigQuantizationMode {
260    /// Play back immediately, no quantization.
261    #[default]
262    Direct = 255,
263
264    /// Play once the pattern ends
265    PatternLength = 0,
266
267    /// Play after 1 sequencer step(s).
268    OneStep = 1,
269
270    /// Play after 2 sequencer step(s).
271    TwoSteps = 2,
272
273    /// Play after 3 sequencer step(s).
274    ThreeSteps = 3,
275
276    /// Play after 4 sequencer step(s).
277    FourSteps = 4,
278
279    /// Play after 6 sequencer step(s).
280    SixSteps = 5,
281
282    /// Play after 8 sequencer step(s).
283    EightSteps = 6,
284
285    /// Play after 12 sequencer step(s).
286    TwelveSteps = 7,
287
288    /// Play after 16 sequencer step(s).
289    SixteenSteps = 8,
290
291    /// Play after 24 sequencer step(s).
292    TwentyFourSteps = 9,
293
294    /// Play after 32 sequencer step(s).
295    ThirtyTwoSteps = 10,
296
297    /// Play after 48 sequencer step(s).
298    FortyEightSteps = 11,
299
300    /// Play after 64 sequencer step(s).
301    SixtyFourSteps = 12,
302
303    /// Play after 96 sequencer step(s).
304    NinetySixSteps = 13,
305
306    /// Play after 128 sequencer step(s).
307    OneTwentyEightSteps = 14,
308
309    /// Play after 192 sequencer step(s).
310    OneNinetyTwoSteps = 15,
311
312    /// Play after 256 sequencer step(s).
313    TwoFiveSixSteps = 16,
314}
315
316#[enum_try_from_u32_to_unsigned_types]
317impl TryFrom<u32> for TrigQuantizationMode {
318    type Error = InvalidValueError;
319    fn try_from(value: u32) -> Result<Self, Self::Error> {
320        match value {
321            255 => Ok(TrigQuantizationMode::Direct),
322            0 => Ok(TrigQuantizationMode::PatternLength),
323            1 => Ok(TrigQuantizationMode::OneStep),
324            2 => Ok(TrigQuantizationMode::TwoSteps),
325            3 => Ok(TrigQuantizationMode::ThreeSteps),
326            4 => Ok(TrigQuantizationMode::FourSteps),
327            5 => Ok(TrigQuantizationMode::SixSteps),
328            6 => Ok(TrigQuantizationMode::EightSteps),
329            7 => Ok(TrigQuantizationMode::TwelveSteps),
330            8 => Ok(TrigQuantizationMode::SixteenSteps),
331            9 => Ok(TrigQuantizationMode::TwentyFourSteps),
332            10 => Ok(TrigQuantizationMode::ThirtyTwoSteps),
333            11 => Ok(TrigQuantizationMode::FortyEightSteps),
334            12 => Ok(TrigQuantizationMode::SixtyFourSteps),
335            13 => Ok(TrigQuantizationMode::NinetySixSteps),
336            14 => Ok(TrigQuantizationMode::OneTwentyEightSteps),
337            15 => Ok(TrigQuantizationMode::OneNinetyTwoSteps),
338            16 => Ok(TrigQuantizationMode::TwoFiveSixSteps),
339            _ => Err(InvalidValueError::TrigQuantizationMode),
340        }
341    }
342}
343
344#[cfg(test)]
345mod ot_trig_quantize_mode {
346
347    mod value {
348        use crate::settings::TrigQuantizationMode;
349
350        #[test]
351        fn test_direct() {
352            assert_eq!(TrigQuantizationMode::Direct as u8, 255);
353        }
354        #[test]
355        fn test_patternlen() {
356            assert_eq!(TrigQuantizationMode::PatternLength as u8, 0);
357        }
358        #[test]
359        fn test_1() {
360            assert_eq!(TrigQuantizationMode::OneStep as u8, 1);
361        }
362        #[test]
363        fn test_2() {
364            assert_eq!(TrigQuantizationMode::TwoSteps as u8, 2);
365        }
366        #[test]
367        fn test_3() {
368            assert_eq!(TrigQuantizationMode::ThreeSteps as u8, 3);
369        }
370        #[test]
371        fn test_4() {
372            assert_eq!(TrigQuantizationMode::FourSteps as u8, 4);
373        }
374        #[test]
375        fn test_6() {
376            assert_eq!(TrigQuantizationMode::SixSteps as u8, 5);
377        }
378        #[test]
379        fn test_8() {
380            assert_eq!(TrigQuantizationMode::EightSteps as u8, 6);
381        }
382        #[test]
383        fn test_12() {
384            assert_eq!(TrigQuantizationMode::TwelveSteps as u8, 7);
385        }
386        #[test]
387        fn test_16() {
388            assert_eq!(TrigQuantizationMode::SixteenSteps as u8, 8);
389        }
390        #[test]
391        fn test_24() {
392            assert_eq!(TrigQuantizationMode::TwentyFourSteps as u8, 9);
393        }
394        #[test]
395        fn test_32() {
396            assert_eq!(TrigQuantizationMode::ThirtyTwoSteps as u8, 10);
397        }
398        #[test]
399        fn test_48() {
400            assert_eq!(TrigQuantizationMode::FortyEightSteps as u8, 11);
401        }
402        #[test]
403        fn test_64() {
404            assert_eq!(TrigQuantizationMode::SixtyFourSteps as u8, 12);
405        }
406        #[test]
407        fn test_96() {
408            assert_eq!(TrigQuantizationMode::NinetySixSteps as u8, 13);
409        }
410        #[test]
411        fn test_128() {
412            assert_eq!(TrigQuantizationMode::OneTwentyEightSteps as u8, 14);
413        }
414        #[test]
415        fn test_192() {
416            assert_eq!(TrigQuantizationMode::OneNinetyTwoSteps as u8, 15);
417        }
418        #[test]
419        fn test_256() {
420            assert_eq!(TrigQuantizationMode::TwoFiveSixSteps as u8, 16);
421        }
422    }
423
424    mod from_value {
425        use crate::settings::TrigQuantizationMode;
426
427        #[test]
428        fn test_error() {
429            for i in 17..=254_u8 {
430                assert!(TrigQuantizationMode::try_from(i).is_err());
431                assert_eq!(
432                    TrigQuantizationMode::try_from(i).unwrap_err().to_string(),
433                    "invalid trig quantization value"
434                );
435            }
436        }
437        #[test]
438        fn test_direct() {
439            assert_eq!(
440                TrigQuantizationMode::Direct,
441                TrigQuantizationMode::try_from(255_u8).unwrap()
442            );
443        }
444        #[test]
445        fn test_patternlen() {
446            assert_eq!(
447                TrigQuantizationMode::PatternLength,
448                TrigQuantizationMode::try_from(0_u8).unwrap()
449            );
450        }
451        #[test]
452        fn test_1() {
453            assert_eq!(
454                TrigQuantizationMode::OneStep,
455                TrigQuantizationMode::try_from(1_u8).unwrap()
456            );
457        }
458        #[test]
459        fn test_2() {
460            assert_eq!(
461                TrigQuantizationMode::TwoSteps,
462                TrigQuantizationMode::try_from(2_u8).unwrap()
463            );
464        }
465        #[test]
466        fn test_3() {
467            assert_eq!(
468                TrigQuantizationMode::ThreeSteps,
469                TrigQuantizationMode::try_from(3_u8).unwrap()
470            );
471        }
472        #[test]
473        fn test_4() {
474            assert_eq!(
475                TrigQuantizationMode::FourSteps,
476                TrigQuantizationMode::try_from(4_u8).unwrap()
477            );
478        }
479        #[test]
480        fn test_6() {
481            assert_eq!(
482                TrigQuantizationMode::SixSteps,
483                TrigQuantizationMode::try_from(5_u8).unwrap()
484            );
485        }
486        #[test]
487        fn test_8() {
488            assert_eq!(
489                TrigQuantizationMode::EightSteps,
490                TrigQuantizationMode::try_from(6_u8).unwrap()
491            );
492        }
493        #[test]
494        fn test_12() {
495            assert_eq!(
496                TrigQuantizationMode::TwelveSteps,
497                TrigQuantizationMode::try_from(7_u8).unwrap()
498            );
499        }
500        #[test]
501        fn test_16() {
502            assert_eq!(
503                TrigQuantizationMode::SixteenSteps,
504                TrigQuantizationMode::try_from(8_u8).unwrap()
505            );
506        }
507        #[test]
508        fn test_24() {
509            assert_eq!(
510                TrigQuantizationMode::TwentyFourSteps,
511                TrigQuantizationMode::try_from(9_u8).unwrap()
512            );
513        }
514        #[test]
515        fn test_32() {
516            assert_eq!(
517                TrigQuantizationMode::ThirtyTwoSteps,
518                TrigQuantizationMode::try_from(10_u8).unwrap()
519            );
520        }
521        #[test]
522        fn test_48() {
523            assert_eq!(
524                TrigQuantizationMode::FortyEightSteps,
525                TrigQuantizationMode::try_from(11_u8).unwrap()
526            );
527        }
528        #[test]
529        fn test_64() {
530            assert_eq!(
531                TrigQuantizationMode::SixtyFourSteps,
532                TrigQuantizationMode::try_from(12_u8).unwrap()
533            );
534        }
535        #[test]
536        fn test_96() {
537            assert_eq!(
538                TrigQuantizationMode::NinetySixSteps,
539                TrigQuantizationMode::try_from(13_u8).unwrap()
540            );
541        }
542        #[test]
543        fn test_128() {
544            assert_eq!(
545                TrigQuantizationMode::OneTwentyEightSteps,
546                TrigQuantizationMode::try_from(14_u8).unwrap()
547            );
548        }
549        #[test]
550        fn test_192() {
551            assert_eq!(
552                TrigQuantizationMode::OneNinetyTwoSteps,
553                TrigQuantizationMode::try_from(15_u8).unwrap()
554            );
555        }
556        #[test]
557        fn test_256() {
558            assert_eq!(
559                TrigQuantizationMode::TwoFiveSixSteps,
560                TrigQuantizationMode::try_from(16_u8).unwrap()
561            );
562        }
563    }
564}
565
566/// Sample Slot options for Projects.
567#[derive(
568    Copy,
569    Clone,
570    Debug,
571    Default,
572    Eq,
573    Hash,
574    Ord,
575    PartialEq,
576    PartialOrd,
577    Serialize,
578    Deserialize,
579    AsMutDerive,
580    AsRefDerive,
581    IntoUnsigneds,
582)]
583pub enum TrigCondition {
584    // Uses implicit discriminants to increment values from 0 -> 64 (inclusive)
585    // https://doc.rust-lang.org/stable/reference/items/enumerations.html#implicit-discriminants
586    #[default]
587    None = 0,
588    /// > FILL is true (will activate the trig) when fill mode is active (see below).
589    Fill,
590    /// > ... true when FILL is not.
591    NotFill,
592    /// > PRE is true if the most recently evaluated trig condition on the same track was true.
593    Pre,
594    /// > ... true when PRE is not.
595    NotPre,
596    /// > true if the most recently evaluated trig condition on the neighbor track was true.
597    /// > The neighbor track is the track before the one being edited.
598    /// > For example, the neighbor track of track 4 is track 3. If no conditions exist on the
599    /// > neighbor track, the condition is false.
600    Nei,
601    /// > ... true when NEI is not.
602    NotNei,
603    /// > only true the first time the pattern play (when looped).
604    First,
605    /// > ... true when 1st is not.
606    NotFirst,
607    /// > probability condition. 1% chance of being true.
608    Percent1,
609    /// > probability condition. 2% chance of being true.
610    Percent2,
611    /// > probability condition. 4% chance of being true.
612    Percent4,
613    /// > probability condition. 6% chance of being true.
614    Percent6,
615    /// > probability condition. 9% chance of being true.
616    Percent9,
617    /// > probability condition. 13% chance of being true.
618    Percent13,
619    /// > probability condition. 19% chance of being true.
620    Percent19,
621    /// > probability condition. 25% chance of being true.
622    Percent25,
623    /// > probability condition. 33% chance of being true.
624    Percent33,
625    /// > probability condition. 41% chance of being true.
626    Percent41,
627    /// > probability condition. 50% chance of being true.
628    Percent50,
629    /// > probability condition. 59% chance of being true.
630    Percent59,
631    /// > probability condition. 67% chance of being true.
632    Percent67,
633    /// > probability condition. 75% chance of being true.
634    Percent75,
635    /// > probability condition. 81% chance of being true.
636    Percent81,
637    /// > probability condition. 87% chance of being true.
638    Percent87,
639    /// > probability condition. 91% chance of being true.
640    Percent91,
641    /// > probability condition. 94% chance of being true.
642    Percent94,
643    /// > probability condition. 96% chance of being true.
644    Percent96,
645    /// > probability condition. 98% chance of being true.
646    Percent98,
647    /// > probability condition. 99% chance of being true.
648    Percent99,
649    /// pattern loop 1 triggers, pattern loop 2 resets
650    PatternT1R2,
651    /// pattern loop 2 triggers, pattern loop 2 resets
652    PatternT2R2,
653    /// pattern loop 1 triggers, pattern loop 3 resets
654    PatternT1R3,
655    /// pattern loop 2 triggers, pattern loop 3 resets
656    PatternT2R3,
657    /// pattern loop 3 triggers, pattern loop 3 resets
658    PatternT3R3,
659    /// pattern loop 1 triggers, pattern loop 4 resets
660    PatternT1R4,
661    /// pattern loop 2 triggers, pattern loop 4 resets
662    PatternT2R4,
663    /// pattern loop 3 triggers, pattern loop 4 resets
664    PatternT3R4,
665    /// pattern loop 4 triggers, pattern loop 4 resets
666    PatternT4R4,
667    /// pattern loop 1 triggers, pattern loop 5 resets
668    PatternT1R5,
669    /// pattern loop 2 triggers, pattern loop 5 resets
670    PatternT2R5,
671    /// pattern loop 3 triggers, pattern loop 5 resets
672    PatternT3R5,
673    /// pattern loop 4 triggers, pattern loop 5 resets
674    PatternT4R5,
675    /// pattern loop 5 triggers, pattern loop 5 resets
676    PatternT5R5,
677    /// pattern loop 1 triggers, pattern loop 6 resets
678    PatternT1R6,
679    /// pattern loop 2 triggers, pattern loop 6 resets
680    PatternT2R6,
681    /// pattern loop 3 triggers, pattern loop 6 resets
682    PatternT3R6,
683    /// pattern loop 4 triggers, pattern loop 6 resets
684    PatternT4R6,
685    /// pattern loop 5 triggers, pattern loop 6 resets
686    PatternT5R6,
687    /// pattern loop 6 triggers, pattern loop 6 resets
688    PatternT6R6,
689    /// pattern loop 1 triggers, pattern loop 7 resets
690    PatternT1R7,
691    /// pattern loop 2 triggers, pattern loop 7 resets
692    PatternT2R7,
693    /// pattern loop 3 triggers, pattern loop 7 resets
694    PatternT3R7,
695    /// pattern loop 4 triggers, pattern loop 7 resets
696    PatternT4R7,
697    /// pattern loop 5 triggers, pattern loop 7 resets
698    PatternT5R7,
699    /// pattern loop 6 triggers, pattern loop 7 resets
700    PatternT6R7,
701    /// pattern loop 7 triggers, pattern loop 7 resets
702    PatternT7R7,
703    /// pattern loop 1 triggers, pattern loop 8 resets
704    PatternT1R8,
705    /// pattern loop 2 triggers, pattern loop 8 resets
706    PatternT2R8,
707    /// pattern loop 3 triggers, pattern loop 8 resets
708    PatternT3R8,
709    /// pattern loop 4 triggers, pattern loop 8 resets
710    PatternT4R8,
711    /// pattern loop 5 triggers, pattern loop 8 resets
712    PatternT5R8,
713    /// pattern loop 6 triggers, pattern loop 8 resets
714    PatternT6R8,
715    /// pattern loop 7 triggers, pattern loop 8 resets
716    PatternT7R8,
717    /// pattern loop 8 triggers, pattern loop 8 resets
718    PatternT8R8,
719}
720
721#[enum_try_from_u32_to_unsigned_types]
722impl TryFrom<u32> for TrigCondition {
723    type Error = InvalidValueError;
724    fn try_from(value: u32) -> Result<Self, Self::Error> {
725        // read the essay for `AudioTrackTrigs.trig_timings_repeats_conditions`
726        // to understand why rem_euclid is used here
727        match value.rem_euclid(128) {
728            0 => Ok(TrigCondition::None),
729            1 => Ok(TrigCondition::Fill),
730            2 => Ok(TrigCondition::NotFill),
731            3 => Ok(TrigCondition::Pre),
732            4 => Ok(TrigCondition::NotPre),
733            5 => Ok(TrigCondition::Nei),
734            6 => Ok(TrigCondition::NotNei),
735            7 => Ok(TrigCondition::First),
736            8 => Ok(TrigCondition::NotFirst),
737            //
738            9 => Ok(TrigCondition::Percent1),
739            10 => Ok(TrigCondition::Percent2),
740            11 => Ok(TrigCondition::Percent4),
741            12 => Ok(TrigCondition::Percent6),
742            13 => Ok(TrigCondition::Percent9),
743            14 => Ok(TrigCondition::Percent13),
744            15 => Ok(TrigCondition::Percent19),
745            16 => Ok(TrigCondition::Percent25),
746            17 => Ok(TrigCondition::Percent33),
747            18 => Ok(TrigCondition::Percent41),
748            19 => Ok(TrigCondition::Percent50),
749            20 => Ok(TrigCondition::Percent59),
750            21 => Ok(TrigCondition::Percent67),
751            22 => Ok(TrigCondition::Percent75),
752            23 => Ok(TrigCondition::Percent81),
753            24 => Ok(TrigCondition::Percent87),
754            25 => Ok(TrigCondition::Percent91),
755            26 => Ok(TrigCondition::Percent94),
756            27 => Ok(TrigCondition::Percent96),
757            28 => Ok(TrigCondition::Percent98),
758            29 => Ok(TrigCondition::Percent99),
759            //
760            30 => Ok(TrigCondition::PatternT1R2),
761            31 => Ok(TrigCondition::PatternT2R2),
762            //
763            32 => Ok(TrigCondition::PatternT1R3),
764            33 => Ok(TrigCondition::PatternT2R3),
765            34 => Ok(TrigCondition::PatternT3R3),
766            //
767            35 => Ok(TrigCondition::PatternT1R4),
768            36 => Ok(TrigCondition::PatternT2R4),
769            37 => Ok(TrigCondition::PatternT3R4),
770            38 => Ok(TrigCondition::PatternT4R4),
771            //
772            39 => Ok(TrigCondition::PatternT1R5),
773            40 => Ok(TrigCondition::PatternT2R5),
774            41 => Ok(TrigCondition::PatternT3R5),
775            42 => Ok(TrigCondition::PatternT4R5),
776            43 => Ok(TrigCondition::PatternT5R5),
777            //
778            44 => Ok(TrigCondition::PatternT1R6),
779            45 => Ok(TrigCondition::PatternT2R6),
780            46 => Ok(TrigCondition::PatternT3R6),
781            47 => Ok(TrigCondition::PatternT4R6),
782            48 => Ok(TrigCondition::PatternT5R6),
783            49 => Ok(TrigCondition::PatternT6R6),
784            //
785            50 => Ok(TrigCondition::PatternT1R7),
786            51 => Ok(TrigCondition::PatternT2R7),
787            52 => Ok(TrigCondition::PatternT3R7),
788            53 => Ok(TrigCondition::PatternT4R7),
789            54 => Ok(TrigCondition::PatternT5R7),
790            55 => Ok(TrigCondition::PatternT6R7),
791            56 => Ok(TrigCondition::PatternT7R7),
792            //
793            57 => Ok(TrigCondition::PatternT1R8),
794            58 => Ok(TrigCondition::PatternT2R8),
795            59 => Ok(TrigCondition::PatternT3R8),
796            60 => Ok(TrigCondition::PatternT4R8),
797            61 => Ok(TrigCondition::PatternT5R8),
798            62 => Ok(TrigCondition::PatternT6R8),
799            63 => Ok(TrigCondition::PatternT7R8),
800            64 => Ok(TrigCondition::PatternT8R8),
801            //
802            _ => Err(InvalidValueError::TrigCondition),
803        }
804    }
805}
806
807#[cfg(test)]
808mod test_spec_trig_condition {
809
810    mod from_value {
811        use crate::settings::TrigCondition;
812
813        #[test]
814        fn none() {
815            assert_eq!(TrigCondition::None, TrigCondition::try_from(&0_u8).unwrap())
816        }
817        #[test]
818        fn fill() {
819            assert_eq!(TrigCondition::Fill, TrigCondition::try_from(&1_u8).unwrap())
820        }
821        #[test]
822        fn notfill() {
823            assert_eq!(
824                TrigCondition::NotFill,
825                TrigCondition::try_from(&2_u8).unwrap()
826            )
827        }
828        #[test]
829        fn pre() {
830            assert_eq!(TrigCondition::Pre, TrigCondition::try_from(&3_u8).unwrap())
831        }
832        #[test]
833        fn notpre() {
834            assert_eq!(
835                TrigCondition::NotPre,
836                TrigCondition::try_from(&4_u8).unwrap()
837            )
838        }
839        #[test]
840        fn nei() {
841            assert_eq!(TrigCondition::Nei, TrigCondition::try_from(&5_u8).unwrap())
842        }
843        #[test]
844        fn notnei() {
845            assert_eq!(
846                TrigCondition::NotNei,
847                TrigCondition::try_from(&6_u8).unwrap()
848            )
849        }
850        #[test]
851        fn first() {
852            assert_eq!(
853                TrigCondition::First,
854                TrigCondition::try_from(&7_u8).unwrap()
855            )
856        }
857        #[test]
858        fn notfirst() {
859            assert_eq!(
860                TrigCondition::NotFirst,
861                TrigCondition::try_from(&8_u8).unwrap()
862            )
863        }
864        #[test]
865        fn perc1() {
866            assert_eq!(
867                TrigCondition::Percent1,
868                TrigCondition::try_from(&9_u8).unwrap()
869            )
870        }
871        #[test]
872        fn perc2() {
873            assert_eq!(
874                TrigCondition::Percent2,
875                TrigCondition::try_from(&10_u8).unwrap()
876            )
877        }
878        #[test]
879        fn perc4() {
880            assert_eq!(
881                TrigCondition::Percent4,
882                TrigCondition::try_from(&11_u8).unwrap()
883            )
884        }
885        #[test]
886        fn perc6() {
887            assert_eq!(
888                TrigCondition::Percent6,
889                TrigCondition::try_from(&12_u8).unwrap()
890            )
891        }
892        #[test]
893        fn perc9() {
894            assert_eq!(
895                TrigCondition::Percent9,
896                TrigCondition::try_from(&13_u8).unwrap()
897            )
898        }
899        #[test]
900        fn perc13() {
901            assert_eq!(
902                TrigCondition::Percent13,
903                TrigCondition::try_from(&14_u8).unwrap()
904            )
905        }
906        #[test]
907        fn perc19() {
908            assert_eq!(
909                TrigCondition::Percent19,
910                TrigCondition::try_from(&15_u8).unwrap()
911            )
912        }
913        #[test]
914        fn perc25() {
915            assert_eq!(
916                TrigCondition::Percent25,
917                TrigCondition::try_from(&16_u8).unwrap()
918            )
919        }
920        #[test]
921        fn perc33() {
922            assert_eq!(
923                TrigCondition::Percent33,
924                TrigCondition::try_from(&17_u8).unwrap()
925            )
926        }
927        #[test]
928        fn perc41() {
929            assert_eq!(
930                TrigCondition::Percent41,
931                TrigCondition::try_from(&18_u8).unwrap()
932            )
933        }
934        #[test]
935        fn perc50() {
936            assert_eq!(
937                TrigCondition::Percent50,
938                TrigCondition::try_from(&19_u8).unwrap()
939            )
940        }
941        #[test]
942        fn perc59() {
943            assert_eq!(
944                TrigCondition::Percent59,
945                TrigCondition::try_from(&20_u8).unwrap()
946            )
947        }
948        #[test]
949        fn perc67() {
950            assert_eq!(
951                TrigCondition::Percent67,
952                TrigCondition::try_from(&21_u8).unwrap()
953            )
954        }
955        #[test]
956        fn perc75() {
957            assert_eq!(
958                TrigCondition::Percent75,
959                TrigCondition::try_from(&22_u8).unwrap()
960            )
961        }
962        #[test]
963        fn perc81() {
964            assert_eq!(
965                TrigCondition::Percent81,
966                TrigCondition::try_from(&23_u8).unwrap()
967            )
968        }
969        #[test]
970        fn perc87() {
971            assert_eq!(
972                TrigCondition::Percent87,
973                TrigCondition::try_from(&24_u8).unwrap()
974            )
975        }
976        #[test]
977        fn perc91() {
978            assert_eq!(
979                TrigCondition::Percent91,
980                TrigCondition::try_from(&25_u8).unwrap()
981            )
982        }
983        #[test]
984        fn perc94() {
985            assert_eq!(
986                TrigCondition::Percent94,
987                TrigCondition::try_from(&26_u8).unwrap()
988            )
989        }
990        #[test]
991        fn perc96() {
992            assert_eq!(
993                TrigCondition::Percent96,
994                TrigCondition::try_from(&27_u8).unwrap()
995            )
996        }
997        #[test]
998        fn perc98() {
999            assert_eq!(
1000                TrigCondition::Percent98,
1001                TrigCondition::try_from(&28_u8).unwrap()
1002            )
1003        }
1004        #[test]
1005        fn perc99() {
1006            assert_eq!(
1007                TrigCondition::Percent99,
1008                TrigCondition::try_from(&29_u8).unwrap()
1009            )
1010        }
1011        #[test]
1012        fn pat_t1r2() {
1013            assert_eq!(
1014                TrigCondition::PatternT1R2,
1015                TrigCondition::try_from(&30_u8).unwrap()
1016            )
1017        }
1018        #[test]
1019        fn pat_t2r2() {
1020            assert_eq!(
1021                TrigCondition::PatternT2R2,
1022                TrigCondition::try_from(&31_u8).unwrap()
1023            )
1024        }
1025        #[test]
1026        fn pat_t1r3() {
1027            assert_eq!(
1028                TrigCondition::PatternT1R3,
1029                TrigCondition::try_from(&32_u8).unwrap()
1030            )
1031        }
1032        #[test]
1033        fn pat_t2r3() {
1034            assert_eq!(
1035                TrigCondition::PatternT2R3,
1036                TrigCondition::try_from(&33_u8).unwrap()
1037            )
1038        }
1039        #[test]
1040        fn pat_t3r3() {
1041            assert_eq!(
1042                TrigCondition::PatternT3R3,
1043                TrigCondition::try_from(&34_u8).unwrap()
1044            )
1045        }
1046
1047        #[test]
1048        fn pat_t1r4() {
1049            assert_eq!(
1050                TrigCondition::PatternT1R4,
1051                TrigCondition::try_from(&35_u8).unwrap()
1052            )
1053        }
1054        #[test]
1055        fn pat_t2r4() {
1056            assert_eq!(
1057                TrigCondition::PatternT2R4,
1058                TrigCondition::try_from(&36_u8).unwrap()
1059            )
1060        }
1061        #[test]
1062        fn pat_t3r4() {
1063            assert_eq!(
1064                TrigCondition::PatternT3R4,
1065                TrigCondition::try_from(&37_u8).unwrap()
1066            )
1067        }
1068        #[test]
1069        fn pat_t4r4() {
1070            assert_eq!(
1071                TrigCondition::PatternT4R4,
1072                TrigCondition::try_from(&38_u8).unwrap()
1073            )
1074        }
1075
1076        #[test]
1077        fn pat_t1r5() {
1078            assert_eq!(
1079                TrigCondition::PatternT1R5,
1080                TrigCondition::try_from(&39_u8).unwrap()
1081            )
1082        }
1083        #[test]
1084        fn pat_t2r5() {
1085            assert_eq!(
1086                TrigCondition::PatternT2R5,
1087                TrigCondition::try_from(&40_u8).unwrap()
1088            )
1089        }
1090        #[test]
1091        fn pat_t3r5() {
1092            assert_eq!(
1093                TrigCondition::PatternT3R5,
1094                TrigCondition::try_from(&41_u8).unwrap()
1095            )
1096        }
1097        #[test]
1098        fn pat_t4r5() {
1099            assert_eq!(
1100                TrigCondition::PatternT4R5,
1101                TrigCondition::try_from(&42_u8).unwrap()
1102            )
1103        }
1104        #[test]
1105        fn pat_t5r5() {
1106            assert_eq!(
1107                TrigCondition::PatternT5R5,
1108                TrigCondition::try_from(&43_u8).unwrap()
1109            )
1110        }
1111
1112        #[test]
1113        fn pat_t1r6() {
1114            assert_eq!(
1115                TrigCondition::PatternT1R6,
1116                TrigCondition::try_from(&44_u8).unwrap()
1117            )
1118        }
1119        #[test]
1120        fn pat_t2r6() {
1121            assert_eq!(
1122                TrigCondition::PatternT2R6,
1123                TrigCondition::try_from(&45_u8).unwrap()
1124            )
1125        }
1126        #[test]
1127        fn pat_t3r6() {
1128            assert_eq!(
1129                TrigCondition::PatternT3R6,
1130                TrigCondition::try_from(&46_u8).unwrap()
1131            )
1132        }
1133        #[test]
1134        fn pat_t4r6() {
1135            assert_eq!(
1136                TrigCondition::PatternT4R6,
1137                TrigCondition::try_from(&47_u8).unwrap()
1138            )
1139        }
1140        #[test]
1141        fn pat_t5r6() {
1142            assert_eq!(
1143                TrigCondition::PatternT5R6,
1144                TrigCondition::try_from(&48_u8).unwrap()
1145            )
1146        }
1147        #[test]
1148        fn pat_t6r6() {
1149            assert_eq!(
1150                TrigCondition::PatternT6R6,
1151                TrigCondition::try_from(&49_u8).unwrap()
1152            )
1153        }
1154
1155        #[test]
1156        fn pat_t1r7() {
1157            assert_eq!(
1158                TrigCondition::PatternT1R7,
1159                TrigCondition::try_from(&50_u8).unwrap()
1160            )
1161        }
1162        #[test]
1163        fn pat_t2r7() {
1164            assert_eq!(
1165                TrigCondition::PatternT2R7,
1166                TrigCondition::try_from(&51_u8).unwrap()
1167            )
1168        }
1169        #[test]
1170        fn pat_t3r7() {
1171            assert_eq!(
1172                TrigCondition::PatternT3R7,
1173                TrigCondition::try_from(&52_u8).unwrap()
1174            )
1175        }
1176        #[test]
1177        fn pat_t4r7() {
1178            assert_eq!(
1179                TrigCondition::PatternT4R7,
1180                TrigCondition::try_from(&53_u8).unwrap()
1181            )
1182        }
1183        #[test]
1184        fn pat_t5r7() {
1185            assert_eq!(
1186                TrigCondition::PatternT5R7,
1187                TrigCondition::try_from(&54_u8).unwrap()
1188            )
1189        }
1190        #[test]
1191        fn pat_t6r7() {
1192            assert_eq!(
1193                TrigCondition::PatternT6R7,
1194                TrigCondition::try_from(&55_u8).unwrap()
1195            )
1196        }
1197        #[test]
1198        fn pat_t7r7() {
1199            assert_eq!(
1200                TrigCondition::PatternT7R7,
1201                TrigCondition::try_from(&56_u8).unwrap()
1202            )
1203        }
1204
1205        #[test]
1206        fn pat_t1r8() {
1207            assert_eq!(
1208                TrigCondition::PatternT1R8,
1209                TrigCondition::try_from(&57_u8).unwrap()
1210            )
1211        }
1212        #[test]
1213        fn pat_t2r8() {
1214            assert_eq!(
1215                TrigCondition::PatternT2R8,
1216                TrigCondition::try_from(&58_u8).unwrap()
1217            )
1218        }
1219        #[test]
1220        fn pat_t3r8() {
1221            assert_eq!(
1222                TrigCondition::PatternT3R8,
1223                TrigCondition::try_from(&59_u8).unwrap()
1224            )
1225        }
1226        #[test]
1227        fn pat_t4r8() {
1228            assert_eq!(
1229                TrigCondition::PatternT4R8,
1230                TrigCondition::try_from(&60_u8).unwrap()
1231            )
1232        }
1233        #[test]
1234        fn pat_t5r8() {
1235            assert_eq!(
1236                TrigCondition::PatternT5R8,
1237                TrigCondition::try_from(&61_u8).unwrap()
1238            )
1239        }
1240        #[test]
1241        fn pat_t6r8() {
1242            assert_eq!(
1243                TrigCondition::PatternT6R8,
1244                TrigCondition::try_from(&62_u8).unwrap()
1245            )
1246        }
1247        #[test]
1248        fn pat_t7r8() {
1249            assert_eq!(
1250                TrigCondition::PatternT7R8,
1251                TrigCondition::try_from(&63_u8).unwrap()
1252            )
1253        }
1254        #[test]
1255        fn pat_t8r8() {
1256            assert_eq!(
1257                TrigCondition::PatternT8R8,
1258                TrigCondition::try_from(&64_u8).unwrap()
1259            )
1260        }
1261    }
1262    mod get_value {
1263        use crate::settings::TrigCondition;
1264
1265        #[test]
1266        fn none() {
1267            assert_eq!(TrigCondition::None as u8, 0)
1268        }
1269        #[test]
1270        fn fill() {
1271            assert_eq!(TrigCondition::Fill as u8, 1)
1272        }
1273        #[test]
1274        fn notfill() {
1275            assert_eq!(TrigCondition::NotFill as u8, 2)
1276        }
1277        #[test]
1278        fn pre() {
1279            assert_eq!(TrigCondition::Pre as u8, 3)
1280        }
1281        #[test]
1282        fn notpre() {
1283            assert_eq!(TrigCondition::NotPre as u8, 4)
1284        }
1285        #[test]
1286        fn nei() {
1287            assert_eq!(TrigCondition::Nei as u8, 5)
1288        }
1289        #[test]
1290        fn notnei() {
1291            assert_eq!(TrigCondition::NotNei as u8, 6)
1292        }
1293        #[test]
1294        fn first() {
1295            assert_eq!(TrigCondition::First as u8, 7)
1296        }
1297        #[test]
1298        fn notfirst() {
1299            assert_eq!(TrigCondition::NotFirst as u8, 8)
1300        }
1301        #[test]
1302        fn perc1() {
1303            assert_eq!(TrigCondition::Percent1 as u8, 9)
1304        }
1305        #[test]
1306        fn perc2() {
1307            assert_eq!(TrigCondition::Percent2 as u8, 10)
1308        }
1309        #[test]
1310        fn perc4() {
1311            assert_eq!(TrigCondition::Percent4 as u8, 11)
1312        }
1313        #[test]
1314        fn perc6() {
1315            assert_eq!(TrigCondition::Percent6 as u8, 12)
1316        }
1317        #[test]
1318        fn perc9() {
1319            assert_eq!(TrigCondition::Percent9 as u8, 13)
1320        }
1321        #[test]
1322        fn perc13() {
1323            assert_eq!(TrigCondition::Percent13 as u8, 14)
1324        }
1325        #[test]
1326        fn perc19() {
1327            assert_eq!(TrigCondition::Percent19 as u8, 15)
1328        }
1329        #[test]
1330        fn perc25() {
1331            assert_eq!(TrigCondition::Percent25 as u8, 16)
1332        }
1333        #[test]
1334        fn perc33() {
1335            assert_eq!(TrigCondition::Percent33 as u8, 17)
1336        }
1337        #[test]
1338        fn perc41() {
1339            assert_eq!(TrigCondition::Percent41 as u8, 18)
1340        }
1341        #[test]
1342        fn perc50() {
1343            assert_eq!(TrigCondition::Percent50 as u8, 19)
1344        }
1345        #[test]
1346        fn perc59() {
1347            assert_eq!(TrigCondition::Percent59 as u8, 20)
1348        }
1349        #[test]
1350        fn perc67() {
1351            assert_eq!(TrigCondition::Percent67 as u8, 21)
1352        }
1353        #[test]
1354        fn perc75() {
1355            assert_eq!(TrigCondition::Percent75 as u8, 22)
1356        }
1357        #[test]
1358        fn perc81() {
1359            assert_eq!(TrigCondition::Percent81 as u8, 23)
1360        }
1361        #[test]
1362        fn perc87() {
1363            assert_eq!(TrigCondition::Percent87 as u8, 24)
1364        }
1365        #[test]
1366        fn perc91() {
1367            assert_eq!(TrigCondition::Percent91 as u8, 25)
1368        }
1369        #[test]
1370        fn perc94() {
1371            assert_eq!(TrigCondition::Percent94 as u8, 26)
1372        }
1373        #[test]
1374        fn perc96() {
1375            assert_eq!(TrigCondition::Percent96 as u8, 27)
1376        }
1377        #[test]
1378        fn perc98() {
1379            assert_eq!(TrigCondition::Percent98 as u8, 28)
1380        }
1381        #[test]
1382        fn perc99() {
1383            assert_eq!(TrigCondition::Percent99 as u8, 29)
1384        }
1385        #[test]
1386        fn pat_t1r2() {
1387            assert_eq!(TrigCondition::PatternT1R2 as u8, 30)
1388        }
1389        #[test]
1390        fn pat_t2r2() {
1391            assert_eq!(TrigCondition::PatternT2R2 as u8, 31)
1392        }
1393        #[test]
1394        fn pat_t1r3() {
1395            assert_eq!(TrigCondition::PatternT1R3 as u8, 32)
1396        }
1397        #[test]
1398        fn pat_t2r3() {
1399            assert_eq!(TrigCondition::PatternT2R3 as u8, 33)
1400        }
1401        #[test]
1402        fn pat_t3r3() {
1403            assert_eq!(TrigCondition::PatternT3R3 as u8, 34)
1404        }
1405
1406        #[test]
1407        fn pat_t1r4() {
1408            assert_eq!(TrigCondition::PatternT1R4 as u8, 35)
1409        }
1410        #[test]
1411        fn pat_t2r4() {
1412            assert_eq!(TrigCondition::PatternT2R4 as u8, 36)
1413        }
1414        #[test]
1415        fn pat_t3r4() {
1416            assert_eq!(TrigCondition::PatternT3R4 as u8, 37)
1417        }
1418        #[test]
1419        fn pat_t4r4() {
1420            assert_eq!(TrigCondition::PatternT4R4 as u8, 38)
1421        }
1422
1423        #[test]
1424        fn pat_t1r5() {
1425            assert_eq!(TrigCondition::PatternT1R5 as u8, 39)
1426        }
1427        #[test]
1428        fn pat_t2r5() {
1429            assert_eq!(TrigCondition::PatternT2R5 as u8, 40)
1430        }
1431        #[test]
1432        fn pat_t3r5() {
1433            assert_eq!(TrigCondition::PatternT3R5 as u8, 41)
1434        }
1435        #[test]
1436        fn pat_t4r5() {
1437            assert_eq!(TrigCondition::PatternT4R5 as u8, 42)
1438        }
1439        #[test]
1440        fn pat_t5r5() {
1441            assert_eq!(TrigCondition::PatternT5R5 as u8, 43)
1442        }
1443
1444        #[test]
1445        fn pat_t1r6() {
1446            assert_eq!(TrigCondition::PatternT1R6 as u8, 44)
1447        }
1448        #[test]
1449        fn pat_t2r6() {
1450            assert_eq!(TrigCondition::PatternT2R6 as u8, 45)
1451        }
1452        #[test]
1453        fn pat_t3r6() {
1454            assert_eq!(TrigCondition::PatternT3R6 as u8, 46)
1455        }
1456        #[test]
1457        fn pat_t4r6() {
1458            assert_eq!(TrigCondition::PatternT4R6 as u8, 47)
1459        }
1460        #[test]
1461        fn pat_t5r6() {
1462            assert_eq!(TrigCondition::PatternT5R6 as u8, 48)
1463        }
1464        #[test]
1465        fn pat_t6r6() {
1466            assert_eq!(TrigCondition::PatternT6R6 as u8, 49)
1467        }
1468
1469        #[test]
1470        fn pat_t1r7() {
1471            assert_eq!(TrigCondition::PatternT1R7 as u8, 50)
1472        }
1473        #[test]
1474        fn pat_t2r7() {
1475            assert_eq!(TrigCondition::PatternT2R7 as u8, 51)
1476        }
1477        #[test]
1478        fn pat_t3r7() {
1479            assert_eq!(TrigCondition::PatternT3R7 as u8, 52)
1480        }
1481        #[test]
1482        fn pat_t4r7() {
1483            assert_eq!(TrigCondition::PatternT4R7 as u8, 53)
1484        }
1485        #[test]
1486        fn pat_t5r7() {
1487            assert_eq!(TrigCondition::PatternT5R7 as u8, 54)
1488        }
1489        #[test]
1490        fn pat_t6r7() {
1491            assert_eq!(TrigCondition::PatternT6R7 as u8, 55)
1492        }
1493        #[test]
1494        fn pat_t7r7() {
1495            assert_eq!(TrigCondition::PatternT7R7 as u8, 56)
1496        }
1497
1498        #[test]
1499        fn pat_t1r8() {
1500            assert_eq!(TrigCondition::PatternT1R8 as u8, 57)
1501        }
1502        #[test]
1503        fn pat_t2r8() {
1504            assert_eq!(TrigCondition::PatternT2R8 as u8, 58)
1505        }
1506        #[test]
1507        fn pat_t3r8() {
1508            assert_eq!(TrigCondition::PatternT3R8 as u8, 59)
1509        }
1510        #[test]
1511        fn pat_t4r8() {
1512            assert_eq!(TrigCondition::PatternT4R8 as u8, 60)
1513        }
1514        #[test]
1515        fn pat_t5r8() {
1516            assert_eq!(TrigCondition::PatternT5R8 as u8, 61)
1517        }
1518        #[test]
1519        fn pat_t6r8() {
1520            assert_eq!(TrigCondition::PatternT6R8 as u8, 62)
1521        }
1522        #[test]
1523        fn pat_t7r8() {
1524            assert_eq!(TrigCondition::PatternT7R8 as u8, 63)
1525        }
1526        #[test]
1527        fn pat_t8r8() {
1528            assert_eq!(TrigCondition::PatternT8R8 as u8, 64)
1529        }
1530    }
1531}
1532
1533/// MIDI Channel for Program Change settings in Project Settings Menu.
1534/// Used where both `Auto` and channel 1-16 options are available
1535/// (Project Menu -> Control -> Midi -> Sync).
1536/// See manual section 8.7.2 SYNC.
1537///
1538/// Values in `project.work`: `-1` = Auto, `0`-`15` = Channel 1-16.
1539#[derive(
1540    Copy,
1541    Clone,
1542    Debug,
1543    Default,
1544    Eq,
1545    Hash,
1546    Ord,
1547    PartialEq,
1548    PartialOrd,
1549    Serialize,
1550    Deserialize,
1551    AsMutDerive,
1552    AsRefDerive,
1553    IntoSigneds,
1554)]
1555#[repr(i8)]
1556pub enum ProgChMidiChannel {
1557    /// Auto MIDI Channel
1558    #[default]
1559    Auto = -1,
1560    /// MIDI CH 1
1561    One = 0,
1562    /// MIDI CH 2
1563    Two = 1,
1564    /// MIDI CH 3
1565    Three = 2,
1566    /// MIDI CH 4
1567    Four = 3,
1568    /// MIDI CH 5
1569    Five = 4,
1570    /// MIDI CH 6
1571    Six = 5,
1572    /// MIDI CH 7
1573    Seven = 6,
1574    /// MIDI CH 8
1575    Eight = 7,
1576    /// MIDI CH 9
1577    Nine = 8,
1578    /// MIDI CH 10
1579    Ten = 9,
1580    /// MIDI CH 11
1581    Eleven = 10,
1582    /// MIDI CH 12
1583    Twelve = 11,
1584    /// MIDI CH 13
1585    Thirteen = 12,
1586    /// MIDI CH 14
1587    Fourteen = 13,
1588    /// MIDI CH 15
1589    Fifteen = 14,
1590    /// MIDI CH 16
1591    Sixteen = 15,
1592}
1593
1594#[enum_try_from_i32_to_signed_types]
1595impl TryFrom<i32> for ProgChMidiChannel {
1596    type Error = InvalidValueError;
1597    fn try_from(value: i32) -> Result<Self, Self::Error> {
1598        match value {
1599            -1 => Ok(Self::Auto),
1600            0 => Ok(Self::One),
1601            1 => Ok(Self::Two),
1602            2 => Ok(Self::Three),
1603            3 => Ok(Self::Four),
1604            4 => Ok(Self::Five),
1605            5 => Ok(Self::Six),
1606            6 => Ok(Self::Seven),
1607            7 => Ok(Self::Eight),
1608            8 => Ok(Self::Nine),
1609            9 => Ok(Self::Ten),
1610            10 => Ok(Self::Eleven),
1611            11 => Ok(Self::Twelve),
1612            12 => Ok(Self::Thirteen),
1613            13 => Ok(Self::Fourteen),
1614            14 => Ok(Self::Fifteen),
1615            15 => Ok(Self::Sixteen),
1616            _ => Err(InvalidValueError::ProgChMidiChannel),
1617        }
1618    }
1619}
1620
1621#[cfg(test)]
1622#[allow(unused_imports)]
1623mod test_spec {
1624
1625    mod value {
1626        use crate::settings::ProgChMidiChannel;
1627
1628        #[test]
1629        fn test_auto() {
1630            assert_eq!(ProgChMidiChannel::Auto as i8, -1);
1631        }
1632        #[test]
1633        fn test_1() {
1634            assert_eq!(ProgChMidiChannel::One as i8, 0);
1635        }
1636        #[test]
1637        fn test_2() {
1638            assert_eq!(ProgChMidiChannel::Two as i8, 1);
1639        }
1640        #[test]
1641        fn test_3() {
1642            assert_eq!(ProgChMidiChannel::Three as i8, 2);
1643        }
1644        #[test]
1645        fn test_4() {
1646            assert_eq!(ProgChMidiChannel::Four as i8, 3);
1647        }
1648        #[test]
1649        fn test_5() {
1650            assert_eq!(ProgChMidiChannel::Five as i8, 4);
1651        }
1652        #[test]
1653        fn test_6() {
1654            assert_eq!(ProgChMidiChannel::Six as i8, 5);
1655        }
1656        #[test]
1657        fn test_7() {
1658            assert_eq!(ProgChMidiChannel::Seven as i8, 6);
1659        }
1660        #[test]
1661        fn test_8() {
1662            assert_eq!(ProgChMidiChannel::Eight as i8, 7);
1663        }
1664        #[test]
1665        fn test_9() {
1666            assert_eq!(ProgChMidiChannel::Nine as i8, 8);
1667        }
1668        #[test]
1669        fn test_10() {
1670            assert_eq!(ProgChMidiChannel::Ten as i8, 9);
1671        }
1672        #[test]
1673        fn test_11() {
1674            assert_eq!(ProgChMidiChannel::Eleven as i8, 10);
1675        }
1676        #[test]
1677        fn test_12() {
1678            assert_eq!(ProgChMidiChannel::Twelve as i8, 11);
1679        }
1680        #[test]
1681        fn test_13() {
1682            assert_eq!(ProgChMidiChannel::Thirteen as i8, 12);
1683        }
1684        #[test]
1685        fn test_14() {
1686            assert_eq!(ProgChMidiChannel::Fourteen as i8, 13);
1687        }
1688        #[test]
1689        fn test_15() {
1690            assert_eq!(ProgChMidiChannel::Fifteen as i8, 14);
1691        }
1692        #[test]
1693        fn test_16() {
1694            assert_eq!(ProgChMidiChannel::Sixteen as i8, 15);
1695        }
1696    }
1697
1698    mod from_value {
1699
1700        use crate::settings::ProgChMidiChannel;
1701
1702        #[test]
1703        fn test_error_1() {
1704            assert!(ProgChMidiChannel::try_from(&100_i8).is_err());
1705        }
1706        #[test]
1707        fn test_auto() {
1708            assert_eq!(
1709                ProgChMidiChannel::Auto,
1710                ProgChMidiChannel::try_from(&-1_i8).unwrap()
1711            );
1712        }
1713        #[test]
1714        fn test_1() {
1715            assert_eq!(
1716                ProgChMidiChannel::One,
1717                ProgChMidiChannel::try_from(&0_i8).unwrap()
1718            );
1719        }
1720        #[test]
1721        fn test_2() {
1722            assert_eq!(
1723                ProgChMidiChannel::Two,
1724                ProgChMidiChannel::try_from(&1_i8).unwrap()
1725            );
1726        }
1727        #[test]
1728        fn test_3() {
1729            assert_eq!(
1730                ProgChMidiChannel::Three,
1731                ProgChMidiChannel::try_from(&2_i8).unwrap()
1732            );
1733        }
1734        #[test]
1735        fn test_4() {
1736            assert_eq!(
1737                ProgChMidiChannel::Four,
1738                ProgChMidiChannel::try_from(&3_i8).unwrap()
1739            );
1740        }
1741        #[test]
1742        fn test_5() {
1743            assert_eq!(
1744                ProgChMidiChannel::Five,
1745                ProgChMidiChannel::try_from(&4_i8).unwrap()
1746            );
1747        }
1748        #[test]
1749        fn test_6() {
1750            assert_eq!(
1751                ProgChMidiChannel::Six,
1752                ProgChMidiChannel::try_from(&5_i8).unwrap()
1753            );
1754        }
1755        #[test]
1756        fn test_7() {
1757            assert_eq!(
1758                ProgChMidiChannel::Seven,
1759                ProgChMidiChannel::try_from(&6_i8).unwrap()
1760            );
1761        }
1762        #[test]
1763        fn test_8() {
1764            assert_eq!(
1765                ProgChMidiChannel::Eight,
1766                ProgChMidiChannel::try_from(&7_i8).unwrap()
1767            );
1768        }
1769        #[test]
1770        fn test_9() {
1771            assert_eq!(
1772                ProgChMidiChannel::Nine,
1773                ProgChMidiChannel::try_from(&8_i8).unwrap()
1774            );
1775        }
1776        #[test]
1777        fn test_10() {
1778            assert_eq!(
1779                ProgChMidiChannel::Ten,
1780                ProgChMidiChannel::try_from(&9_i8).unwrap()
1781            );
1782        }
1783        #[test]
1784        fn test_11() {
1785            assert_eq!(
1786                ProgChMidiChannel::Eleven,
1787                ProgChMidiChannel::try_from(&10_i8).unwrap()
1788            );
1789        }
1790        #[test]
1791        fn test_12() {
1792            assert_eq!(
1793                ProgChMidiChannel::Twelve,
1794                ProgChMidiChannel::try_from(&11_i8).unwrap()
1795            );
1796        }
1797        #[test]
1798        fn test_13() {
1799            assert_eq!(
1800                ProgChMidiChannel::Thirteen,
1801                ProgChMidiChannel::try_from(&12_i8).unwrap()
1802            );
1803        }
1804        #[test]
1805        fn test_14() {
1806            assert_eq!(
1807                ProgChMidiChannel::Fourteen,
1808                ProgChMidiChannel::try_from(&13_i8).unwrap()
1809            );
1810        }
1811        #[test]
1812        fn test_15() {
1813            assert_eq!(
1814                ProgChMidiChannel::Fifteen,
1815                ProgChMidiChannel::try_from(&14_i8).unwrap()
1816            );
1817        }
1818        #[test]
1819        fn test_16() {
1820            assert_eq!(
1821                ProgChMidiChannel::Sixteen,
1822                ProgChMidiChannel::try_from(&15_i8).unwrap()
1823            );
1824        }
1825    }
1826}
1827
1828// todo: create internal SlotTypeParsed enum for parsing values, then have Display working properly
1829/// Slot's machine type (cannot access flex samples for a static machine etc).
1830#[derive(
1831    Copy,
1832    Clone,
1833    Debug,
1834    Eq,
1835    Hash,
1836    Ord,
1837    PartialEq,
1838    PartialOrd,
1839    Serialize,
1840    Deserialize,
1841    AsMutDerive,
1842    AsRefDerive,
1843)]
1844pub enum SlotType {
1845    /// Static machine slot
1846    Static,
1847    /// Flex machine slot
1848    Flex,
1849}
1850
1851impl SlotType {
1852    pub fn other(&self) -> Self {
1853        match self {
1854            Self::Static => Self::Flex,
1855            Self::Flex => Self::Static,
1856        }
1857    }
1858}
1859
1860impl TryFrom<String> for SlotType {
1861    type Error = InvalidValueError;
1862    fn try_from(value: String) -> Result<Self, Self::Error> {
1863        match value.to_ascii_uppercase().as_str() {
1864            "STATIC" => Ok(SlotType::Static),
1865            "FLEX" => Ok(SlotType::Flex),
1866            _ => Err(InvalidValueError::SlotType),
1867        }
1868    }
1869}
1870
1871impl TryFrom<&str> for SlotType {
1872    type Error = InvalidValueError;
1873    fn try_from(value: &str) -> Result<Self, Self::Error> {
1874        Self::try_from(value.to_string())
1875    }
1876}
1877
1878impl Display for SlotType {
1879    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1880        let str = match self {
1881            SlotType::Static => "STATIC".to_string(),
1882            SlotType::Flex => "FLEX".to_string(),
1883        };
1884        write!(f, "{str}")
1885    }
1886}
1887
1888impl From<SlotType> for String {
1889    fn from(value: SlotType) -> Self {
1890        value.to_string()
1891    }
1892}
1893
1894#[cfg(test)]
1895mod slot_type {
1896    mod value {
1897        use crate::settings::SlotType;
1898
1899        #[test]
1900        fn test_static() {
1901            assert_eq!(SlotType::Static.to_string(), "STATIC");
1902            assert_eq!(String::from(SlotType::Static), "STATIC");
1903        }
1904        #[test]
1905        fn test_flex() {
1906            assert_eq!(SlotType::Flex.to_string(), "FLEX");
1907            assert_eq!(String::from(SlotType::Flex), "FLEX");
1908        }
1909    }
1910
1911    mod other {
1912        use crate::settings::SlotType;
1913        #[test]
1914        fn static_slot() {
1915            assert_eq!(SlotType::Static.other(), SlotType::Flex)
1916        }
1917
1918        #[test]
1919        fn flex_slot() {
1920            assert_eq!(SlotType::Flex.other(), SlotType::Static)
1921        }
1922    }
1923
1924    mod from_value {
1925        use crate::settings::SlotType;
1926
1927        #[test]
1928        fn test_error() {
1929            assert!(SlotType::try_from("SOME INCORRECT STRING").is_err());
1930        }
1931
1932        #[test]
1933        fn test_static_upper() {
1934            assert_eq!(SlotType::Static, SlotType::try_from("STATIC").unwrap(),);
1935        }
1936
1937        #[test]
1938        fn test_static_lower() {
1939            assert_eq!(SlotType::Static, SlotType::try_from("static").unwrap(),);
1940        }
1941
1942        #[test]
1943        fn test_flex_upper() {
1944            assert_eq!(SlotType::Flex, SlotType::try_from("FLEX").unwrap(),);
1945        }
1946
1947        #[test]
1948        fn test_flex_lower() {
1949            assert_eq!(SlotType::Flex, SlotType::try_from("flex").unwrap(),);
1950        }
1951    }
1952}