use serde::{Deserialize, Serialize}; use crate::config::{DEFAULT_LENGTH, MAX_BANKS, MAX_PATTERNS, MAX_STEPS}; #[derive(Clone, Copy, Serialize, Deserialize, Default, PartialEq)] pub enum PatternSpeed { Eighth, // 1/8x Quarter, // 1/4x Half, // 1/2x #[default] Normal, // 1x Double, // 2x Quad, // 4x Octo, // 8x } impl PatternSpeed { pub fn multiplier(&self) -> f64 { match self { Self::Eighth => 0.125, Self::Quarter => 0.25, Self::Half => 0.5, Self::Normal => 1.0, Self::Double => 2.0, Self::Quad => 4.0, Self::Octo => 8.0, } } pub fn label(&self) -> &'static str { match self { Self::Eighth => "1/8x", Self::Quarter => "1/4x", Self::Half => "1/2x", Self::Normal => "1x", Self::Double => "2x", Self::Quad => "4x", Self::Octo => "8x", } } pub fn next(&self) -> Self { match self { Self::Eighth => Self::Quarter, Self::Quarter => Self::Half, Self::Half => Self::Normal, Self::Normal => Self::Double, Self::Double => Self::Quad, Self::Quad => Self::Octo, Self::Octo => Self::Octo, } } pub fn prev(&self) -> Self { match self { Self::Eighth => Self::Eighth, Self::Quarter => Self::Eighth, Self::Half => Self::Quarter, Self::Normal => Self::Half, Self::Double => Self::Normal, Self::Quad => Self::Double, Self::Octo => Self::Quad, } } pub fn from_label(s: &str) -> Option { match s.trim() { "1/8x" | "1/8" | "0.125x" => Some(Self::Eighth), "1/4x" | "1/4" | "0.25x" => Some(Self::Quarter), "1/2x" | "1/2" | "0.5x" => Some(Self::Half), "1x" | "1" => Some(Self::Normal), "2x" | "2" => Some(Self::Double), "4x" | "4" => Some(Self::Quad), "8x" | "8" => Some(Self::Octo), _ => None, } } } #[derive(Clone, Serialize, Deserialize)] pub struct Step { pub active: bool, pub script: String, #[serde(skip)] pub command: Option, } impl Default for Step { fn default() -> Self { Self { active: true, script: String::new(), command: None, } } } #[derive(Clone, Serialize, Deserialize)] pub struct Pattern { pub steps: Vec, pub length: usize, #[serde(default)] pub speed: PatternSpeed, #[serde(default)] pub name: Option, } impl Default for Pattern { fn default() -> Self { Self { steps: (0..MAX_STEPS).map(|_| Step::default()).collect(), length: DEFAULT_LENGTH, speed: PatternSpeed::default(), name: None, } } } impl Pattern { pub fn step(&self, index: usize) -> Option<&Step> { self.steps.get(index) } pub fn step_mut(&mut self, index: usize) -> Option<&mut Step> { self.steps.get_mut(index) } pub fn set_length(&mut self, length: usize) { let length = length.clamp(2, MAX_STEPS); while self.steps.len() < length { self.steps.push(Step::default()); } self.length = length; } } #[derive(Clone, Serialize, Deserialize)] pub struct Bank { pub patterns: Vec, #[serde(default)] pub name: Option, } impl Default for Bank { fn default() -> Self { Self { patterns: (0..MAX_PATTERNS).map(|_| Pattern::default()).collect(), name: None, } } } #[derive(Clone, Serialize, Deserialize)] pub struct Project { pub banks: Vec, } impl Default for Project { fn default() -> Self { Self { banks: (0..MAX_BANKS).map(|_| Bank::default()).collect(), } } } impl Project { pub fn pattern_at(&self, bank: usize, pattern: usize) -> &Pattern { &self.banks[bank].patterns[pattern] } pub fn pattern_at_mut(&mut self, bank: usize, pattern: usize) -> &mut Pattern { &mut self.banks[bank].patterns[pattern] } }