fix(library): extract track/disc number from file tags during backfill import

insert_qobuz_cached_track_direct was hardcoding track_number to 0,
causing all imported tracks to show wrong numbers. Now accepts
track_number and disc_number params, and both callers (backfill
downloads and offline cache sync) extract metadata from the audio
file via MetadataExtractor before inserting.

Also fix LocalLibraryView to use || instead of ?? for track_number
fallback, so 0 correctly falls back to index-based numbering.

Closes #147
This commit is contained in:
vicrodh committed 2026-03-06 11:08:32 -06:00
1 parent 36d5ff65b7
commit 786ce883ac
4 files changed
+30 -5

No files matched your search

+4 -2
View File
@@ -3348,6 +3348,8 @@ impl LibraryDatabase {
file_path: &str, file_path: &str,
bit_depth: Option<u32>, bit_depth: Option<u32>,
sample_rate: Option<f64>, sample_rate: Option<f64>,
track_number: Option<u32>,
disc_number: Option<u32>,
) -> Result<(), LibraryError> { ) -> Result<(), LibraryError> {
use std::time::SystemTime; use std::time::SystemTime;
@@ -3378,8 +3380,8 @@ impl LibraryDatabase {
artist, artist,
album.unwrap_or("Unknown Album"), album.unwrap_or("Unknown Album"),
artist, // Use artist as album_artist for proper grouping artist, // Use artist as album_artist for proper grouping
0, // track_number - will be updated if metadata is available track_number.map(|v| v as i64),
None::<u32>, // disc_number disc_number.map(|v| v as i64),
None::<u32>, // year None::<u32>, // year
duration_secs as i64, duration_secs as i64,
"flac", // Default format for downloads "flac", // Default format for downloads
+12 -1
View File
@@ -2620,7 +2620,16 @@ pub async fn library_backfill_downloads(
continue; continue;
} }
// Track doesn't exist - insert as new // Track doesn't exist - extract track/disc number from file tags
let (track_num, disc_num) = match MetadataExtractor::extract(std::path::Path::new(&file_path)) {
Ok(meta) => (meta.track_number, meta.disc_number),
Err(e) => {
log::warn!("Could not extract metadata from {}: {}", file_path, e);
(None, None)
}
};
// Insert as new
match library_db.insert_qobuz_cached_track_direct( match library_db.insert_qobuz_cached_track_direct(
track_id, track_id,
&title, &title,
@@ -2630,6 +2639,8 @@ pub async fn library_backfill_downloads(
&file_path, &file_path,
bit_depth, bit_depth,
sample_rate, sample_rate,
track_num,
disc_num,
) { ) {
Ok(_) => report.added_tracks += 1, Ok(_) => report.added_tracks += 1,
Err(e) => { Err(e) => {
+13 -1
View File
@@ -11,6 +11,7 @@ use crate::offline_cache::metadata::{
embed_artwork, fetch_complete_metadata, organize_cached_file, save_album_artwork, embed_artwork, fetch_complete_metadata, organize_cached_file, save_album_artwork,
write_flac_tags, write_flac_tags,
}; };
use crate::library::MetadataExtractor;
use crate::offline_cache::OfflineCacheState; use crate::offline_cache::OfflineCacheState;
/// Post-process a cached track: fetch metadata, tag FLAC, embed artwork, organize files /// Post-process a cached track: fetch metadata, tag FLAC, embed artwork, organize files
@@ -876,7 +877,16 @@ pub async fn sync_offline_cache_to_library(
already_present += 1; already_present += 1;
} }
Ok(false) => { Ok(false) => {
// Insert into library with basic metadata // Extract track/disc number from file tags
let (track_num, disc_num) = match MetadataExtractor::extract(std::path::Path::new(&track.file_path)) {
Ok(meta) => (meta.track_number, meta.disc_number),
Err(e) => {
log::warn!("Could not extract metadata from {}: {}", track.file_path, e);
(None, None)
}
};
// Insert into library with metadata from file tags
match library_db.insert_qobuz_cached_track_direct( match library_db.insert_qobuz_cached_track_direct(
track.track_id, track.track_id,
&track.title, &track.title,
@@ -886,6 +896,8 @@ pub async fn sync_offline_cache_to_library(
&track.file_path, &track.file_path,
track.bit_depth, track.bit_depth,
track.sample_rate, track.sample_rate,
track_num,
disc_num,
) { ) {
Ok(_) => { Ok(_) => {
log::info!( log::info!(
@@ -3250,7 +3250,7 @@
{/if} {/if}
{#each section.tracks as track, index (track.id)} {#each section.tracks as track, index (track.id)}
<TrackRow <TrackRow
number={track.track_number ?? index + 1} number={track.track_number || index + 1}
title={track.title} title={track.title}
artist={track.artist !== selectedAlbum?.artist ? track.artist : undefined} artist={track.artist !== selectedAlbum?.artist ? track.artist : undefined}
duration={formatDuration(track.duration_secs)} duration={formatDuration(track.duration_secs)}