diff --git a/server/jellyfin/README.md b/server/jellyfin/README.md index 9710865c4..421394e46 100644 --- a/server/jellyfin/README.md +++ b/server/jellyfin/README.md @@ -199,9 +199,6 @@ make test PKG=./server/jellyfin/... Access control for artists is enforced by scoping the `Artists`/`Items?IncludeItemTypes=MusicArtist` *list* to the user's libraries, plus the persistence layer's own defense-in-depth; a client that already has an artist id from elsewhere is not re-checked against library membership. -- **Album track order.** Browsing an album's tracks (`Items?ParentId=&IncludeItemTypes=Audio`) - without an explicit `SortBy` does not guarantee track order — clients that need it should pass a - sort. Track numbers are always present on each item (`IndexNumber`). - **Playlists never match `Filters=IsFavorite`.** `GET Items?IncludeItemTypes=Playlist` (alone or mixed with other types, e.g. Finamp's favorites screen sending `IncludeItemTypes=Audio,MusicAlbum,Playlist`) is supported, but `model.Playlist` has no diff --git a/server/jellyfin/e2e/browsing_test.go b/server/jellyfin/e2e/browsing_test.go index 6a5b867c9..b8c6be2d0 100644 --- a/server/jellyfin/e2e/browsing_test.go +++ b/server/jellyfin/e2e/browsing_test.go @@ -76,15 +76,12 @@ var _ = Describe("Browsing", func() { Expect(names(q.Items)).To(ConsistOf("Abbey Road", "Help!")) }) - It("browses an album's tracks with their track numbers", func() { + It("browses an album's tracks in track order by default", func() { q := queryResult(get("/Items?IncludeItemTypes=Audio&ParentId=" + enc(albumID("Abbey Road")))) Expect(q.TotalRecordCount).To(Equal(2)) - Expect(names(q.Items)).To(ConsistOf("Come Together", "Something")) - idx := map[string]int{} - for _, it := range q.Items { - idx[it.Name] = *it.IndexNumber - } - Expect(idx).To(Equal(map[string]int{"Come Together": 1, "Something": 2})) + Expect(names(q.Items)).To(Equal([]string{"Come Together", "Something"})) + Expect(*q.Items[0].IndexNumber).To(Equal(1)) + Expect(*q.Items[1].IndexNumber).To(Equal(2)) }) }) diff --git a/server/jellyfin/items.go b/server/jellyfin/items.go index 8e5a5c0d1..3a067397e 100644 --- a/server/jellyfin/items.go +++ b/server/jellyfin/items.go @@ -185,6 +185,12 @@ func (api *Router) listSongs(ctx context.Context, opts model.QueryOptions, paren if search != "" { mfs, err = repo.Search(search, opts) } else { + // When browsing an album's tracks, default to track order (disc + track number) like + // Subsonic's GetAlbum and real Jellyfin do; an explicit SortBy from the client still wins, + // since applySort would already have set opts.Sort. + if parentId != "" && opts.Sort == "" { + opts.Sort = filter.SongsByAlbum(parentId).Sort + } mfs, err = repo.GetAll(opts) } if err != nil {