danceinterpreter_rs/dataloading/dataprovider/
song_data_provider.rs1use 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}