Skip to main content

danceinterpreter_rs/dataloading/dataprovider/
song_data_provider.rs

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