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.set_current_as_played();
193                self.current = SongDataSource::Static(index);
194            }
195            SongChange::PlaylistAbsolute(index) => {
196                self.set_current_as_played();
197                self.current = SongDataSource::Playlist(index);
198            }
199            SongChange::Previous => {
200                self.prev();
201            }
202            SongChange::Next => {
203                self.next();
204            }
205        }
206    }
207
208    pub fn handle_song_data_edit(&mut self, i: usize, edit: SongDataEdit) {
209        if let Some(song) = self.playlist_songs.get_mut(i) {
210            match edit {
211                SongDataEdit::Title(title) => {
212                    song.title = title;
213                }
214                SongDataEdit::Artist(artist) => {
215                    song.artist = artist;
216                }
217                SongDataEdit::Dance(dance) => {
218                    song.dance = dance;
219                }
220            }
221        }
222    }
223
224    pub fn process_traktor_message(&mut self, message: traktor_api::ServerMessage) {
225        self.set_current_as_played();
226        self.traktor_provider
227            .process_message(message, &self.playlist_songs);
228    }
229
230    pub fn get_current_traktor_index(&self) -> Option<usize> {
231        self.traktor_provider
232            .get_current_index(&self.playlist_songs)
233    }
234
235    pub fn take_scroll_index(&mut self) -> Option<usize> {
236        let should_scroll = self.should_scroll | self.traktor_provider.take_should_scroll();
237        self.should_scroll = false;
238
239        if !should_scroll {
240            return None;
241        }
242
243        match self.current {
244            SongDataSource::Traktor => self.get_current_traktor_index(),
245            SongDataSource::Playlist(i) => Some(i),
246            _ => None,
247        }
248    }
249}