ot_tools_io/projects/
settings.rs

1/*
2SPDX-License-Identifier: GPL-3.0-or-later
3Copyright © 2024 Mike Robeson [dijksterhuis]
4*/
5
6//! Model and parsing of a global project settings
7//! e.g. whether Track 8 is a master track or not.
8//! Used in the [crate::projects::ProjectFile] type.
9
10pub mod control_menu;
11pub mod mixer;
12pub mod tempo;
13pub mod trig_mode_midi_tracks;
14
15use control_menu::{
16    AudioControlPage, ControlMenu, InputControlPage, MemoryControlPage, MetronomeControlPage,
17    MidiChannelsMidiPage, MidiControlMidiPage, MidiSequencerControlPage, MidiSubMenu,
18    MidiSyncMidiPage, SequencerControlPage,
19};
20
21use mixer::MixerMenu;
22use tempo::TempoMenu;
23use trig_mode_midi_tracks::MidiTrackTrigModes;
24
25use serde::{Deserialize, Serialize};
26
27use crate::{OptionEnumValueConvert, RBoxErr};
28
29use crate::projects::{
30    options::ProjectMidiChannels, parse_hashmap_string_value_bool, string_to_hashmap, FromHashMap,
31    ProjectFromString, ProjectRawFileSection, ProjectToString,
32};
33
34/*
35Example data:
36[SETTINGS]\r\nWRITEPROTECTED=0\r\nTEMPOx24=2880\r\nPATTERN_TEMPO_ENABLED=0\r\nMIDI_CLOCK_SEND=0\r\nMIDI_CLOCK_RECEIVE=0\r\nMIDI_TRANSPORT_SEND=0\r\nMIDI_TRANSPORT_RECEIVE=0\r\nMIDI_PROGRAM_CHANGE_SEND=0\r\nMIDI_PROGRAM_CHANGE_SEND_CH=-1\r\nMIDI_PROGRAM_CHANGE_RECEIVE=0\r\nMIDI_PROGRAM_CHANGE_RECEIVE_CH=-1\r\nMIDI_TRIG_CH1=0\r\nMIDI_TRIG_CH2=1\r\nMIDI_TRIG_CH3=2\r\nMIDI_TRIG_CH4=3\r\nMIDI_TRIG_CH5=4\r\nMIDI_TRIG_CH6=5\r\nMIDI_TRIG_CH7=6\r\nMIDI_TRIG_CH8=7\r\nMIDI_AUTO_CHANNEL=10\r\nMIDI_SOFT_THRU=0\r\nMIDI_AUDIO_TRK_CC_IN=1\r\nMIDI_AUDIO_TRK_CC_OUT=3\r\nMIDI_AUDIO_TRK_NOTE_IN=1\r\nMIDI_AUDIO_TRK_NOTE_OUT=3\r\nMIDI_MIDI_TRK_CC_IN=1\r\nPATTERN_CHANGE_CHAIN_BEHAVIOR=0\r\nPATTERN_CHANGE_AUTO_SILENCE_TRACKS=0\r\nPATTERN_CHANGE_AUTO_TRIG_LFOS=0\r\nLOAD_24BIT_FLEX=0\r\nDYNAMIC_RECORDERS=0\r\nRECORD_24BIT=0\r\nRESERVED_RECORDER_COUNT=8\r\nRESERVED_RECORDER_LENGTH=16\r\nINPUT_DELAY_COMPENSATION=0\r\nGATE_AB=127\r\nGATE_CD=127\r\nGAIN_AB=64\r\nGAIN_CD=64\r\nDIR_AB=0\r\nDIR_CD=0\r\nPHONES_MIX=64\r\nMAIN_TO_CUE=0\r\nMASTER_TRACK=0\r\nCUE_STUDIO_MODE=0\r\nMAIN_LEVEL=64\r\nCUE_LEVEL=64\r\nMETRONOME_TIME_SIGNATURE=3\r\nMETRONOME_TIME_SIGNATURE_DENOMINATOR=2\r\nMETRONOME_PREROLL=0\r\nMETRONOME_CUE_VOLUME=32\r\nMETRONOME_MAIN_VOLUME=0\r\nMETRONOME_PITCH=12\r\nMETRONOME_TONAL=1\r\nMETRONOME_ENABLED=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\nTRIG_MODE_MIDI=0\r\n[/SETTINGS]
37----
38
39[SETTINGS]
40WRITEPROTECTED=0
41TEMPOx24=2880
42PATTERN_TEMPO_ENABLED=0
43MIDI_CLOCK_SEND=0
44MIDI_CLOCK_RECEIVE=0
45MIDI_TRANSPORT_SEND=0
46MIDI_TRANSPORT_RECEIVE=0
47MIDI_PROGRAM_CHANGE_SEND=0
48MIDI_PROGRAM_CHANGE_SEND_CH=-1
49MIDI_PROGRAM_CHANGE_RECEIVE=0
50MIDI_PROGRAM_CHANGE_RECEIVE_CH=-1
51MIDI_TRIG_CH1=0\r\nMIDI_TRIG_CH2=1
52MIDI_TRIG_CH3=2\r\nMIDI_TRIG_CH4=3
53MIDI_TRIG_CH5=4\r\nMIDI_TRIG_CH6=5
54MIDI_TRIG_CH7=6\r\nMIDI_TRIG_CH8=7
55MIDI_AUTO_CHANNEL=10
56MIDI_SOFT_THRU=0
57MIDI_AUDIO_TRK_CC_IN=1
58MIDI_AUDIO_TRK_CC_OUT=3
59MIDI_AUDIO_TRK_NOTE_IN=1
60MIDI_AUDIO_TRK_NOTE_OUT=3
61MIDI_MIDI_TRK_CC_IN=1
62PATTERN_CHANGE_CHAIN_BEHAVIOR=0
63PATTERN_CHANGE_AUTO_SILENCE_TRACKS=0
64PATTERN_CHANGE_AUTO_TRIG_LFOS=0
65LOAD_24BIT_FLEX=0
66DYNAMIC_RECORDERS=0
67RECORD_24BIT=0
68RESERVED_RECORDER_COUNT=8
69RESERVED_RECORDER_LENGTH=16
70INPUT_DELAY_COMPENSATION=0
71GATE_AB=127
72GATE_CD=127
73GAIN_AB=64
74GAIN_CD=64
75DIR_AB=0
76DIR_CD=0
77PHONES_MIX=64
78MAIN_TO_CUE=0
79MASTER_TRACK=0
80CUE_STUDIO_MODE=0
81MAIN_LEVEL=64
82CUE_LEVEL=64
83METRONOME_TIME_SIGNATURE=3
84METRONOME_TIME_SIGNATURE_DENOMINATOR=2
85METRONOME_PREROLL=0
86METRONOME_CUE_VOLUME=32
87METRONOME_MAIN_VOLUME=0
88METRONOME_PITCH=12
89METRONOME_TONAL=1
90METRONOME_ENABLED=0
91TRIG_MODE_MIDI=0
92TRIG_MODE_MIDI=0
93TRIG_MODE_MIDI=0
94TRIG_MODE_MIDI=0
95TRIG_MODE_MIDI=0
96TRIG_MODE_MIDI=0
97TRIG_MODE_MIDI=0
98TRIG_MODE_MIDI=0
99[/SETTINGS]
100*/
101
102/// Project settings read from a parsed Octatrack Project file
103
104#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
105pub struct ProjectSettings {
106    /// Whether the project can be written to (is currently being read/written when `true`)
107    pub write_protected: bool,
108
109    /// Current settings in the `Project`'s control menu UI.
110    pub control: ControlMenu,
111
112    /// Unknown: Whether MIDI 'Thru' is enabled/disabled?
113    pub midi_soft_thru: bool,
114
115    /// Current state of the settings in the Mixer Menu overview
116    pub mixer: MixerMenu,
117
118    /// Current state of the settings in the Tempo menu
119    pub tempo: TempoMenu,
120
121    /// Current selections for MIDI Track Trig Mode
122    pub midi_tracks_trig_mode: MidiTrackTrigModes,
123}
124
125impl Default for ProjectSettings {
126    fn default() -> Self {
127        Self {
128            write_protected: false,
129            control: ControlMenu {
130                audio: AudioControlPage {
131                    master_track: false,
132                    cue_studio_mode: false,
133                },
134                input: InputControlPage {
135                    gate_ab: 127,
136                    gate_cd: 127,
137                    input_delay_compensation: false,
138                },
139                sequencer: SequencerControlPage {
140                    pattern_change_chain_behaviour: 0,
141                    pattern_change_auto_silence_tracks: false,
142                    pattern_change_auto_trig_lfos: false,
143                },
144                midi_sequencer: MidiSequencerControlPage {},
145                memory: MemoryControlPage {
146                    load_24bit_flex: false,
147                    dynamic_recorders: false,
148                    record_24bit: false,
149                    reserved_recorder_count: 8,
150                    reserved_recorder_length: 16,
151                },
152                metronome: MetronomeControlPage {
153                    metronome_time_signature: 3,
154                    metronome_time_signature_denominator: 2,
155                    metronome_preroll: 0,
156                    metronome_cue_volume: 32,
157                    metronome_main_volume: 0,
158                    metronome_pitch: 12,
159                    metronome_tonal: true,
160                    metronome_enabled: false,
161                },
162                midi: MidiSubMenu {
163                    control: MidiControlMidiPage {
164                        midi_audio_track_cc_in: true,
165                        midi_audio_track_cc_out: 3,
166                        midi_audio_track_note_in: 1,
167                        midi_audio_track_note_out: 3,
168                        midi_midi_track_cc_in: 1,
169                    },
170                    sync: MidiSyncMidiPage {
171                        midi_clock_send: false,
172                        midi_clock_receive: false,
173                        midi_transport_send: false,
174                        midi_transport_receive: false,
175                        midi_progchange_send: false,
176                        midi_progchange_send_channel: ProjectMidiChannels::Disabled,
177                        midi_progchange_receive: false,
178                        midi_progchange_receive_channel: ProjectMidiChannels::Disabled,
179                    },
180                    channels: MidiChannelsMidiPage {
181                        midi_trig_ch1: 0,
182                        midi_trig_ch2: 1,
183                        midi_trig_ch3: 2,
184                        midi_trig_ch4: 3,
185                        midi_trig_ch5: 4,
186                        midi_trig_ch6: 5,
187                        midi_trig_ch7: 6,
188                        midi_trig_ch8: 7,
189                        midi_auto_channel: 10,
190                    },
191                },
192            },
193            midi_soft_thru: false,
194            mixer: MixerMenu {
195                gain_ab: 64,
196                gain_cd: 64,
197                dir_ab: 0,
198                dir_cd: 0,
199                phones_mix: 64,
200                main_to_cue: 0,
201                main_level: 64,
202                cue_level: 64,
203            },
204            tempo: TempoMenu {
205                tempo: 120,
206                pattern_tempo_enabled: false,
207            },
208            midi_tracks_trig_mode: MidiTrackTrigModes {
209                trig_mode_midi_track_1: 0,
210                trig_mode_midi_track_2: 0,
211                trig_mode_midi_track_3: 0,
212                trig_mode_midi_track_4: 0,
213                trig_mode_midi_track_5: 0,
214                trig_mode_midi_track_6: 0,
215                trig_mode_midi_track_7: 0,
216                trig_mode_midi_track_8: 0,
217            },
218        }
219    }
220}
221
222impl ProjectFromString for ProjectSettings {
223    type T = Self;
224
225    /// Load project 'state' data from the raw project ASCII file.
226    fn from_string(s: &str) -> RBoxErr<Self> {
227        let hmap = string_to_hashmap(s, &ProjectRawFileSection::Settings)?;
228
229        Ok(Self {
230            write_protected: parse_hashmap_string_value_bool(&hmap, "writeprotected", None)?,
231            // Unknown: Whether MIDI 'Thru' is enabled/disabled?
232            midi_soft_thru: parse_hashmap_string_value_bool(&hmap, "midi_soft_thru", None)?,
233            //
234            control: ControlMenu::from_hashmap(&hmap)?,
235            mixer: MixerMenu::from_hashmap(&hmap)?,
236            tempo: TempoMenu::from_hashmap(&hmap)?,
237            midi_tracks_trig_mode: MidiTrackTrigModes::from_hashmap(&hmap)?,
238        })
239    }
240}
241
242impl ProjectToString for ProjectSettings {
243    /// Extract `OctatrackProjectMetadata` fields from the project file's ASCII data
244    fn to_string(&self) -> RBoxErr<String> {
245        let mut s = "".to_string();
246        s.push_str("[SETTINGS]");
247        s.push_str("\r\n");
248
249        s.push_str(format!("WRITEPROTECTED={}", self.write_protected as u8).as_str());
250        s.push_str("\r\n");
251        s.push_str(format!("TEMPOx24={}", self.tempo.tempo * 24).as_str());
252        s.push_str("\r\n");
253        s.push_str(
254            format!(
255                "PATTERN_TEMPO_ENABLED={}",
256                self.tempo.pattern_tempo_enabled as u8
257            )
258            .as_str(),
259        );
260        s.push_str("\r\n");
261
262        s.push_str(
263            format!(
264                "MIDI_CLOCK_SEND={}",
265                self.control.midi.sync.midi_clock_send as u8
266            )
267            .as_str(),
268        );
269        s.push_str("\r\n");
270        s.push_str(
271            format!(
272                "MIDI_CLOCK_RECEIVE={}",
273                self.control.midi.sync.midi_clock_receive as u8
274            )
275            .as_str(),
276        );
277        s.push_str("\r\n");
278        s.push_str(
279            format!(
280                "MIDI_TRANSPORT_SEND={}",
281                self.control.midi.sync.midi_transport_send as u8
282            )
283            .as_str(),
284        );
285        s.push_str("\r\n");
286        s.push_str(
287            format!(
288                "MIDI_TRANSPORT_RECEIVE={}",
289                self.control.midi.sync.midi_transport_receive as u8
290            )
291            .as_str(),
292        );
293        s.push_str("\r\n");
294        s.push_str(
295            format!(
296                "MIDI_PROGRAM_CHANGE_SEND={}",
297                self.control.midi.sync.midi_progchange_send as u8
298            )
299            .as_str(),
300        );
301        s.push_str("\r\n");
302        s.push_str(
303            format!(
304                "MIDI_PROGRAM_CHANGE_SEND_CH={}",
305                self.control
306                    .midi
307                    .sync
308                    .midi_progchange_send_channel
309                    .value()?
310            )
311            .as_str(),
312        );
313        s.push_str("\r\n");
314        s.push_str(
315            format!(
316                "MIDI_PROGRAM_CHANGE_RECEIVE={}",
317                self.control.midi.sync.midi_progchange_receive as u8
318            )
319            .as_str(),
320        );
321        s.push_str("\r\n");
322        s.push_str(
323            format!(
324                "MIDI_PROGRAM_CHANGE_RECEIVE_CH={}",
325                self.control
326                    .midi
327                    .sync
328                    .midi_progchange_receive_channel
329                    .value()?
330            )
331            .as_str(),
332        );
333        s.push_str("\r\n");
334
335        s.push_str(format!("MIDI_TRIG_CH1={}", self.control.midi.channels.midi_trig_ch1).as_str());
336        s.push_str("\r\n");
337        s.push_str(format!("MIDI_TRIG_CH2={}", self.control.midi.channels.midi_trig_ch2).as_str());
338        s.push_str("\r\n");
339        s.push_str(format!("MIDI_TRIG_CH3={}", self.control.midi.channels.midi_trig_ch3).as_str());
340        s.push_str("\r\n");
341        s.push_str(format!("MIDI_TRIG_CH4={}", self.control.midi.channels.midi_trig_ch4).as_str());
342        s.push_str("\r\n");
343        s.push_str(format!("MIDI_TRIG_CH5={}", self.control.midi.channels.midi_trig_ch5).as_str());
344        s.push_str("\r\n");
345        s.push_str(format!("MIDI_TRIG_CH6={}", self.control.midi.channels.midi_trig_ch6).as_str());
346        s.push_str("\r\n");
347        s.push_str(format!("MIDI_TRIG_CH7={}", self.control.midi.channels.midi_trig_ch7).as_str());
348        s.push_str("\r\n");
349        s.push_str(format!("MIDI_TRIG_CH8={}", self.control.midi.channels.midi_trig_ch8).as_str());
350        s.push_str("\r\n");
351        s.push_str(
352            format!(
353                "MIDI_AUTO_CHANNEL={}",
354                self.control.midi.channels.midi_auto_channel
355            )
356            .as_str(),
357        );
358        s.push_str("\r\n");
359
360        s.push_str(format!("MIDI_SOFT_THRU={}", self.midi_soft_thru as u8).as_str());
361        s.push_str("\r\n");
362
363        s.push_str(
364            format!(
365                "MIDI_AUDIO_TRK_CC_IN={}",
366                self.control.midi.control.midi_audio_track_cc_in as u8
367            )
368            .as_str(),
369        );
370        s.push_str("\r\n");
371        s.push_str(
372            format!(
373                "MIDI_AUDIO_TRK_CC_OUT={}",
374                self.control.midi.control.midi_audio_track_cc_out
375            )
376            .as_str(),
377        );
378        s.push_str("\r\n");
379        s.push_str(
380            format!("MIDI_AUDIO_TRK_NOTE_IN={}", {
381                self.control.midi.control.midi_audio_track_note_in
382            })
383            .as_str(),
384        );
385        s.push_str("\r\n");
386        s.push_str(
387            format!(
388                "MIDI_AUDIO_TRK_NOTE_OUT={}",
389                self.control.midi.control.midi_audio_track_note_out
390            )
391            .as_str(),
392        );
393        s.push_str("\r\n");
394        s.push_str(
395            format!(
396                "MIDI_MIDI_TRK_CC_IN={}",
397                self.control.midi.control.midi_midi_track_cc_in
398            )
399            .as_str(),
400        );
401        s.push_str("\r\n");
402
403        s.push_str(
404            format!(
405                "PATTERN_CHANGE_CHAIN_BEHAVIOR={}",
406                self.control.sequencer.pattern_change_chain_behaviour
407            )
408            .as_str(),
409        );
410        s.push_str("\r\n");
411        s.push_str(
412            format!(
413                "PATTERN_CHANGE_AUTO_SILENCE_TRACKS={}",
414                self.control.sequencer.pattern_change_auto_silence_tracks as u8
415            )
416            .as_str(),
417        );
418        s.push_str("\r\n");
419        s.push_str(
420            format!(
421                "PATTERN_CHANGE_AUTO_TRIG_LFOS={}",
422                self.control.sequencer.pattern_change_auto_trig_lfos as u8
423            )
424            .as_str(),
425        );
426        s.push_str("\r\n");
427
428        s.push_str(
429            format!(
430                "LOAD_24BIT_FLEX={}",
431                self.control.memory.load_24bit_flex as u8
432            )
433            .as_str(),
434        );
435        s.push_str("\r\n");
436        s.push_str(
437            format!(
438                "DYNAMIC_RECORDERS={}",
439                self.control.memory.dynamic_recorders as u8
440            )
441            .as_str(),
442        );
443        s.push_str("\r\n");
444        s.push_str(format!("RECORD_24BIT={}", self.control.memory.record_24bit as u8).as_str());
445        s.push_str("\r\n");
446        s.push_str(
447            format!(
448                "RESERVED_RECORDER_COUNT={}",
449                self.control.memory.reserved_recorder_count
450            )
451            .as_str(),
452        );
453        s.push_str("\r\n");
454        s.push_str(
455            format!(
456                "RESERVED_RECORDER_LENGTH={}",
457                self.control.memory.reserved_recorder_length
458            )
459            .as_str(),
460        );
461        s.push_str("\r\n");
462
463        s.push_str(
464            format!(
465                "INPUT_DELAY_COMPENSATION={}",
466                self.control.input.input_delay_compensation as u8
467            )
468            .as_str(),
469        );
470        s.push_str("\r\n");
471
472        s.push_str(format!("GATE_AB={}", self.control.input.gate_ab).as_str());
473        s.push_str("\r\n");
474        s.push_str(format!("GATE_CD={}", self.control.input.gate_cd).as_str());
475        s.push_str("\r\n");
476        s.push_str(format!("GAIN_AB={}", self.mixer.gain_ab).as_str());
477        s.push_str("\r\n");
478        s.push_str(format!("GAIN_CD={}", self.mixer.gain_cd).as_str());
479        s.push_str("\r\n");
480        s.push_str(format!("DIR_AB={}", self.mixer.dir_ab).as_str());
481        s.push_str("\r\n");
482        s.push_str(format!("DIR_CD={}", self.mixer.dir_cd).as_str());
483        s.push_str("\r\n");
484        s.push_str(format!("PHONES_MIX={}", self.mixer.phones_mix).as_str());
485        s.push_str("\r\n");
486        s.push_str(format!("MAIN_TO_CUE={}", self.mixer.main_to_cue).as_str());
487        s.push_str("\r\n");
488
489        s.push_str(format!("MASTER_TRACK={}", self.control.audio.master_track as u8).as_str());
490        s.push_str("\r\n");
491        s.push_str(
492            format!(
493                "CUE_STUDIO_MODE={}",
494                self.control.audio.cue_studio_mode as u8
495            )
496            .as_str(),
497        );
498        s.push_str("\r\n");
499
500        s.push_str(format!("MAIN_LEVEL={}", self.mixer.main_level).as_str());
501        s.push_str("\r\n");
502        s.push_str(format!("CUE_LEVEL={}", self.mixer.cue_level).as_str());
503        s.push_str("\r\n");
504
505        s.push_str(
506            format!(
507                "METRONOME_TIME_SIGNATURE={}",
508                self.control.metronome.metronome_time_signature
509            )
510            .as_str(),
511        );
512        s.push_str("\r\n");
513        s.push_str(
514            format!(
515                "METRONOME_TIME_SIGNATURE_DENOMINATOR={}",
516                self.control.metronome.metronome_time_signature_denominator
517            )
518            .as_str(),
519        );
520        s.push_str("\r\n");
521        s.push_str(
522            format!(
523                "METRONOME_PREROLL={}",
524                self.control.metronome.metronome_preroll
525            )
526            .as_str(),
527        );
528        s.push_str("\r\n");
529        s.push_str(
530            format!(
531                "METRONOME_CUE_VOLUME={}",
532                self.control.metronome.metronome_cue_volume
533            )
534            .as_str(),
535        );
536        s.push_str("\r\n");
537        s.push_str(
538            format!(
539                "METRONOME_MAIN_VOLUME={}",
540                self.control.metronome.metronome_main_volume
541            )
542            .as_str(),
543        );
544        s.push_str("\r\n");
545        s.push_str(format!("METRONOME_PITCH={}", self.control.metronome.metronome_pitch).as_str());
546        s.push_str("\r\n");
547        s.push_str(
548            format!(
549                "METRONOME_TONAL={}",
550                self.control.metronome.metronome_tonal as u8
551            )
552            .as_str(),
553        );
554        s.push_str("\r\n");
555        s.push_str(
556            format!(
557                "METRONOME_ENABLED={}",
558                self.control.metronome.metronome_enabled as u8
559            )
560            .as_str(),
561        );
562        s.push_str("\r\n");
563
564        s.push_str(
565            format!(
566                "TRIG_MODE_MIDI={}",
567                self.midi_tracks_trig_mode.trig_mode_midi_track_1
568            )
569            .as_str(),
570        );
571        s.push_str("\r\n");
572        s.push_str(
573            format!(
574                "TRIG_MODE_MIDI={}",
575                self.midi_tracks_trig_mode.trig_mode_midi_track_2
576            )
577            .as_str(),
578        );
579        s.push_str("\r\n");
580        s.push_str(
581            format!(
582                "TRIG_MODE_MIDI={}",
583                self.midi_tracks_trig_mode.trig_mode_midi_track_3
584            )
585            .as_str(),
586        );
587        s.push_str("\r\n");
588        s.push_str(
589            format!(
590                "TRIG_MODE_MIDI={}",
591                self.midi_tracks_trig_mode.trig_mode_midi_track_4
592            )
593            .as_str(),
594        );
595        s.push_str("\r\n");
596        s.push_str(
597            format!(
598                "TRIG_MODE_MIDI={}",
599                self.midi_tracks_trig_mode.trig_mode_midi_track_5
600            )
601            .as_str(),
602        );
603        s.push_str("\r\n");
604        s.push_str(
605            format!(
606                "TRIG_MODE_MIDI={}",
607                self.midi_tracks_trig_mode.trig_mode_midi_track_6
608            )
609            .as_str(),
610        );
611        s.push_str("\r\n");
612        s.push_str(
613            format!(
614                "TRIG_MODE_MIDI={}",
615                self.midi_tracks_trig_mode.trig_mode_midi_track_7
616            )
617            .as_str(),
618        );
619        s.push_str("\r\n");
620        s.push_str(
621            format!(
622                "TRIG_MODE_MIDI={}",
623                self.midi_tracks_trig_mode.trig_mode_midi_track_8
624            )
625            .as_str(),
626        );
627
628        s.push_str("\r\n[/SETTINGS]");
629
630        Ok(s)
631    }
632}