diff options
| author | salmon <salmonik@tuta.io> | 2026-08-12 02:17:02 +0200 |
|---|---|---|
| committer | salmon <salmonik@tuta.io> | 2026-08-12 02:17:02 +0200 |
| commit | 3c054ed1ec22b1cf9f1dea5d0a2403e6407fbdfa (patch) | |
| tree | 0bed861fa5f903a3644cda2e7c3293690fbf7bbe /src/queue.rs | |
| parent | rc service: create state dir and log before daemon(8) starts (diff) | |
| download | rsplayer-3c054ed1ec22b1cf9f1dea5d0a2403e6407fbdfa.tar.gz rsplayer-3c054ed1ec22b1cf9f1dea5d0a2403e6407fbdfa.zip | |
queue logic fixes
Diffstat (limited to '')
| -rw-r--r-- | src/queue.rs | 53 |
1 files changed, 24 insertions, 29 deletions
diff --git a/src/queue.rs b/src/queue.rs index 1f2f0fc..c3f8dbe 100644 --- a/src/queue.rs +++ b/src/queue.rs | |||
| @@ -202,7 +202,6 @@ pub struct Queue { | |||
| 202 | position: usize, | 202 | position: usize, |
| 203 | shuffle: ShuffleMode, | 203 | shuffle: ShuffleMode, |
| 204 | shuffled_indices: Vec<usize>, | 204 | shuffled_indices: Vec<usize>, |
| 205 | original_tracks: Vec<Track>, | ||
| 206 | } | 205 | } |
| 207 | 206 | ||
| 208 | impl Default for Queue { | 207 | impl Default for Queue { |
| @@ -218,7 +217,6 @@ impl Queue { | |||
| 218 | position: 0, | 217 | position: 0, |
| 219 | shuffle: ShuffleMode::None, | 218 | shuffle: ShuffleMode::None, |
| 220 | shuffled_indices: Vec::new(), | 219 | shuffled_indices: Vec::new(), |
| 221 | original_tracks: Vec::new(), | ||
| 222 | } | 220 | } |
| 223 | } | 221 | } |
| 224 | 222 | ||
| @@ -248,62 +246,59 @@ impl Queue { | |||
| 248 | } | 246 | } |
| 249 | 247 | ||
| 250 | pub fn set_shuffle(&mut self, mode: ShuffleMode) { | 248 | pub fn set_shuffle(&mut self, mode: ShuffleMode) { |
| 251 | match mode { | 249 | self.shuffle = mode; |
| 250 | match self.shuffle { | ||
| 252 | ShuffleMode::None => { | 251 | ShuffleMode::None => { |
| 253 | self.shuffle = ShuffleMode::None; | ||
| 254 | self.restore_from_original(); | 252 | self.restore_from_original(); |
| 255 | } | 253 | } |
| 256 | ShuffleMode::All => { | 254 | ShuffleMode::All => { |
| 257 | self.original_tracks = self.tracks.clone(); | ||
| 258 | self.shuffle = ShuffleMode::All; | ||
| 259 | self.update_shuffle_indices(); | 255 | self.update_shuffle_indices(); |
| 260 | } | 256 | } |
| 261 | ShuffleMode::Album => { | 257 | ShuffleMode::Album => { |
| 262 | self.original_tracks = self.tracks.clone(); | ||
| 263 | self.shuffle = ShuffleMode::Album; | ||
| 264 | self.update_shuffle_indices_album(); | 258 | self.update_shuffle_indices_album(); |
| 265 | } | 259 | } |
| 266 | ShuffleMode::Albums => { | 260 | ShuffleMode::Albums => { |
| 267 | self.original_tracks = self.tracks.clone(); | ||
| 268 | self.shuffle = ShuffleMode::Albums; | ||
| 269 | self.update_shuffle_indices_albums(); | 261 | self.update_shuffle_indices_albums(); |
| 270 | } | 262 | } |
| 271 | } | 263 | } |
| 272 | } | 264 | } |
| 273 | 265 | ||
| 274 | fn restore_from_original(&mut self) { | 266 | fn restore_from_original(&mut self) { |
| 275 | if self.original_tracks.is_empty() { | 267 | // Restore linear (unshuffled) order. `tracks` is never reordered by |
| 268 | // shuffle — only `shuffled_indices` is a permutation — so the live | ||
| 269 | // list already carries the original insertion order. Keep the played | ||
| 270 | // segment (positions 0..=current in shuffled order) in the order it | ||
| 271 | // was played, then append the unplayed entries in original order. | ||
| 272 | // Entries are tracked by identity, so duplicate paths are preserved | ||
| 273 | // and entries added during shuffle survive. | ||
| 274 | if self.tracks.is_empty() { | ||
| 275 | self.position = 0; | ||
| 276 | self.shuffled_indices.clear(); | 276 | self.shuffled_indices.clear(); |
| 277 | return; | 277 | return; |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | let current_pos = self.position; | 280 | let current_pos = self.position.min(self.tracks.len().saturating_sub(1)); |
| 281 | 281 | ||
| 282 | // Find which tracks have been played (positions 0..=current_pos in shuffled order) | 282 | // Played entries, in played order (positions 0..=current_pos in shuffled order). |
| 283 | let mut played_track_paths: Vec<std::path::PathBuf> = Vec::new(); | 283 | let mut played: Vec<Track> = Vec::new(); |
| 284 | let mut played_idx: Vec<usize> = Vec::new(); | ||
| 284 | for i in 0..=current_pos { | 285 | for i in 0..=current_pos { |
| 285 | if let Some(&idx) = self.shuffled_indices.get(i) | 286 | if let Some(&idx) = self.shuffled_indices.get(i) { |
| 286 | && let Some(track) = self.tracks.get(idx) | 287 | if let Some(track) = self.tracks.get(idx) { |
| 287 | { | 288 | played.push(track.clone()); |
| 288 | played_track_paths.push(track.path.clone()); | 289 | played_idx.push(idx); |
| 290 | } | ||
| 289 | } | 291 | } |
| 290 | } | 292 | } |
| 291 | 293 | ||
| 292 | // Keep the played tracks in their current order | 294 | // Unplayed entries keep their original (insertion) order. |
| 293 | let mut new_tracks: Vec<Track> = Vec::new(); | 295 | let mut new_tracks = played; |
| 294 | for path in &played_track_paths { | 296 | for (idx, track) in self.tracks.iter().enumerate() { |
| 295 | if let Some(track) = self.tracks.iter().find(|t| &t.path == path) { | 297 | if !played_idx.contains(&idx) { |
| 296 | new_tracks.push(track.clone()); | 298 | new_tracks.push(track.clone()); |
| 297 | } | 299 | } |
| 298 | } | 300 | } |
| 299 | 301 | ||
| 300 | // Add remaining tracks from original in original order | ||
| 301 | for orig_track in &self.original_tracks { | ||
| 302 | let is_played = played_track_paths.iter().any(|p| p == &orig_track.path); | ||
| 303 | if !is_played { | ||
| 304 | new_tracks.push(orig_track.clone()); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | self.tracks = new_tracks; | 302 | self.tracks = new_tracks; |
| 308 | self.position = current_pos; | 303 | self.position = current_pos; |
| 309 | self.shuffled_indices.clear(); | 304 | self.shuffled_indices.clear(); |
