175 lines
4.2 KiB
Rust
175 lines
4.2 KiB
Rust
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<Self> {
|
|
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<String>,
|
|
}
|
|
|
|
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<Step>,
|
|
pub length: usize,
|
|
#[serde(default)]
|
|
pub speed: PatternSpeed,
|
|
#[serde(default)]
|
|
pub name: Option<String>,
|
|
}
|
|
|
|
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<Pattern>,
|
|
#[serde(default)]
|
|
pub name: Option<String>,
|
|
}
|
|
|
|
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<Bank>,
|
|
}
|
|
|
|
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]
|
|
}
|
|
}
|