use crate::projects::{
parse_hashmap_string_value, parse_hashmap_string_value_bool, string_to_hashmap,
ProjectParseError, SectionHeader,
};
use ot_tools_io_derive::{AsMutDerive, AsRefDerive};
use serde::{Deserialize, Serialize};
#[derive(
Copy,
Clone,
Debug,
Default, // todo: surely this isn't correct? all zero values?
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct State {
pub bank: u8,
pub pattern: u8,
pub arrangement: u8,
pub arrangement_mode: u8,
pub part: u8,
pub track: u8,
pub track_othermode: u8,
pub scene_a_mute: bool,
pub scene_b_mute: bool,
pub track_cue_mask: u8,
pub track_mute_mask: u8,
pub track_solo_mask: u8,
pub midi_track_mute_mask: u8,
pub midi_track_solo_mask: u8,
pub midi_mode: u8,
}
impl std::str::FromStr for State {
type Err = ProjectParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let hmap = string_to_hashmap(s, &SectionHeader::States)?;
Ok(Self {
bank: parse_hashmap_string_value::<u8>(&hmap, "bank", None)?,
pattern: parse_hashmap_string_value::<u8>(&hmap, "pattern", None)?,
arrangement: parse_hashmap_string_value::<u8>(&hmap, "arrangement", None)?,
arrangement_mode: parse_hashmap_string_value::<u8>(&hmap, "arrangement_mode", None)?,
part: parse_hashmap_string_value::<u8>(&hmap, "part", None)?,
track: parse_hashmap_string_value::<u8>(&hmap, "track", None)?,
track_othermode: parse_hashmap_string_value::<u8>(&hmap, "track_othermode", None)?,
scene_a_mute: parse_hashmap_string_value_bool(&hmap, "scene_a_mute", None)?,
scene_b_mute: parse_hashmap_string_value_bool(&hmap, "scene_b_mute", None)?,
track_cue_mask: parse_hashmap_string_value::<u8>(&hmap, "track_cue_mask", None)?,
track_mute_mask: parse_hashmap_string_value::<u8>(&hmap, "track_mute_mask", None)?,
track_solo_mask: parse_hashmap_string_value::<u8>(&hmap, "track_solo_mask", None)?,
midi_track_mute_mask: parse_hashmap_string_value::<u8>(
&hmap,
"midi_track_mute_mask",
None,
)?,
midi_track_solo_mask: parse_hashmap_string_value::<u8>(
&hmap,
"midi_track_solo_mask",
None,
)?,
midi_mode: parse_hashmap_string_value::<u8>(&hmap, "midi_mode", None)?,
})
}
}
impl std::fmt::Display for State {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut s = "".to_string();
s.push_str("[STATES]\r\n");
s.push_str(format!("BANK={}", self.bank).as_str());
s.push_str("\r\n");
s.push_str(format!("PATTERN={}", self.pattern).as_str());
s.push_str("\r\n");
s.push_str(format!("ARRANGEMENT={}", self.arrangement).as_str());
s.push_str("\r\n");
s.push_str(format!("ARRANGEMENT_MODE={}", self.arrangement_mode).as_str());
s.push_str("\r\n");
s.push_str(format!("PART={}", self.part).as_str());
s.push_str("\r\n");
s.push_str(format!("TRACK={}", self.track).as_str());
s.push_str("\r\n");
s.push_str(format!("TRACK_OTHERMODE={}", self.track_othermode).as_str());
s.push_str("\r\n");
s.push_str(format!("SCENE_A_MUTE={}", self.scene_a_mute as u8).as_str());
s.push_str("\r\n");
s.push_str(format!("SCENE_B_MUTE={}", self.scene_b_mute as u8).as_str());
s.push_str("\r\n");
s.push_str(format!("TRACK_CUE_MASK={}", self.track_cue_mask).as_str());
s.push_str("\r\n");
s.push_str(format!("TRACK_MUTE_MASK={}", self.track_mute_mask).as_str());
s.push_str("\r\n");
s.push_str(format!("TRACK_SOLO_MASK={}", self.track_solo_mask).as_str());
s.push_str("\r\n");
s.push_str(format!("MIDI_TRACK_MUTE_MASK={}", self.midi_track_mute_mask).as_str());
s.push_str("\r\n");
s.push_str(format!("MIDI_TRACK_SOLO_MASK={}", self.midi_track_solo_mask).as_str());
s.push_str("\r\n");
s.push_str(format!("MIDI_MODE={}", self.midi_mode).as_str());
s.push_str("\r\n[/STATES]");
write!(f, "{s:#}")
}
}