use ot_tools_io_derive::{AsMutDerive, AsRefDerive};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::projects::{
parse_hashmap_string_value, parse_hashmap_string_value_bool, ProjectParseError,
};
use crate::settings::ProgChMidiChannel;
#[derive(
Copy,
Clone,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct ControlMenu {
pub audio: AudioControlPage,
pub input: InputControlPage,
pub sequencer: SequencerControlPage,
pub midi_sequencer: MidiSequencerControlPage,
pub memory: MemoryControlPage,
pub metronome: MetronomeControlPage,
pub midi: MidiSubMenu,
}
impl TryFrom<&HashMap<String, String>> for ControlMenu {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let audio = AudioControlPage::try_from(value)?;
let input = InputControlPage::try_from(value)?;
let sequencer = SequencerControlPage::try_from(value)?;
let midi_sequencer = MidiSequencerControlPage {};
let memory = MemoryControlPage::try_from(value)?;
let metronome = MetronomeControlPage::try_from(value)?;
let midi = MidiSubMenu::try_from(value)?;
Ok(Self {
audio,
input,
sequencer,
midi_sequencer,
memory,
metronome,
midi,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiSubMenu {
pub control: MidiControlMidiPage,
pub sync: MidiSyncMidiPage,
pub channels: MidiChannelsMidiPage,
}
impl TryFrom<&HashMap<String, String>> for MidiSubMenu {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let control = MidiControlMidiPage::try_from(value)?;
let sync = MidiSyncMidiPage::try_from(value)?;
let channels = MidiChannelsMidiPage::try_from(value)?;
Ok(Self {
control,
sync,
channels,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioControlPage {
pub master_track: bool,
pub cue_studio_mode: bool,
}
#[allow(clippy::derivable_impls)] impl Default for AudioControlPage {
fn default() -> Self {
Self {
master_track: false,
cue_studio_mode: false,
}
}
}
impl TryFrom<&HashMap<String, String>> for AudioControlPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let master_track = parse_hashmap_string_value_bool(value, "master_track", None)?;
let cue_studio_mode = parse_hashmap_string_value_bool(value, "cue_studio_mode", None)?;
Ok(Self {
master_track,
cue_studio_mode,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct InputControlPage {
pub gate_ab: u8,
pub gate_cd: u8,
pub input_delay_compensation: bool,
}
impl Default for InputControlPage {
fn default() -> Self {
Self {
gate_ab: 127,
gate_cd: 127,
input_delay_compensation: false,
}
}
}
impl TryFrom<&HashMap<String, String>> for InputControlPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let gate_ab = parse_hashmap_string_value::<u8>(value, "gate_ab", None)?;
let gate_cd = parse_hashmap_string_value::<u8>(value, "gate_cd", None)?;
let input_delay_compensation =
parse_hashmap_string_value_bool(value, "input_delay_compensation", None)?;
Ok(Self {
gate_ab,
gate_cd,
input_delay_compensation,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct SequencerControlPage {
pub pattern_change_chain_behaviour: u8,
pub pattern_change_auto_silence_tracks: bool,
pub pattern_change_auto_trig_lfos: bool,
}
#[allow(clippy::derivable_impls)] impl Default for SequencerControlPage {
fn default() -> Self {
SequencerControlPage {
pattern_change_chain_behaviour: 0,
pattern_change_auto_silence_tracks: false,
pattern_change_auto_trig_lfos: false,
}
}
}
impl TryFrom<&HashMap<String, String>> for SequencerControlPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let pattern_change_chain_behaviour =
parse_hashmap_string_value::<u8>(value, "pattern_change_chain_behavior", None)?;
let pattern_change_auto_silence_tracks =
parse_hashmap_string_value_bool(value, "pattern_change_auto_trig_lfos", None)?;
let pattern_change_auto_trig_lfos =
parse_hashmap_string_value_bool(value, "pattern_change_auto_trig_lfos", None)?;
Ok(Self {
pattern_change_chain_behaviour,
pattern_change_auto_silence_tracks,
pattern_change_auto_trig_lfos,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiSequencerControlPage {}
#[allow(clippy::derivable_impls)] impl Default for MidiSequencerControlPage {
fn default() -> Self {
Self {}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MemoryControlPage {
pub load_24bit_flex: bool,
pub dynamic_recorders: bool,
pub record_24bit: bool,
pub reserved_recorder_count: u8,
pub reserved_recorder_length: u32,
}
impl Default for MemoryControlPage {
fn default() -> Self {
Self {
load_24bit_flex: false,
dynamic_recorders: false,
record_24bit: false,
reserved_recorder_count: 8,
reserved_recorder_length: 16,
}
}
}
impl TryFrom<&HashMap<String, String>> for MemoryControlPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let load_24bit_flex = parse_hashmap_string_value_bool(value, "load_24bit_flex", None)?;
let dynamic_recorders = parse_hashmap_string_value_bool(value, "dynamic_recorders", None)?;
let record_24bit = parse_hashmap_string_value_bool(value, "record_24bit", None)?;
let reserved_recorder_count =
parse_hashmap_string_value::<u8>(value, "reserved_recorder_count", None)?;
let reserved_recorder_length =
parse_hashmap_string_value::<u32>(value, "reserved_recorder_length", None)?;
Ok(Self {
load_24bit_flex,
dynamic_recorders,
record_24bit,
reserved_recorder_count,
reserved_recorder_length,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MetronomeControlPage {
pub metronome_time_signature: u8,
pub metronome_time_signature_denominator: u8,
pub metronome_preroll: u8,
pub metronome_cue_volume: u8,
pub metronome_main_volume: u8,
pub metronome_pitch: u8,
pub metronome_tonal: bool,
pub metronome_enabled: bool,
}
impl Default for MetronomeControlPage {
fn default() -> Self {
Self {
metronome_time_signature: 3,
metronome_time_signature_denominator: 2,
metronome_preroll: 0,
metronome_cue_volume: 32,
metronome_main_volume: 0,
metronome_pitch: 12,
metronome_tonal: true,
metronome_enabled: false,
}
}
}
impl TryFrom<&HashMap<String, String>> for MetronomeControlPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let metronome_time_signature =
parse_hashmap_string_value::<u8>(value, "metronome_time_signature", None)?;
let metronome_time_signature_denominator =
parse_hashmap_string_value::<u8>(value, "metronome_time_signature_denominator", None)?;
let metronome_preroll = parse_hashmap_string_value::<u8>(value, "metronome_preroll", None)?;
let metronome_cue_volume =
parse_hashmap_string_value::<u8>(value, "metronome_cue_volume", None)?;
let metronome_main_volume =
parse_hashmap_string_value::<u8>(value, "metronome_main_volume", None)?;
let metronome_pitch = parse_hashmap_string_value::<u8>(value, "metronome_pitch", None)?;
let metronome_tonal = parse_hashmap_string_value_bool(value, "metronome_tonal", None)?;
let metronome_enabled = parse_hashmap_string_value_bool(value, "metronome_enabled", None)?;
Ok(Self {
metronome_time_signature,
metronome_time_signature_denominator,
metronome_preroll,
metronome_cue_volume,
metronome_main_volume,
metronome_pitch,
metronome_tonal,
metronome_enabled,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiControlMidiPage {
pub midi_audio_track_cc_in: bool,
pub midi_audio_track_cc_out: u8,
pub midi_audio_track_note_in: u8,
pub midi_audio_track_note_out: u8,
pub midi_midi_track_cc_in: u8,
}
impl Default for MidiControlMidiPage {
fn default() -> Self {
Self {
midi_audio_track_cc_in: true,
midi_audio_track_cc_out: 3,
midi_audio_track_note_in: 1,
midi_audio_track_note_out: 3,
midi_midi_track_cc_in: 1,
}
}
}
impl TryFrom<&HashMap<String, String>> for MidiControlMidiPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let midi_audio_track_cc_in =
parse_hashmap_string_value_bool(value, "midi_audio_trk_cc_in", None)?;
let midi_audio_track_cc_out =
parse_hashmap_string_value::<u8>(value, "midi_audio_trk_cc_out", None)?;
let midi_audio_track_note_in =
parse_hashmap_string_value::<u8>(value, "midi_audio_trk_note_in", None)?;
let midi_audio_track_note_out =
parse_hashmap_string_value::<u8>(value, "midi_audio_trk_note_out", None)?;
let midi_midi_track_cc_in =
parse_hashmap_string_value::<u8>(value, "midi_midi_trk_cc_in", None)?;
Ok(Self {
midi_audio_track_cc_in,
midi_audio_track_cc_out,
midi_audio_track_note_in,
midi_audio_track_note_out,
midi_midi_track_cc_in,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiSyncMidiPage {
pub midi_clock_send: bool,
pub midi_clock_receive: bool,
pub midi_transport_send: bool,
pub midi_transport_receive: bool,
pub midi_progchange_send: bool,
pub midi_progchange_send_channel: ProgChMidiChannel,
pub midi_progchange_receive: bool,
pub midi_progchange_receive_channel: ProgChMidiChannel,
}
impl Default for MidiSyncMidiPage {
fn default() -> Self {
Self {
midi_clock_send: false,
midi_clock_receive: false,
midi_transport_send: false,
midi_transport_receive: false,
midi_progchange_send: false,
midi_progchange_send_channel: ProgChMidiChannel::Auto,
midi_progchange_receive: false,
midi_progchange_receive_channel: ProgChMidiChannel::Auto,
}
}
}
impl TryFrom<&HashMap<String, String>> for MidiSyncMidiPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let midi_clock_send = parse_hashmap_string_value_bool(value, "midi_clock_send", None)?;
let midi_clock_receive =
parse_hashmap_string_value_bool(value, "midi_clock_receive", None)?;
let midi_transport_send =
parse_hashmap_string_value_bool(value, "midi_transport_send", None)?;
let midi_transport_receive =
parse_hashmap_string_value_bool(value, "midi_transport_receive", None)?;
let midi_progchange_send =
parse_hashmap_string_value_bool(value, "midi_program_change_send", None)?;
let midi_progchange_send_channel = ProgChMidiChannel::try_from(
&parse_hashmap_string_value::<i8>(value, "midi_program_change_send_ch", None)?,
)?;
let midi_progchange_receive =
parse_hashmap_string_value_bool(value, "midi_program_change_receive", None)?;
let midi_progchange_receive_channel = ProgChMidiChannel::try_from(
&parse_hashmap_string_value::<i8>(value, "midi_program_change_receive_ch", None)?,
)?;
Ok(Self {
midi_clock_send,
midi_clock_receive,
midi_transport_send,
midi_transport_receive,
midi_progchange_send,
midi_progchange_send_channel,
midi_progchange_receive,
midi_progchange_receive_channel,
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiChannelsMidiPage {
pub midi_trig_ch1: i8,
pub midi_trig_ch2: i8,
pub midi_trig_ch3: i8,
pub midi_trig_ch4: i8,
pub midi_trig_ch5: i8,
pub midi_trig_ch6: i8,
pub midi_trig_ch7: i8,
pub midi_trig_ch8: i8,
pub midi_auto_channel: i8,
}
impl Default for MidiChannelsMidiPage {
fn default() -> Self {
Self {
midi_trig_ch1: 0,
midi_trig_ch2: 1,
midi_trig_ch3: 2,
midi_trig_ch4: 3,
midi_trig_ch5: 4,
midi_trig_ch6: 5,
midi_trig_ch7: 6,
midi_trig_ch8: 7,
midi_auto_channel: 10,
}
}
}
impl TryFrom<&HashMap<String, String>> for MidiChannelsMidiPage {
type Error = ProjectParseError;
fn try_from(value: &HashMap<String, String>) -> Result<Self, Self::Error> {
let midi_trig_ch1 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch1", None)?;
let midi_trig_ch2 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch2", None)?;
let midi_trig_ch3 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch3", None)?;
let midi_trig_ch4 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch4", None)?;
let midi_trig_ch5 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch5", None)?;
let midi_trig_ch6 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch6", None)?;
let midi_trig_ch7 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch7", None)?;
let midi_trig_ch8 = parse_hashmap_string_value::<i8>(value, "midi_trig_ch8", None)?;
let midi_auto_channel = parse_hashmap_string_value::<i8>(value, "midi_auto_channel", None)?;
Ok(Self {
midi_trig_ch1,
midi_trig_ch2,
midi_trig_ch3,
midi_trig_ch4,
midi_trig_ch5,
midi_trig_ch6,
midi_trig_ch7,
midi_trig_ch8,
midi_auto_channel,
})
}
}