use crate::core::cell::Cell;
use crate::core::fixed::fixed::Q15;
use alloc::{string::String, vec::Vec};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Track {
Notes {
name: String,
instrument: usize,
rows: Vec<Cell>,
muted: bool,
},
Euclidean {
name: String,
instrument: usize,
muted: bool,
events: u8,
steps: u8,
rotation: u8,
prototype: Cell,
humanize_advance_max_ticks: u8,
humanize_probability: Q15,
},
}
impl Default for Track {
fn default() -> Self {
Track::Notes {
name: String::new(),
instrument: 0,
rows: Vec::new(),
muted: false,
}
}
}
impl Track {
#[inline]
pub fn name(&self) -> &str {
match self {
Track::Notes { name, .. } | Track::Euclidean { name, .. } => name,
}
}
#[inline]
pub fn name_mut(&mut self) -> &mut String {
match self {
Track::Notes { name, .. } | Track::Euclidean { name, .. } => name,
}
}
#[inline]
pub fn instrument(&self) -> usize {
match self {
Track::Notes { instrument, .. } | Track::Euclidean { instrument, .. } => *instrument,
}
}
#[inline]
pub fn set_instrument(&mut self, idx: usize) {
match self {
Track::Notes { instrument, .. } | Track::Euclidean { instrument, .. } => {
*instrument = idx;
}
}
}
#[inline]
pub fn muted(&self) -> bool {
match self {
Track::Notes { muted, .. } | Track::Euclidean { muted, .. } => *muted,
}
}
#[inline]
pub fn set_muted(&mut self, m: bool) {
match self {
Track::Notes { muted, .. } | Track::Euclidean { muted, .. } => {
*muted = m;
}
}
}
#[inline]
pub fn is_euclidean(&self) -> bool {
matches!(self, Track::Euclidean { .. })
}
#[inline]
pub fn rows(&self) -> Option<&[Cell]> {
match self {
Track::Notes { rows, .. } => Some(rows),
Track::Euclidean { .. } => None,
}
}
#[inline]
pub fn rows_mut(&mut self) -> Option<&mut Vec<Cell>> {
match self {
Track::Notes { rows, .. } => Some(rows),
Track::Euclidean { .. } => None,
}
}
#[doc(hidden)]
#[track_caller]
pub fn expect_notes_rows(&self) -> &[Cell] {
self.rows().expect("Track is not Track::Notes")
}
#[doc(hidden)]
#[track_caller]
pub fn expect_notes_rows_mut(&mut self) -> &mut Vec<Cell> {
self.rows_mut().expect("Track is not Track::Notes")
}
pub fn cell_at(&self, row: u32) -> Cell {
match self {
Track::Notes { rows, .. } => rows.get(row as usize).cloned().unwrap_or_default(),
Track::Euclidean {
events,
steps,
rotation,
prototype,
..
} => {
let steps_u32 = (*steps).max(1) as u32;
let pos = row % steps_u32;
let rot = (*rotation as u32) % steps_u32;
let bjork_idx = ((pos + steps_u32 - rot) % steps_u32) as usize;
let canonical = crate::core::daw::euclidean::euclidean_pattern(*events, *steps);
if canonical.get(bjork_idx).copied().unwrap_or(false) {
prototype.clone()
} else {
Cell::default()
}
}
}
}
pub fn natural_length(&self) -> usize {
match self {
Track::Notes { rows, .. } => rows.len(),
Track::Euclidean { steps, .. } => *steps as usize,
}
}
}