danceinterpreter_rs/traktor_api/
model.rs

1use bytes::Bytes;
2use iced::futures::channel::mpsc;
3use serde::{Deserialize, Deserializer, Serialize};
4
5#[derive(Debug, Clone)]
6pub enum AppMessage {
7    Reconnect { debug_logging: bool },
8}
9
10#[derive(Debug, Clone)]
11pub enum ServerMessage {
12    Ready(mpsc::UnboundedSender<AppMessage>),
13    Connect {
14        time_offset_ms: i64,
15        initial_state: Box<State>,
16    },
17    Update(StateUpdate),
18    CoverImage {
19        path: String,
20        data: Bytes,
21    },
22    Log(String),
23}
24
25#[derive(Debug, Clone)]
26pub enum ID {
27    A,
28    B,
29    C,
30    D,
31}
32
33#[derive(Debug, Clone)]
34pub enum StateUpdate {
35    Mixer(MixerState),
36    Channel(ID, ChannelState),
37    DeckContent(ID, Box<DeckContentState>),
38    DeckPlayState(ID, DeckPlayState),
39}
40
41#[derive(Debug, Clone)]
42pub struct State {
43    pub mixer: MixerState,
44    pub channels: (ChannelState, ChannelState, ChannelState, ChannelState),
45    pub decks: (DeckState, DeckState, DeckState, DeckState),
46}
47
48impl State {
49    pub fn apply_update(&mut self, update: StateUpdate) {
50        match update {
51            StateUpdate::Mixer(mixer) => {
52                self.mixer = mixer;
53            }
54            StateUpdate::Channel(id, channel) => match id {
55                ID::A => {
56                    self.channels.0 = channel;
57                }
58                ID::B => {
59                    self.channels.1 = channel;
60                }
61                ID::C => {
62                    self.channels.2 = channel;
63                }
64                ID::D => {
65                    self.channels.3 = channel;
66                }
67            },
68            StateUpdate::DeckContent(id, deck_content) => match id {
69                ID::A => {
70                    self.decks.0.content = *deck_content;
71                }
72                ID::B => {
73                    self.decks.1.content = *deck_content;
74                }
75                ID::C => {
76                    self.decks.2.content = *deck_content;
77                }
78                ID::D => {
79                    self.decks.3.content = *deck_content;
80                }
81            },
82            StateUpdate::DeckPlayState(id, deck_play_state) => match id {
83                ID::A => {
84                    self.decks.0.play_state = deck_play_state;
85                }
86                ID::B => {
87                    self.decks.1.play_state = deck_play_state;
88                }
89                ID::C => {
90                    self.decks.2.play_state = deck_play_state;
91                }
92                ID::D => {
93                    self.decks.3.play_state = deck_play_state;
94                }
95            },
96        }
97    }
98}
99
100impl<'de> Deserialize<'de> for State {
101    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
102    where
103        D: Deserializer<'de>,
104    {
105        #[derive(Deserialize)]
106        struct FlattenedState {
107            mixer: MixerState,
108            channel0: ChannelState,
109            channel1: ChannelState,
110            channel2: ChannelState,
111            channel3: ChannelState,
112            deck0content: DeckContentState,
113            deck1content: DeckContentState,
114            deck2content: DeckContentState,
115            deck3content: DeckContentState,
116            deck0playstate: DeckPlayState,
117            deck1playstate: DeckPlayState,
118            deck2playstate: DeckPlayState,
119            deck3playstate: DeckPlayState,
120        }
121
122        let flattened_state: FlattenedState = Deserialize::deserialize(deserializer)?;
123
124        Ok(State {
125            mixer: flattened_state.mixer,
126            channels: (
127                flattened_state.channel0,
128                flattened_state.channel1,
129                flattened_state.channel2,
130                flattened_state.channel3,
131            ),
132            decks: (
133                DeckState {
134                    content: flattened_state.deck0content,
135                    play_state: flattened_state.deck0playstate,
136                },
137                DeckState {
138                    content: flattened_state.deck1content,
139                    play_state: flattened_state.deck1playstate,
140                },
141                DeckState {
142                    content: flattened_state.deck2content,
143                    play_state: flattened_state.deck2playstate,
144                },
145                DeckState {
146                    content: flattened_state.deck3content,
147                    play_state: flattened_state.deck3playstate,
148                },
149            ),
150        })
151    }
152}
153
154#[derive(Debug, Deserialize, Clone)]
155#[serde(rename_all = "camelCase")]
156pub struct MixerState {
157    pub x_fader: f64,
158    pub master_volume: f64,
159    pub cue_volume: f64,
160    pub cue_mix: f64,
161    pub mic_volume: f64,
162}
163
164#[derive(Debug, Deserialize, Clone)]
165#[serde(rename_all = "camelCase")]
166pub struct ChannelState {
167    pub cue: bool,
168    pub volume: f64,
169    pub x_fader_left: bool,
170    pub x_fader_right: bool,
171}
172
173#[derive(Debug, Clone)]
174pub struct DeckState {
175    pub content: DeckContentState,
176    pub play_state: DeckPlayState,
177}
178
179#[derive(Debug, Deserialize, Clone)]
180#[serde(rename_all = "camelCase")]
181pub struct DeckContentState {
182    pub is_loaded: bool,
183
184    pub number: u32,
185    pub title: String,
186    pub artist: String,
187    pub album: String,
188    pub genre: String,
189    pub comment: String,
190    pub comment2: String,
191    pub label: String,
192
193    pub key: String,
194    pub file_path: String,
195    pub track_length: f64,
196    pub bpm: f64,
197}
198
199#[derive(Debug, Deserialize, Clone)]
200pub struct DeckPlayState {
201    pub timestamp: u64,
202    pub position: f64,
203    pub speed: f64,
204}
205
206#[derive(Debug, Serialize, Clone)]
207#[serde(rename_all = "camelCase")]
208pub(in crate::traktor_api) struct ConnectionResponse {
209    pub session_id: String,
210    pub debug_logging: bool,
211}
212
213#[derive(Debug, Deserialize, Clone)]
214#[serde(rename_all = "camelCase")]
215pub(in crate::traktor_api) struct InitializeRequest {
216    pub session_id: String,
217    pub timestamp: u64,
218    pub state: State,
219}
220
221#[derive(Debug, Deserialize, Clone)]
222#[serde(rename_all = "camelCase")]
223pub(in crate::traktor_api) struct UpdateRequest<T> {
224    pub session_id: String,
225    pub state: T,
226}