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.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}