rytm_rs/object/
global.rs

1pub mod menu;
2pub mod types;
3pub(crate) mod unknown;
4
5use self::unknown::GlobalUnknown;
6use crate::{
7    error::{ParameterError, RytmError, SysexConversionError},
8    impl_sysex_compatible,
9    sysex::{SysexCompatible, SysexMeta, SysexType, GLOBAL_SYSEX_SIZE},
10    util::{assemble_u32_from_u8_array_be, break_u32_into_u8_array_be},
11    AnySysexType,
12};
13use derivative::Derivative;
14use menu::*;
15use rytm_rs_macro::parameter_range;
16use rytm_sys::{ar_global_raw_to_syx, ar_global_t, ar_sysex_meta_t};
17use serde::{Deserialize, Serialize};
18
19impl_sysex_compatible!(
20    Global,
21    ar_global_t,
22    ar_global_raw_to_syx,
23    SysexType::Global,
24    GLOBAL_SYSEX_SIZE
25);
26
27/// Represents a global in the analog rytm.
28///
29/// It does not map identically to the structure in the firmware.
30///
31/// Globals are global settings which you may found in the settings menu of the device.
32#[derive(Derivative, Clone, Copy, Serialize, Deserialize)]
33#[derivative(Debug)]
34pub struct Global {
35    #[derivative(Debug = "ignore")]
36    sysex_meta: SysexMeta,
37    /// Version of the global structure.
38    version: u32,
39
40    index: usize,
41
42    metronome_settings: MetronomeSettings,
43    midi_config: MidiConfig,
44    sequencer_config: SequencerConfig,
45    routing: Routing,
46
47    #[derivative(Debug = "ignore")]
48    __unknown: GlobalUnknown,
49}
50
51impl From<&Global> for ar_global_t {
52    fn from(global: &Global) -> Self {
53        let mut raw_global = Self {
54            version: break_u32_into_u8_array_be(global.version),
55            ..Default::default()
56        };
57
58        global
59            .metronome_settings
60            .apply_to_raw_global(&mut raw_global);
61        global.midi_config.apply_to_raw_global(&mut raw_global);
62        global.sequencer_config.apply_to_raw_global(&mut raw_global);
63        global.routing.apply_to_raw_global(&mut raw_global);
64
65        global.__unknown.apply_to_raw_global(&mut raw_global);
66
67        raw_global
68    }
69}
70
71impl Global {
72    pub(crate) fn as_raw_parts(&self) -> (SysexMeta, ar_global_t) {
73        (self.sysex_meta, self.into())
74    }
75
76    pub(crate) fn try_from_raw(
77        sysex_meta: SysexMeta,
78        raw_global: &ar_global_t,
79    ) -> Result<Self, RytmError> {
80        let slot_number = sysex_meta.get_normalized_object_index();
81
82        Ok(Self {
83            index: slot_number,
84            sysex_meta,
85            version: assemble_u32_from_u8_array_be(&raw_global.version),
86
87            metronome_settings: raw_global.try_into()?,
88            midi_config: raw_global.try_into()?,
89            sequencer_config: raw_global.try_into()?,
90            routing: raw_global.try_into()?,
91
92            __unknown: raw_global.into(),
93        })
94    }
95
96    /// Makes a new global complying to project defaults.
97    ///
98    /// Range `0..=3`
99    #[parameter_range(range = "global_slot:0..=3")]
100    pub fn try_default(global_slot: usize) -> Result<Self, RytmError> {
101        Self::try_default_with_device_id(global_slot, 0)
102    }
103
104    /// Makes a new global complying to project defaults.
105    ///
106    /// Global slot range `0..=3`
107    /// Device id range `0..=127`
108    #[parameter_range(range = "global_slot:0..=3", range = "device_id:0..=127")]
109    pub fn try_default_with_device_id(
110        global_slot: usize,
111        device_id: u8,
112    ) -> Result<Self, RytmError> {
113        Ok(Self {
114            index: global_slot,
115            sysex_meta: SysexMeta::try_default_for_global(global_slot, Some(device_id))?,
116            version: 2,
117
118            metronome_settings: MetronomeSettings::default(),
119            midi_config: MidiConfig::default(),
120            sequencer_config: SequencerConfig::default(),
121            routing: Routing::default(),
122
123            __unknown: GlobalUnknown::default(),
124        })
125    }
126
127    /// Makes a new global in the work buffer complying to project defaults as if it comes from the work buffer.
128    pub fn work_buffer_default() -> Self {
129        Self::work_buffer_default_with_device_id(0)
130    }
131
132    /// Makes a new global in the work buffer complying to project defaults as if it comes from the work buffer.
133    pub fn work_buffer_default_with_device_id(device_id: u8) -> Self {
134        Self {
135            index: 0,
136            sysex_meta: SysexMeta::default_for_global_in_work_buffer(Some(device_id)),
137            version: 2,
138
139            metronome_settings: MetronomeSettings::default(),
140            midi_config: MidiConfig::default(),
141            sequencer_config: SequencerConfig::default(),
142            routing: Routing::default(),
143
144            __unknown: GlobalUnknown::default(),
145        }
146    }
147
148    /// Returns the version of the global structure.
149    pub const fn structure_version(&self) -> u32 {
150        self.version
151    }
152
153    /// Checks if this global is the global at work buffer.
154    pub const fn is_work_buffer(&self) -> bool {
155        self.sysex_meta.is_targeting_work_buffer()
156    }
157
158    /// Returns the global slot index.
159    pub const fn index(&self) -> usize {
160        self.index
161    }
162
163    /// Returns the metronome settings.
164    pub const fn metronome_settings(&self) -> &MetronomeSettings {
165        &self.metronome_settings
166    }
167
168    /// Returns the metronome settings mutably.
169    pub fn metronome_settings_mut(&mut self) -> &mut MetronomeSettings {
170        &mut self.metronome_settings
171    }
172
173    /// Returns the midi config.
174    pub const fn midi_config(&self) -> &MidiConfig {
175        &self.midi_config
176    }
177
178    /// Returns the midi config mutably.
179    pub fn midi_config_mut(&mut self) -> &mut MidiConfig {
180        &mut self.midi_config
181    }
182
183    /// Returns the sequencer config.
184    pub const fn sequencer_config(&self) -> &SequencerConfig {
185        &self.sequencer_config
186    }
187
188    /// Returns the sequencer config mutably.
189    pub fn sequencer_config_mut(&mut self) -> &mut SequencerConfig {
190        &mut self.sequencer_config
191    }
192
193    /// Returns the routing.
194    pub const fn routing(&self) -> &Routing {
195        &self.routing
196    }
197
198    /// Returns the routing mutably.
199    pub fn routing_mut(&mut self) -> &mut Routing {
200        &mut self.routing
201    }
202
203    pub(crate) fn set_device_id(&mut self, device_id: u8) {
204        self.sysex_meta.set_device_id(device_id);
205    }
206}