diff --git a/server/subsonic/helpers.go b/server/subsonic/helpers.go index f193e8170..13833f96e 100644 --- a/server/subsonic/helpers.go +++ b/server/subsonic/helpers.go @@ -628,6 +628,21 @@ func buildLyricCues(cues []model.Cue, lineEnd *int64) []responses.LyricCue { return out } +// mainKindLyric returns the main-kind lyric to surface through the plain-text +// legacy getLyrics endpoint, which has no notion of translation/pronunciation +// tracks. It falls back to the first entry so untyped lyrics still resolve. +func mainKindLyric(lyricsList model.LyricList) (model.Lyrics, bool) { + if len(lyricsList) == 0 { + return model.Lyrics{}, false + } + for _, l := range lyricsList { + if model.LyricKindOrMain(l.Kind) == model.LyricKindMain { + return l, true + } + } + return lyricsList[0], true +} + func buildLyricsList(mf *model.MediaFile, lyricsList model.LyricList, enhanced bool) *responses.LyricsList { var filtered model.LyricList if enhanced { diff --git a/server/subsonic/media_retrieval.go b/server/subsonic/media_retrieval.go index b807d17ca..3b029e672 100644 --- a/server/subsonic/media_retrieval.go +++ b/server/subsonic/media_retrieval.go @@ -119,7 +119,8 @@ func (api *Router) GetLyrics(r *http.Request) (*responses.Subsonic, error) { return nil, err } - if len(structuredLyrics) == 0 { + mainLyric, ok := mainKindLyric(structuredLyrics) + if !ok { return response, nil } @@ -127,7 +128,7 @@ func (api *Router) GetLyrics(r *http.Request) (*responses.Subsonic, error) { lyricsResponse.Title = title var lyricsText strings.Builder - for _, line := range structuredLyrics[0].Line { + for _, line := range mainLyric.Line { lyricsText.WriteString(line.Value + "\n") } lyricsResponse.Value = lyricsText.String() diff --git a/server/subsonic/media_retrieval_test.go b/server/subsonic/media_retrieval_test.go index 68c9cf1e6..c7db51da6 100644 --- a/server/subsonic/media_retrieval_test.go +++ b/server/subsonic/media_retrieval_test.go @@ -149,6 +149,26 @@ var _ = Describe("MediaRetrievalController", func() { Expect(response.Lyrics.Title).To(Equal("Never Gonna Give You Up")) Expect(response.Lyrics.Value).To(Equal("We're no strangers to love\nYou know the rules and so do I\n")) }) + It("should surface the main-kind track when translation tracks are present", func() { + r := newGetRequest("artist=Rick+Astley", "title=Never+Gonna+Give+You+Up") + start := int64(0) + lyricsJSON, err := json.Marshal(model.LyricList{ + {Kind: model.LyricKindTranslation, Lang: "por", Line: []model.Line{{Start: &start, Value: "Nunca vou te decepcionar"}}}, + {Kind: model.LyricKindMain, Lang: "eng", Line: []model.Line{{Start: &start, Value: "Never gonna let you down"}}}, + }) + Expect(err).ToNot(HaveOccurred()) + mockRepo.SetData(model.MediaFiles{ + { + ID: "1", + Artist: "Rick Astley", + Title: "Never Gonna Give You Up", + Lyrics: string(lyricsJSON), + }, + }) + response, err := router.GetLyrics(r) + Expect(err).ToNot(HaveOccurred()) + Expect(response.Lyrics.Value).To(Equal("Never gonna let you down\n")) + }) It("should return empty subsonic response if the record corresponding to the given artist & title is not found", func() { r := newGetRequest("artist=Dheeraj", "title=Rinkiya+Ke+Papa") mockRepo.SetData(model.MediaFiles{})