Skip to main content

record_player/
state.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
4#[serde(rename_all = "lowercase")]
5pub enum DeckId { A, B }
6
7impl DeckId {
8    pub const ALL: [Self; 2] = [Self::A, Self::B];
9    pub const fn index(self) -> usize { match self { Self::A => 0, Self::B => 1 } }
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum LoadStatus { Empty, Loading, Ready, Failed }
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum SurfaceRegion { Programme, LeadIn, Deadwax }
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21pub struct PlaybackState {
22    pub load_status: LoadStatus,
23    pub duration_seconds: f64,
24    pub current_seconds: f64,
25    pub playing: bool,
26    pub pending_play_when_ready: bool,
27    pub suspended_at_seconds: Option<f64>,
28    pub playback_rate: f32,
29}
30
31impl Default for PlaybackState {
32    fn default() -> Self {
33        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 }
34    }
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub struct TransportState { pub motor_on: bool }
39impl Default for TransportState { fn default() -> Self { Self { motor_on: false } } }
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub struct NeedleState { pub lifted: bool }
43impl Default for NeedleState { fn default() -> Self { Self { lifted: true } } }
44
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46pub struct MixerState {
47    pub channel_gain: f32,
48    pub crossfader: f32,
49}
50impl Default for MixerState { fn default() -> Self { Self { channel_gain: 1.0, crossfader: 0.5 } } }
51
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct ScratchState {
54    pub active: bool,
55    pub pointer_id: Option<i32>,
56    pub was_playing: bool,
57    pub started_at_seconds: f64,
58    pub target_position_frames: f64,
59    pub rendered_position_frames: f64,
60    pub target_rate: f32,
61    pub base_rotation_degrees: f64,
62}
63impl Default for ScratchState {
64    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 } }
65}
66
67#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
68pub struct DeckState {
69    pub loaded: bool,
70    pub transport: TransportState,
71    pub needle: NeedleState,
72    pub playback: PlaybackState,
73    pub mixer: MixerState,
74    pub scratch: ScratchState,
75}
76impl Default for DeckState {
77    fn default() -> Self { Self { loaded: false, transport: TransportState::default(), needle: NeedleState::default(), playback: PlaybackState::default(), mixer: MixerState::default(), scratch: ScratchState::default() } }
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81pub struct TimedRegionState {
82    pub active: bool,
83    pub completed: bool,
84    pub started_at_ms: f64,
85    pub duration_ms: f64,
86}
87impl Default for TimedRegionState {
88    fn default() -> Self { Self { active: false, completed: false, started_at_ms: 0.0, duration_ms: 0.0 } }
89}
90
91#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
92pub struct ClipLoopState { pub active: bool, pub clip_id: Option<String> }
93impl Default for ClipLoopState { fn default() -> Self { Self { active: false, clip_id: None } } }
94
95#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
96pub struct PlayerConfig {
97    pub sample_rate: f64,
98    pub sharp_crossfader_width: f32,
99}
100impl Default for PlayerConfig { fn default() -> Self { Self { sample_rate: 48_000.0, sharp_crossfader_width: 0.08 } } }
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
103pub struct PlayerState {
104    pub decks: [DeckState; 2],
105    pub active_deck: DeckId,
106    pub lead_in: TimedRegionState,
107    pub deadwax: TimedRegionState,
108    pub clip_loop: ClipLoopState,
109}
110impl Default for PlayerState {
111    fn default() -> Self { Self { decks: [DeckState::default(), DeckState::default()], active_deck: DeckId::A, lead_in: TimedRegionState::default(), deadwax: TimedRegionState::default(), clip_loop: ClipLoopState::default() } }
112}