From 4e946963e10861f5b6af66dc7790a55a1988cf9f Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 29 Jun 2026 12:22:46 +0200 Subject: [PATCH] Handle multi artist albums --- src/music/db.rs | 1 + src/music/metadata.rs | 2 ++ src/origins/local/snapshot.rs | 38 +++++++++++++++++++---------------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/music/db.rs b/src/music/db.rs index 64de4d1..e3c7a2b 100644 --- a/src/music/db.rs +++ b/src/music/db.rs @@ -167,6 +167,7 @@ pub async fn restore_music_metadata_from_db( let mut music_metadata = MusicMetadata { artist: artists_by_inode.remove(&inode).unwrap_or_default(), + album_artist: None, album: mm_row.album, track_number: mm_row.track_number, track_title: mm_row.track_title, diff --git a/src/music/metadata.rs b/src/music/metadata.rs index d5798af..0a2c169 100644 --- a/src/music/metadata.rs +++ b/src/music/metadata.rs @@ -3,6 +3,7 @@ use symphonia::core::meta::{MetadataRevision, StandardTagKey}; #[derive(Debug, Default, Clone)] pub struct MusicMetadata { pub artist: Vec, + pub album_artist: Option, pub album: String, pub track_number: i32, pub track_title: String, @@ -39,6 +40,7 @@ pub(crate) fn extract_standard_tags(revision: &MetadataRevision, out: &mut Music let value = tag.value.to_string(); match tag.std_key { Some(StandardTagKey::Artist) => out.artist.push(value), + Some(StandardTagKey::AlbumArtist) => out.album_artist = Some(value), Some(StandardTagKey::Album) => out.album = value, Some(StandardTagKey::TrackNumber) => { out.track_number = value.parse::().unwrap_or(0) diff --git a/src/origins/local/snapshot.rs b/src/origins/local/snapshot.rs index 395e427..d3b7a51 100644 --- a/src/origins/local/snapshot.rs +++ b/src/origins/local/snapshot.rs @@ -62,14 +62,15 @@ pub fn read_into_map( ) -> Result<(), io::Error> { for item in fs::read_dir(source)? { let entry = item?; - let name = entry.file_name().to_string_lossy().into_owned(); let item_path = entry.path(); + + if entry.file_type()?.is_dir() { + read_into_map(&item_path, destination, map)?; + continue; + } + + let name = entry.file_name().to_string_lossy().into_owned(); let metadata = entry.metadata()?; - let file_type = if entry.file_type()?.is_dir() { - FileType::Directory - } else { - FileType::File - }; let music_metadata = MusicMetadataParserFactory::for_path(&item_path) .and_then(|parser| parser.parse(&item_path)) .map(|mut mm| { @@ -80,12 +81,19 @@ pub fn read_into_map( }); let mut local_path = PathBuf::new(); - if music_metadata.is_some() { - let music_metadata = music_metadata.clone().unwrap(); - local_path.push(music_metadata.artist.join("-")); - local_path.push(music_metadata.album); + if let Some(ref mm) = music_metadata { + let joined; + let artist_dir = match mm.album_artist.as_deref() { + Some(a) => a, + None => { + joined = mm.artist.join("-"); + &joined + } + }; + local_path.push(artist_dir); + local_path.push(&mm.album); } - local_path.push(name.clone()); + local_path.push(&name); let inode = INodeNo(metadata.ino()); let parent_inode = ensure_virtual_dirs(&local_path, source, map); @@ -93,18 +101,14 @@ pub fn read_into_map( inode, parent_inode, name, - item_path.clone(), + item_path, local_path, - file_type, + FileType::File, metadata, music_metadata, ); map.insert(inode, local_item); - - if file_type == FileType::Directory { - read_into_map(&item_path, destination, map)?; - } } return Ok(()); }