From 956e3be3808f918923aef3259ea5b28bfc055b03 Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 22 May 2026 17:57:08 +0200 Subject: Fix metadata extraction for symphonia 0.6 and add Albums shuffle mode --- src/queue.rs | 130 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 23 deletions(-) (limited to 'src/queue.rs') diff --git a/src/queue.rs b/src/queue.rs index b0acf5f..9d09fec 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -6,6 +6,7 @@ pub enum ShuffleMode { None, All, Album, + Albums, } #[derive(Debug, Default, Clone)] @@ -46,28 +47,8 @@ pub fn extract_metadata(path: &Path) -> Option { }; { - let meta = probed.metadata(); - if let Some(rev) = meta.current() { - for tag in &rev.media.tags { - match &tag.std { - Some(StandardTag::TrackTitle(value)) => { - metadata.title = Some(value.to_string()); - } - Some(StandardTag::Artist(value)) => { - metadata.artist = Some(value.to_string()); - } - Some(StandardTag::Album(value)) => { - metadata.album = Some(value.to_string()); - } - _ => {} - } - } - } - } - - if metadata.title.is_none() && metadata.artist.is_none() && metadata.album.is_none() { - let meta = probed.metadata(); - if let Some(rev) = meta.current() { + let mut meta = probed.metadata(); + if let Some(rev) = meta.skip_to_latest() { for tag in &rev.media.tags { match &tag.std { Some(StandardTag::TrackTitle(value)) => { @@ -183,6 +164,12 @@ impl Queue { self.update_shuffle_indices(); } + #[allow(dead_code)] + pub fn push_track(&mut self, track: Track) { + self.tracks.push(track); + self.update_shuffle_indices(); + } + pub fn insert_after_current(&mut self, path: PathBuf) { if self.tracks.is_empty() { self.tracks.push(Track::from_path(path)); @@ -213,6 +200,11 @@ impl Queue { self.shuffle = ShuffleMode::Album; self.update_shuffle_indices_album(); } + ShuffleMode::Albums => { + self.original_tracks = self.tracks.clone(); + self.shuffle = ShuffleMode::Albums; + self.update_shuffle_indices_albums(); + } } } @@ -268,6 +260,9 @@ impl Queue { ShuffleMode::Album => { self.update_shuffle_indices_album(); } + ShuffleMode::Albums => { + self.update_shuffle_indices_albums(); + } ShuffleMode::None => {} } } @@ -285,6 +280,62 @@ impl Queue { } } + fn update_shuffle_indices_albums(&mut self) { + let len = self.tracks.len(); + self.shuffled_indices = (0..len).collect(); + + if len <= 1 { + return; + } + + let pos = self.position.min(len.saturating_sub(1)); + if pos + 1 >= len { + return; + } + + let range_start = pos + 1; + let mut rng = rand::rng(); + + // Build album groups within the range, shuffling tracks within each group + let mut groups: Vec> = Vec::new(); + let mut current_group: Vec = Vec::new(); + let mut current_album: Option<&str> = None; + + for i in range_start..len { + let album = self.tracks.get(i).and_then(|t| t.album.as_deref()); + + if current_group.is_empty() { + current_group.push(i); + current_album = album; + } else if album != current_album { + // Shuffle tracks within this album group before adding it + if current_group.len() > 1 { + current_group.shuffle(&mut rng); + } + groups.push(std::mem::take(&mut current_group)); + current_group.push(i); + current_album = album; + } else { + current_group.push(i); + } + } + if !current_group.is_empty() { + if current_group.len() > 1 { + current_group.shuffle(&mut rng); + } + groups.push(current_group); + } + + // Shuffle the album group order + groups.shuffle(&mut rng); + + let mut new_indices: Vec = self.shuffled_indices[..=pos].to_vec(); + for group in &groups { + new_indices.extend(group); + } + self.shuffled_indices = new_indices; + } + fn shuffle_album_range(&mut self, range: std::ops::Range, rng: &mut impl rand::Rng) { if range.start >= range.end { return; @@ -327,7 +378,7 @@ impl Queue { self.shuffled_indices .get(self.position) .and_then(|&idx| self.tracks.get(idx)) - } else if self.shuffle == ShuffleMode::Album { + } else if self.shuffle == ShuffleMode::Album || self.shuffle == ShuffleMode::Albums { self.shuffled_indices .get(self.position) .and_then(|&idx| self.tracks.get(idx)) @@ -397,6 +448,39 @@ impl Queue { ShuffleMode::Album => { self.shuffle_album_range(0..self.tracks.len(), &mut rng); } + ShuffleMode::Albums => { + let mut groups: Vec> = Vec::new(); + let mut current_group: Vec = Vec::new(); + let mut current_album: Option<&str> = None; + + for i in 0..self.tracks.len() { + let album = self.tracks.get(i).and_then(|t| t.album.as_deref()); + + if current_group.is_empty() { + current_group.push(i); + current_album = album; + } else if album != current_album { + if current_group.len() > 1 { + current_group.shuffle(&mut rng); + } + groups.push(std::mem::take(&mut current_group)); + current_group.push(i); + current_album = album; + } else { + current_group.push(i); + } + } + if !current_group.is_empty() { + if current_group.len() > 1 { + current_group.shuffle(&mut rng); + } + groups.push(current_group); + } + + groups.shuffle(&mut rng); + + self.shuffled_indices = groups.concat(); + } ShuffleMode::None => {} } } -- cgit v1.2.3