Skip to main content

danceinterpreter_rs/traktor_api/
model.rs

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