use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DeckId { A, B }
impl DeckId {
pub const ALL: [Self; 2] = [Self::A, Self::B];
pub const fn index(self) -> usize { match self { Self::A => 0, Self::B => 1 } }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum LoadStatus { Empty, Loading, Ready, Failed }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SurfaceRegion { Programme, LeadIn, Deadwax }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlaybackState {
pub load_status: LoadStatus,
pub duration_seconds: f64,
pub current_seconds: f64,
pub playing: bool,
pub pending_play_when_ready: bool,
pub suspended_at_seconds: Option<f64>,
pub playback_rate: f32,
}
impl Default for PlaybackState {
fn default() -> Self {
Self { load_status: LoadStatus::Empty, duration_seconds: 0.0, current_seconds: 0.0, playing: false, pending_play_when_ready: false, suspended_at_seconds: None, playback_rate: 1.0 }
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TransportState { pub motor_on: bool }
impl Default for TransportState { fn default() -> Self { Self { motor_on: false } } }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct NeedleState { pub lifted: bool }
impl Default for NeedleState { fn default() -> Self { Self { lifted: true } } }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MixerState {
pub channel_gain: f32,
pub crossfader: f32,
}
impl Default for MixerState { fn default() -> Self { Self { channel_gain: 1.0, crossfader: 0.5 } } }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ScratchState {
pub active: bool,
pub pointer_id: Option<i32>,
pub was_playing: bool,
pub started_at_seconds: f64,
pub target_position_frames: f64,
pub rendered_position_frames: f64,
pub target_rate: f32,
pub base_rotation_degrees: f64,
}
impl Default for ScratchState {
fn default() -> Self { Self { active: false, pointer_id: None, was_playing: false, started_at_seconds: 0.0, target_position_frames: 0.0, rendered_position_frames: 0.0, target_rate: 0.0, base_rotation_degrees: 0.0 } }
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeckState {
pub loaded: bool,
pub transport: TransportState,
pub needle: NeedleState,
pub playback: PlaybackState,
pub mixer: MixerState,
pub scratch: ScratchState,
}
impl Default for DeckState {
fn default() -> Self { Self { loaded: false, transport: TransportState::default(), needle: NeedleState::default(), playback: PlaybackState::default(), mixer: MixerState::default(), scratch: ScratchState::default() } }
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TimedRegionState {
pub active: bool,
pub completed: bool,
pub started_at_ms: f64,
pub duration_ms: f64,
}
impl Default for TimedRegionState {
fn default() -> Self { Self { active: false, completed: false, started_at_ms: 0.0, duration_ms: 0.0 } }
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClipLoopState { pub active: bool, pub clip_id: Option<String> }
impl Default for ClipLoopState { fn default() -> Self { Self { active: false, clip_id: None } } }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlayerConfig {
pub sample_rate: f64,
pub sharp_crossfader_width: f32,
}
impl Default for PlayerConfig { fn default() -> Self { Self { sample_rate: 48_000.0, sharp_crossfader_width: 0.08 } } }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlayerState {
pub decks: [DeckState; 2],
pub active_deck: DeckId,
pub lead_in: TimedRegionState,
pub deadwax: TimedRegionState,
pub clip_loop: ClipLoopState,
}
impl Default for PlayerState {
fn default() -> Self { Self { decks: [DeckState::default(), DeckState::default()], active_deck: DeckId::A, lead_in: TimedRegionState::default(), deadwax: TimedRegionState::default(), clip_loop: ClipLoopState::default() } }
}