danceinterpreter_rs/traktor_api/
model.rs1use 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}