fix(library): read "DSD" back out of the database as DSD, not Unknown
`LibraryDatabase::parse_format` is the inverse of `AudioFormat`'s Display,
which is what the scanner stores. It had no arm for "DSD", so every DSD row
came back out of the DB as `Unknown`: the album header printed "UNKNOWN" as
its format, the quality badge said CD (depth 1 IS a known depth below 24) and
the detail line read "1-bit / 2822.4 kHz". The now-playing bar was right all
along because it reads the decoder, not the row — which is exactly the clue
that separated the two data sources.
A fold to `Unknown` is a VALID answer, so nothing failed: not the build, not
`cargo check` (it cannot see the match at all), not a single test.
Three sites had the same hole and all three are fixed:
- `database.rs`, the one that bit;
- `local_plex.rs`, same fold for a Plex server serving DSD;
- `media_servers_qt.rs`, worse than the others — its fallback is `Flac`, so
a .dsf from Jellyfin or Navidrome was not losing its format, it was being
mislabelled as lossless PCM.
The guard is a round-trip over EVERY variant rather than a "DSD parses" test:
adding a variant without an arm now fails here instead of shipping the same
silent loss again. Verified against the real rows: format is stored as "DSD",
so this is a READ-side fix and no rescan is needed.
cc
This commit is contained in:
3 files changed
+80
-1
No files matched your search
@@ -303,6 +303,11 @@ pub fn thumb_url(path: &str, size: Option<u32>) -> String {
|
||||
// Cache reads, mapped into the local-library shapes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Plex reports a codec/container word. The DSD arm is not decoration: the
|
||||
/// identical omission in `LibraryDatabase::parse_format` is what made every
|
||||
/// local DSD track read back as `Unknown`, print "UNKNOWN" as its format and
|
||||
/// wear the CD badge. A Plex server serving DSD hits the same fold, and a fold
|
||||
/// to `Unknown` is a VALID answer — which is why no test ever sees it.
|
||||
fn parse_audio_format(s: &str) -> qbz_library::AudioFormat {
|
||||
use qbz_library::AudioFormat;
|
||||
match s.to_ascii_lowercase().as_str() {
|
||||
@@ -312,6 +317,7 @@ fn parse_audio_format(s: &str) -> qbz_library::AudioFormat {
|
||||
"aiff" | "aif" => AudioFormat::Aiff,
|
||||
"ape" => AudioFormat::Ape,
|
||||
"mp3" => AudioFormat::Mp3,
|
||||
"dsd" | "dsf" | "dff" => AudioFormat::Dsd,
|
||||
_ => AudioFormat::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +369,15 @@ fn parse_audio_format(container: &str, codec: Option<&str>) -> qbz_library::Audi
|
||||
use qbz_library::AudioFormat as F;
|
||||
let probe = |s: &str| -> Option<F> {
|
||||
let s = s.to_ascii_lowercase();
|
||||
if s.contains("flac") {
|
||||
// DSD first, and it matters MORE here than in the sibling parsers:
|
||||
// this one falls back to `Flac`, not `Unknown`, so an unrecognised DSD
|
||||
// track from Jellyfin/Navidrome does not merely lose its format — it
|
||||
// is actively mislabelled lossless-PCM, with a "24-bit / …" badge it
|
||||
// never had. Jellyfin reports `Container: "dsf"`, Subsonic a `suffix`
|
||||
// of `dsf`/`dff` and a MIME of `audio/x-dsf`.
|
||||
if s.contains("dsd") || s.contains("dsf") || s.contains("dff") {
|
||||
Some(F::Dsd)
|
||||
} else if s.contains("flac") {
|
||||
Some(F::Flac)
|
||||
} else if s.contains("mp3") || s.contains("mpeg") {
|
||||
Some(F::Mp3)
|
||||
|
||||
Reference in new issue
Block a user