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