1#![allow(
5 clippy::cast_lossless,
6 clippy::cast_possible_truncation,
7 clippy::cast_sign_loss
8)]
9pub mod types;
12pub(crate) mod unknown;
13
14use self::types::{
15 FxParameterMenuItem, ParameterMenuItem, PatternMode, SampleRecorderRecordingLength,
16 SampleRecorderSource, SequencerMode,
17};
18use crate::{
19 error::{ParameterError, RytmError, SysexConversionError},
20 impl_sysex_compatible,
21 sysex::{SysexCompatible, SysexMeta, SysexType, SETTINGS_SYSEX_SIZE},
22 util::{assemble_u32_from_u8_array_be, break_u32_into_u8_array_be},
23 AnySysexType,
24};
25use derivative::Derivative;
26use rytm_rs_macro::parameter_range;
27use rytm_sys::{ar_settings_raw_to_syx, ar_settings_t, ar_sysex_meta_t};
28use serde::{Deserialize, Serialize};
29use unknown::SettingsUnknown;
30
31impl_sysex_compatible!(
32 Settings,
33 ar_settings_t,
34 ar_settings_raw_to_syx,
35 SysexType::Settings,
36 SETTINGS_SYSEX_SIZE
37);
38
39#[derive(Derivative, Clone, Copy, Serialize, Deserialize)]
45#[derivative(Debug)]
46pub struct Settings {
47 #[derivative(Debug = "ignore")]
48 sysex_meta: SysexMeta,
49 version: u32,
51
52 bpm_project: f32,
53
54 selected_track: u8,
55 selected_parameter_menu_item: ParameterMenuItem,
56 selected_fx_menu_item: FxParameterMenuItem,
57 selected_page: u8,
58 selected_mode: SequencerMode,
59 selected_pattern_mode: PatternMode,
60
61 mute_flags: u16,
62
63 fixed_velocity_enable: bool,
64 fixed_velocity_amount: u8,
65
66 sample_recorder_src: SampleRecorderSource,
67 sample_recorder_thr: u8,
68 sample_recorder_monitor_enable: bool,
69 sample_recorder_rlen: SampleRecorderRecordingLength,
70
71 __unknown: SettingsUnknown,
73}
74
75impl From<&Settings> for ar_settings_t {
76 fn from(settings: &Settings) -> Self {
77 let bpm = (settings.bpm_project * 120.0) as u16;
78 let bpm_msb = (bpm >> 8) as u8;
79 let bpm_lsb = bpm as u8;
80
81 let track_mute_msb = (settings.mute_flags >> 8) as u8;
82 let track_mute_lsb = settings.mute_flags as u8;
83
84 let mut raw_settings = Self {
85 version: break_u32_into_u8_array_be(settings.version),
86 bpm_msb,
87 bpm_lsb,
88 selected_track: settings.selected_track,
89 _selected_track_duplicate: settings.selected_track,
90 selected_trig_or_parameter_menu: settings.selected_parameter_menu_item.into(),
91 selected_fx_menu: settings.selected_fx_menu_item.into(),
92 selected_page: settings.selected_page,
93
94 track_mute_msb,
95 track_mute_lsb,
96
97 selected_mode: settings.selected_mode.into(),
98 selected_pattern_transition_mode: settings.selected_pattern_mode.into(),
99
100 fixed_velocity_enable: settings.fixed_velocity_enable.into(),
101 fixed_velocity_amount: settings.fixed_velocity_amount,
102
103 sample_recorder_src: settings.sample_recorder_src.into(),
104 sample_recorder_thr: settings.sample_recorder_thr,
105 sample_recorder_monitor: settings.sample_recorder_monitor_enable.into(),
106
107 sample_recorder_rlen: settings.sample_recorder_rlen.into(),
108
109 ..Default::default()
110 };
111
112 settings.__unknown.apply_to_raw_settings(&mut raw_settings);
113
114 raw_settings
115 }
116}
117
118impl Default for Settings {
119 fn default() -> Self {
120 Self::try_default_with_device_id(0).unwrap()
121 }
122}
123
124impl Settings {
125 #[parameter_range(range = "device_id:0..=127")]
129 pub fn try_default_with_device_id(device_id: u8) -> Result<Self, RytmError> {
130 Ok(Self {
131 sysex_meta: SysexMeta::default_for_settings(Some(device_id)),
132 version: 3,
133 bpm_project: 120.0,
134 selected_track: 0,
135
136 selected_parameter_menu_item: ParameterMenuItem::default(),
137 selected_fx_menu_item: FxParameterMenuItem::default(),
138 selected_page: 0,
139
140 mute_flags: 0,
141
142 selected_mode: SequencerMode::default(),
143 selected_pattern_mode: PatternMode::default(),
144
145 fixed_velocity_enable: false,
146 fixed_velocity_amount: 100,
147 sample_recorder_src: SampleRecorderSource::default(),
148 sample_recorder_thr: 0,
149 sample_recorder_monitor_enable: false,
150
151 sample_recorder_rlen: SampleRecorderRecordingLength::default(),
152
153 __unknown: SettingsUnknown::default(),
154 })
155 }
156
157 pub(crate) fn as_raw_parts(&self) -> (SysexMeta, ar_settings_t) {
158 (self.sysex_meta, self.into())
159 }
160
161 pub(crate) fn try_from_raw(
162 sysex_meta: SysexMeta,
163 raw_settings: &ar_settings_t,
164 ) -> Result<Self, RytmError> {
165 let bpm_project = (raw_settings.bpm_msb as u16) << 8 | raw_settings.bpm_lsb as u16;
166 let bpm_project = bpm_project as f32 / 120.0;
167
168 let mute_flags =
169 (raw_settings.track_mute_msb as u16) << 8 | raw_settings.track_mute_lsb as u16;
170
171 Ok(Self {
172 sysex_meta,
173 version: assemble_u32_from_u8_array_be(&raw_settings.version),
174 bpm_project,
175 selected_track: raw_settings.selected_track,
176
177 selected_parameter_menu_item: raw_settings
178 .selected_trig_or_parameter_menu
179 .try_into()?,
180 selected_fx_menu_item: raw_settings.selected_fx_menu.try_into()?,
181 selected_page: raw_settings.selected_page,
182
183 mute_flags,
184
185 selected_mode: raw_settings.selected_mode.try_into()?,
186 selected_pattern_mode: raw_settings.selected_pattern_transition_mode.try_into()?,
187
188 fixed_velocity_enable: raw_settings.fixed_velocity_enable != 0,
189 fixed_velocity_amount: raw_settings.fixed_velocity_amount,
190
191 sample_recorder_src: raw_settings.sample_recorder_src.try_into()?,
192 sample_recorder_thr: raw_settings.sample_recorder_thr,
193 sample_recorder_monitor_enable: raw_settings.sample_recorder_monitor != 0,
194 sample_recorder_rlen: raw_settings.sample_recorder_rlen.try_into()?,
195
196 __unknown: raw_settings.into(),
197 })
198 }
199
200 #[parameter_range(range = "bpm:30.0..=300.0")]
206 pub fn set_bpm(&mut self, bpm: f32) -> Result<(), RytmError> {
207 self.bpm_project = bpm;
208 Ok(())
209 }
210
211 #[parameter_range(range = "track_index:0..=11")]
215 pub fn set_selected_track(&mut self, track_index: usize) -> Result<(), RytmError> {
216 self.selected_track = track_index as u8;
217 Ok(())
218 }
219
220 pub fn set_selected_parameter_menu_item(&mut self, parameter_menu_item: ParameterMenuItem) {
224 self.selected_parameter_menu_item = parameter_menu_item;
225 }
226
227 pub fn set_selected_fx_menu_item(&mut self, fx_menu_item: FxParameterMenuItem) {
233 self.selected_fx_menu_item = fx_menu_item;
234 }
235
236 #[parameter_range(range = "page_index:0..=3")]
242 pub fn set_selected_page(&mut self, page_index: usize) -> Result<(), RytmError> {
243 self.selected_page = page_index as u8;
244 Ok(())
245 }
246
247 pub fn set_selected_mode(&mut self, sequencer_mode: SequencerMode) {
249 self.selected_mode = sequencer_mode;
250 }
251
252 pub fn set_selected_pattern_mode(&mut self, pattern_mode: PatternMode) {
254 self.selected_pattern_mode = pattern_mode;
255 }
256
257 #[parameter_range(range = "mute_flags:0..=4095")]
261 pub fn set_mute_flags(&mut self, mute_flags: u16) -> Result<(), RytmError> {
262 self.mute_flags = mute_flags;
263 Ok(())
264 }
265
266 #[parameter_range(range = "sound_index:0..=11")]
270 pub fn mute_sound(&mut self, sound_index: usize) -> Result<(), RytmError> {
271 self.mute_flags |= 1 << sound_index;
272 Ok(())
273 }
274
275 #[parameter_range(range = "sound_index:0..=11")]
279 pub fn unmute_sound(&mut self, sound_index: usize) -> Result<(), RytmError> {
280 self.mute_flags &= !(1 << sound_index);
281 Ok(())
282 }
283
284 #[parameter_range(range = "sound_index:0..=11")]
288 pub fn toggle_mute_sound(&mut self, sound_index: usize) -> Result<(), RytmError> {
289 self.mute_flags ^= 1 << sound_index;
290 Ok(())
291 }
292
293 pub fn mute_range_of_sounds(&mut self, range: std::ops::Range<usize>) -> Result<(), RytmError> {
301 if range.end > 11 {
302 return Err(RytmError::Parameter(ParameterError::Range {
303 value: format!("{range:?}",),
304 parameter_name: "range".to_string(),
305 }));
306 }
307
308 for sound_index in range {
309 self.mute_sound(sound_index)?;
310 }
311
312 Ok(())
313 }
314
315 pub fn unmute_range_of_sounds(
323 &mut self,
324 range: std::ops::Range<usize>,
325 ) -> Result<(), RytmError> {
326 for sound_index in range {
327 self.unmute_sound(sound_index)?;
328 }
329 Ok(())
330 }
331
332 pub fn toggle_mute_range_of_sounds(
340 &mut self,
341 range: std::ops::Range<usize>,
342 ) -> Result<(), RytmError> {
343 for sound_index in range {
344 self.toggle_mute_sound(sound_index)?;
345 }
346 Ok(())
347 }
348
349 pub fn set_fixed_velocity_enable(&mut self, fixed_velocity_enable: bool) {
351 self.fixed_velocity_enable = fixed_velocity_enable;
352 }
353
354 #[parameter_range(range = "fixed_velocity_amount:0..=127")]
358 pub fn set_fixed_velocity_amount(
359 &mut self,
360 fixed_velocity_amount: usize,
361 ) -> Result<(), RytmError> {
362 self.fixed_velocity_amount = fixed_velocity_amount as u8;
363 Ok(())
364 }
365
366 pub fn set_sample_recorder_source(&mut self, sample_recorder_source: SampleRecorderSource) {
368 self.sample_recorder_src = sample_recorder_source;
369 }
370
371 #[parameter_range(range = "sample_recorder_threshold:0..=127")]
375 pub fn set_sample_recorder_threshold(
376 &mut self,
377 sample_recorder_threshold: usize,
378 ) -> Result<(), RytmError> {
379 self.sample_recorder_thr = sample_recorder_threshold as u8;
380 Ok(())
381 }
382
383 pub fn set_sample_recorder_monitor_enable(&mut self, set_sample_recorder_monitor_enable: bool) {
385 self.sample_recorder_monitor_enable = set_sample_recorder_monitor_enable;
386 }
387
388 pub fn set_sample_recorder_recording_length(
390 &mut self,
391 sample_recorder_recording_length: SampleRecorderRecordingLength,
392 ) {
393 self.sample_recorder_rlen = sample_recorder_recording_length;
394 }
395
396 pub const fn bpm(&self) -> f32 {
402 self.bpm_project
403 }
404
405 pub const fn selected_track(&self) -> usize {
409 self.selected_track as usize
410 }
411
412 pub const fn selected_parameter_menu_item(&self) -> ParameterMenuItem {
414 self.selected_parameter_menu_item
415 }
416
417 pub const fn selected_fx_menu_item(&self) -> FxParameterMenuItem {
419 self.selected_fx_menu_item
420 }
421
422 pub const fn selected_page(&self) -> usize {
426 self.selected_page as usize
427 }
428
429 pub const fn selected_mode(&self) -> SequencerMode {
431 self.selected_mode
432 }
433
434 pub const fn selected_pattern_mode(&self) -> PatternMode {
436 self.selected_pattern_mode
437 }
438
439 pub const fn raw_mute_flags(&self) -> u16 {
441 self.mute_flags
442 }
443
444 pub fn muted_sound_indexes(&self) -> Vec<usize> {
446 let mut muted_track_numbers = Vec::new();
447 for sound_index in 0..=11 {
448 if self.mute_flags & (1 << sound_index) != 0 {
449 muted_track_numbers.push(sound_index);
450 }
451 }
452 muted_track_numbers
453 }
454
455 pub fn unmuted_sound_indexes(&self) -> Vec<usize> {
457 let mut unmuted_sound_indexes = Vec::new();
458 for sound_index in 0..=11 {
459 if self.mute_flags & (1 << sound_index) == 0 {
460 unmuted_sound_indexes.push(sound_index);
461 }
462 }
463 unmuted_sound_indexes
464 }
465
466 #[parameter_range(range = "sound_index:0..=11")]
468 pub fn is_sound_muted(&self, sound_index: usize) -> Result<bool, RytmError> {
469 Ok(self.mute_flags & (1 << sound_index) != 0)
470 }
471
472 pub const fn fixed_velocity_enabled(&self) -> bool {
474 self.fixed_velocity_enable
475 }
476
477 pub const fn fixed_velocity_amount(&self) -> usize {
481 self.fixed_velocity_amount as usize
482 }
483
484 pub const fn sample_recorder_source(&self) -> SampleRecorderSource {
486 self.sample_recorder_src
487 }
488
489 pub const fn sample_recorder_threshold(&self) -> usize {
493 self.sample_recorder_thr as usize
494 }
495
496 pub const fn sample_recorder_monitor_enabled(&self) -> bool {
498 self.sample_recorder_monitor_enable
499 }
500
501 pub const fn sample_recorder_recording_length(&self) -> SampleRecorderRecordingLength {
503 self.sample_recorder_rlen
504 }
505
506 pub const fn structure_version(&self) -> u32 {
508 self.version
509 }
510
511 pub(crate) fn set_device_id(&mut self, device_id: u8) {
512 self.sysex_meta.set_device_id(device_id);
513 }
514}