Skip to main content

danceinterpreter_rs/dataloading/dataprovider/
mod.rs

1use crate::dataloading::displayable_data::DisplayableData;
2use crate::dataloading::songinfo::SongInfo;
3use crate::dataloading::staticinfo::StaticInfo;
4use crate::traktor_api;
5use crate::traktor_api::TraktorDataProvider;
6use std::cmp::PartialEq;
7
8#[derive(Default, Debug, PartialEq, Clone)]
9pub enum ItemSource {
10    #[default]
11    Blank,
12    Traktor,
13    Other(SongInfo),
14    Static(usize),
15    Playlist(usize),
16}
17
18#[derive(Debug, Clone, Copy)]
19pub enum ItemChange {
20    Blank,
21    Traktor,
22    StaticAbsolute(usize),
23    PlaylistAbsolute(usize),
24    Previous,
25    Next,
26}
27#[derive(Debug, Clone)]
28pub enum SongDataEdit {
29    Title(String),
30    Artist(String),
31    Dance(String),
32}
33
34#[derive(Debug, Clone)]
35pub enum StaticDataEdit {
36    Name(String),
37}
38
39#[derive(Default)]
40pub struct DataProvider {
41    pub playlist_songs: Vec<SongInfo>,
42    pub playlist_played: Vec<bool>,
43
44    pub statics: Vec<StaticInfo>,
45
46    pub traktor_provider: TraktorDataProvider,
47
48    pub current: ItemSource,
49    pub next: Option<ItemSource>,
50
51    should_scroll: bool,
52}
53
54impl DataProvider {
55    pub fn set_vec(&mut self, vec: Vec<SongInfo>) {
56        self.playlist_songs = vec;
57        self.playlist_played = vec![false; self.playlist_songs.len()];
58
59        if !self.playlist_songs.is_empty() {
60            self.current = ItemSource::Playlist(0);
61        } else {
62            self.current = ItemSource::Blank;
63        }
64    }
65
66    pub fn set_statics(&mut self, vec: Vec<StaticInfo>) {
67        self.statics = vec;
68    }
69
70    fn set_current_as_played(&mut self) {
71        let i = match self.current {
72            ItemSource::Playlist(i) => i,
73            ItemSource::Traktor => {
74                let Some(index) = self.get_current_traktor_index() else {
75                    return;
76                };
77                index
78            }
79            _ => return,
80        };
81
82        if let Some(v) = self.playlist_played.get_mut(i) {
83            *v = true;
84        }
85    }
86
87    pub fn get_current_displayable_data(&self) -> Option<DisplayableData> {
88        match self.current {
89            ItemSource::Static(i) => self.statics.get(i).map(|s| s.into()),
90            ItemSource::Playlist(i) => self.playlist_songs.get(i).map(|s| s.into()),
91            ItemSource::Other(ref song) => Some(song.into()),
92            ItemSource::Blank => None,
93            ItemSource::Traktor => self.traktor_provider.get_song_info().map(|s| s.into()),
94        }
95    }
96    pub fn get_next_displayable_data(&self) -> Option<DisplayableData> {
97        if let Some(next) = self.next.as_ref() {
98            return match next {
99                ItemSource::Static(i) => self.statics.get(*i).map(|s| s.into()),
100                ItemSource::Playlist(i) => self.playlist_songs.get(*i).map(|s| s.into()),
101                ItemSource::Other(song) => Some(song.into()),
102                ItemSource::Blank => None,
103                ItemSource::Traktor => self.traktor_provider.get_next_song_info().map(|s| s.into()),
104            };
105        }
106
107        match self.current {
108            ItemSource::Static(_) => None,
109            ItemSource::Playlist(i) => self.playlist_songs.get(i + 1).map(|s| s.into()),
110            ItemSource::Other(ref song) => Some(song.into()),
111            ItemSource::Blank => None,
112            ItemSource::Traktor => self.traktor_provider.get_next_song_info().map(|s| s.into()),
113        }
114    }
115
116    pub fn prev(&mut self) {
117        self.should_scroll = true;
118
119        let ItemSource::Playlist(current_index) = self.current else {
120            return;
121        };
122
123        if current_index == 0 {
124            return;
125        }
126
127        self.set_current_as_played();
128        self.current = ItemSource::Playlist(current_index - 1);
129    }
130
131    pub fn next(&mut self) {
132        self.should_scroll = true;
133
134        if let Some(next) = self.next.take() {
135            self.set_current_as_played();
136            self.current = next;
137            return;
138        }
139
140        let ItemSource::Playlist(current_index) = self.current else {
141            return;
142        };
143
144        if current_index == self.playlist_songs.len() - 1 {
145            return;
146        }
147
148        self.set_current_as_played();
149        self.current = ItemSource::Playlist(current_index + 1);
150    }
151
152    pub fn set_current(&mut self, n: ItemSource) {
153        self.set_current_as_played();
154
155        match n {
156            ItemSource::Static(i) => {
157                if self.playlist_songs.get(i).is_some() {
158                    self.current = n;
159                }
160            }
161            ItemSource::Playlist(i) => {
162                if self.playlist_songs.get(i).is_some() {
163                    self.current = n;
164                }
165            }
166            _ => self.current = n,
167        }
168    }
169
170    pub fn set_next(&mut self, next: ItemSource) {
171        self.next = Some(next);
172    }
173
174    pub fn append_song(&mut self, song: SongInfo) {
175        self.playlist_songs.push(song);
176        self.playlist_played.push(false);
177    }
178
179    pub fn add_static(&mut self) {
180        self.statics.push(StaticInfo::default());
181    }
182
183    pub fn toggle_static_favorite(&mut self, index: usize) {
184        if let Some(song) = self.statics.get_mut(index) {
185            song.is_favorite = !song.is_favorite;
186        }
187    }
188
189    pub fn handle_static_data_edit(&mut self, index: usize, edit: StaticDataEdit) {
190        if let Some(s) = self.statics.get_mut(index) {
191            match edit {
192                StaticDataEdit::Name(name) => s.name = name,
193            }
194        }
195    }
196
197    pub fn delete_item(&mut self, song: ItemSource) {
198        if self.current == song {
199            self.current = ItemSource::Blank;
200        } else if self.next == Some(song.clone()) {
201            self.next = None;
202        }
203
204        if let ItemSource::Playlist(i) = song {
205            self.playlist_songs.remove(i);
206            self.playlist_played.remove(i);
207        } else if let ItemSource::Static(i) = song {
208            self.statics.remove(i);
209        }
210    }
211
212    pub fn handle_item_change(&mut self, change: ItemChange) {
213        match change {
214            ItemChange::Blank => {
215                self.set_current_as_played();
216                self.current = ItemSource::Blank;
217            }
218            ItemChange::Traktor => {
219                self.set_current_as_played();
220                self.current = ItemSource::Traktor;
221            }
222            ItemChange::StaticAbsolute(index) => {
223                self.traktor_provider.sync = false;
224                self.set_current_as_played();
225                self.current = ItemSource::Static(index);
226            }
227            ItemChange::PlaylistAbsolute(index) => {
228                self.set_current_as_played();
229                self.current = ItemSource::Playlist(index);
230            }
231            ItemChange::Previous => {
232                self.prev();
233            }
234            ItemChange::Next => {
235                self.next();
236            }
237        }
238    }
239
240    pub fn handle_song_data_edit(&mut self, i: usize, edit: SongDataEdit) {
241        if let Some(song) = self.playlist_songs.get_mut(i) {
242            match edit {
243                SongDataEdit::Title(title) => {
244                    song.title = title;
245                }
246                SongDataEdit::Artist(artist) => {
247                    song.artist = artist;
248                }
249                SongDataEdit::Dance(dance) => {
250                    song.dance = dance;
251                }
252            }
253        }
254    }
255
256    pub fn process_traktor_message(&mut self, message: traktor_api::ServerMessage) {
257        self.set_current_as_played();
258        self.traktor_provider
259            .process_message(message, &self.playlist_songs);
260    }
261
262    pub fn get_current_traktor_index(&self) -> Option<usize> {
263        self.traktor_provider
264            .get_current_index(&self.playlist_songs)
265    }
266
267    pub fn take_scroll_index(&mut self) -> Option<usize> {
268        let should_scroll = self.should_scroll | self.traktor_provider.take_should_scroll();
269        self.should_scroll = false;
270
271        if !should_scroll {
272            return None;
273        }
274
275        match self.current {
276            ItemSource::Traktor => self.get_current_traktor_index(),
277            ItemSource::Playlist(i) => Some(i),
278            _ => None,
279        }
280    }
281
282    pub fn get_play_state(&self, playlist_index: usize) -> (bool, bool, bool, bool) {
283        let mut is_current = false;
284        let mut is_next = false;
285        let mut is_traktor = false;
286        let is_played = self
287            .playlist_played
288            .get(playlist_index)
289            .copied()
290            .unwrap_or(false);
291
292        if let ItemSource::Playlist(i) = self.current {
293            is_current = playlist_index == i;
294            is_next = playlist_index == (i + 1);
295        }
296
297        if let Some(ItemSource::Playlist(i)) = self.next {
298            is_next = playlist_index == i;
299        }
300
301        if matches!(self.current, ItemSource::Traktor)
302            && let Some(index) = self.get_current_traktor_index()
303        {
304            is_traktor = playlist_index == index;
305        }
306
307        (is_current, is_next, is_traktor, is_played)
308    }
309}