aboutsummaryrefslogtreecommitdiffstats
path: root/src/queue.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/queue.rs85
1 files changed, 83 insertions, 2 deletions
diff --git a/src/queue.rs b/src/queue.rs
index 9e8e1af..109b748 100644
--- a/src/queue.rs
+++ b/src/queue.rs
@@ -124,6 +124,7 @@ pub struct Queue {
124 position: usize, 124 position: usize,
125 shuffle: ShuffleMode, 125 shuffle: ShuffleMode,
126 shuffled_indices: Vec<usize>, 126 shuffled_indices: Vec<usize>,
127 original_tracks: Vec<Track>,
127} 128}
128 129
129impl Default for Queue { 130impl Default for Queue {
@@ -139,6 +140,7 @@ impl Queue {
139 position: 0, 140 position: 0,
140 shuffle: ShuffleMode::None, 141 shuffle: ShuffleMode::None,
141 shuffled_indices: Vec::new(), 142 shuffled_indices: Vec::new(),
143 original_tracks: Vec::new(),
142 } 144 }
143 } 145 }
144 146
@@ -162,8 +164,38 @@ impl Queue {
162 } 164 }
163 165
164 pub fn set_shuffle(&mut self, mode: ShuffleMode) { 166 pub fn set_shuffle(&mut self, mode: ShuffleMode) {
165 self.shuffle = mode; 167 match mode {
166 self.update_shuffle_indices(); 168 ShuffleMode::None => {
169 self.shuffle = ShuffleMode::None;
170 self.restore_from_original();
171 }
172 ShuffleMode::All => {
173 self.original_tracks = self.tracks.clone();
174 self.shuffle = ShuffleMode::All;
175 self.update_shuffle_indices();
176 }
177 ShuffleMode::Album => {
178 self.original_tracks = self.tracks.clone();
179 self.shuffle = ShuffleMode::Album;
180 self.update_shuffle_indices_album();
181 }
182 }
183 }
184
185 fn restore_from_original(&mut self) {
186 if self.original_tracks.is_empty() {
187 self.shuffled_indices.clear();
188 return;
189 }
190
191 let current_pos = self.position;
192 let played: Vec<Track> = self.tracks[..current_pos].to_vec();
193 let unplayed_original: Vec<Track> = self.original_tracks[current_pos..].to_vec();
194
195 self.tracks = played;
196 self.tracks.extend(unplayed_original);
197 self.position = current_pos;
198 self.shuffled_indices.clear();
167 } 199 }
168 200
169 fn update_shuffle_indices(&mut self) { 201 fn update_shuffle_indices(&mut self) {
@@ -180,6 +212,55 @@ impl Queue {
180 } 212 }
181 } 213 }
182 214
215 fn update_shuffle_indices_album(&mut self) {
216 let len = self.tracks.len();
217 self.shuffled_indices = (0..len).collect();
218
219 let mut rng = rand::rng();
220 let pos = self.position.min(len.saturating_sub(1));
221
222 if pos == 0 && len > 1 {
223 self.shuffle_album_range(0..len, &mut rng);
224 } else if pos + 1 < len {
225 self.shuffle_album_range(pos + 1..len, &mut rng);
226 }
227 }
228
229 fn shuffle_album_range(&mut self, range: std::ops::Range<usize>, rng: &mut impl rand::Rng) {
230 if range.start >= range.end {
231 return;
232 }
233
234 let mut album_ranges: Vec<(usize, usize)> = Vec::new();
235 let mut current_album: Option<&str> = None;
236 let mut range_start: Option<usize> = None;
237
238 for i in range.clone() {
239 let album = self.tracks.get(i).and_then(|t| t.album.as_deref());
240 match (current_album, range_start) {
241 (None, None) => {
242 current_album = album;
243 range_start = Some(i);
244 }
245 (Some(_), Some(start)) if album != current_album => {
246 album_ranges.push((start, i));
247 current_album = album;
248 range_start = Some(i);
249 }
250 _ => {}
251 }
252 }
253 if let Some(start) = range_start {
254 album_ranges.push((start, range.end));
255 }
256
257 for (start, end) in album_ranges {
258 if start + 1 < end {
259 self.shuffled_indices[start..end].shuffle(rng);
260 }
261 }
262 }
263
183 pub fn current(&self) -> Option<&Track> { 264 pub fn current(&self) -> Option<&Track> {
184 if self.tracks.is_empty() { 265 if self.tracks.is_empty() {
185 None 266 None