An album's genres lead with a different track than upstream's #46

Closed
opened 2026-08-03 21:47:19 +02:00 by Claude · 1 comment
Collaborator

One album's genres are in a different order from upstream's, though every track
in it agrees with upstream exactly.

Enigma/Seven Lives Many Faces (2008): upstream's album row starts
Ambient|…|New Age|…, this server's starts New Age|…. Same genres, different
first track.

An album takes its genres from its tracks, in the order the tracks are folded
in. The album spans sub-folders whose tracks carry different genre lists, so
which track is folded first decides which genres lead. That is a question about
the order a folder's children are walked and summarised
(crates/jellyfin-app/src/scan/summary.rs), not about reading tags.

Measured after #44: 1 row of 329 albums. It is the last genre difference in the
music library — tracks are at 0.

One album's genres are in a different order from upstream's, though every track in it agrees with upstream exactly. `Enigma/Seven Lives Many Faces (2008)`: upstream's album row starts `Ambient|…|New Age|…`, this server's starts `New Age|…`. Same genres, different first track. An album takes its genres from its tracks, in the order the tracks are folded in. The album spans sub-folders whose tracks carry different genre lists, so which track is folded first decides which genres lead. That is a question about the order a folder's children are walked and summarised (`crates/jellyfin-app/src/scan/summary.rs`), not about reading tags. Measured after #44: 1 row of 329 albums. It is the last genre difference in the music library — tracks are at 0.
Author
Collaborator

An album folds its tracks in the order its folder lists them, and that list is
read once — before any tag is read.

The rule, from upstream:

  • AlbumMetadataService.GetChildrenForMetadataUpdates takes
    GetRecursiveChildren(i => i is Audio), and UpdateGenres
    (MetadataService.cs:547) is SelectMany(i => i.Genres).Distinct(...) — first
    appearance wins, so the child order is the answer.
  • Folder.AddChildrenToList walks depth-first, a folder's contents standing
    where the folder does.
  • Folder.Children is materialised once (_children ??= LoadChildren()) and the
    query carries no OrderBy, so ApplyOrder falls through to SortName.
  • That list is fixed before the tracks are refreshed. At resolve time a
    track's name is its file stem (ResolverHelper.cs:96) and
    Audio.CreateSortName is disc + track + name with both numbers still null.

So a track is placed by its file stem exactly as written, and a folder by the
folded form of its directory name. For Seven Lives Many Faces, Encounters
sorts before cd 02 because a track keeps its case and a folder does not — which
is why the ten-genre root tracks lead and New Age does not.

before after
album rows differing on Genres 1 0
track rows differing on Genres 0 0

All 329 albums now agree with upstream.

Worth recording: the first implementation used the stored SortName, which
is the post-tag spelling. It fixed this album and broke two others — 2 differing
where we started with 1. It was caught only by rescanning the whole library
rather than the one album in the issue. Of the orderings tried against all 329,
the pre-tag rule is the only one that reproduces every row: stored sort name
missed 2, path order 1, readdir order 1, insertion order 4.

Not touched: 119 tracks still differ from upstream on SortName itself. The
fold order no longer reads that column, so the two are independent.

An album folds its tracks in the order its folder lists them, and that list is read once — before any tag is read. The rule, from upstream: - `AlbumMetadataService.GetChildrenForMetadataUpdates` takes `GetRecursiveChildren(i => i is Audio)`, and `UpdateGenres` (`MetadataService.cs:547`) is `SelectMany(i => i.Genres).Distinct(...)` — first appearance wins, so the child order *is* the answer. - `Folder.AddChildrenToList` walks depth-first, a folder's contents standing where the folder does. - `Folder.Children` is materialised once (`_children ??= LoadChildren()`) and the query carries no `OrderBy`, so `ApplyOrder` falls through to `SortName`. - That list is fixed **before** the tracks are refreshed. At resolve time a track's name is its file stem (`ResolverHelper.cs:96`) and `Audio.CreateSortName` is disc + track + name with both numbers still null. So a track is placed by its file stem exactly as written, and a folder by the folded form of its directory name. For `Seven Lives Many Faces`, `Encounters` sorts before `cd 02` because a track keeps its case and a folder does not — which is why the ten-genre root tracks lead and `New Age` does not. | | before | after | |---|---|---| | album rows differing on `Genres` | 1 | **0** | | track rows differing on `Genres` | 0 | 0 | All 329 albums now agree with upstream. Worth recording: the first implementation used the **stored** `SortName`, which is the post-tag spelling. It fixed this album and broke two others — 2 differing where we started with 1. It was caught only by rescanning the whole library rather than the one album in the issue. Of the orderings tried against all 329, the pre-tag rule is the only one that reproduces every row: stored sort name missed 2, path order 1, readdir order 1, insertion order 4. Not touched: 119 tracks still differ from upstream on `SortName` itself. The fold order no longer reads that column, so the two are independent.
Sign in to join this conversation.
No description provided.