From 847570966b0f859f840ebf2496913edbdec8da19 Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 14 Sep 2026 17:33:56 -0400 Subject: [PATCH] feat(subsonic): add option to disable getNowPlaying - Add Subsonic.EnableGetNowPlaying configuration, enabled by default - Return an empty response when the endpoint is disabled --- conf/configuration.go | 2 ++ server/subsonic/album_lists.go | 8 ++++++++ .../subsonic/e2e/subsonic_album_lists_test.go | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/conf/configuration.go b/conf/configuration.go index e549e2a61..c3096af5a 100644 --- a/conf/configuration.go +++ b/conf/configuration.go @@ -190,6 +190,7 @@ type subsonicOptions struct { ArtistParticipations bool DefaultReportRealPath bool EnableAverageRating bool + EnableGetNowPlaying bool LegacyClients string MinimalClients string } @@ -1068,6 +1069,7 @@ func setViperDefaults() { viper.SetDefault("subsonic.artistparticipations", false) viper.SetDefault("subsonic.defaultreportrealpath", false) viper.SetDefault("subsonic.enableaveragerating", true) + viper.SetDefault("subsonic.enablegetnowplaying", true) viper.SetDefault("subsonic.legacyclients", "DSub") viper.SetDefault("subsonic.minimalclients", "SubMusic") viper.SetDefault("transcoding.maxconcurrent", 0) diff --git a/server/subsonic/album_lists.go b/server/subsonic/album_lists.go index ba5f88a68..5340a4e02 100644 --- a/server/subsonic/album_lists.go +++ b/server/subsonic/album_lists.go @@ -6,6 +6,7 @@ import ( "strconv" "time" + "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/core/scrobbler" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" @@ -203,6 +204,13 @@ func (api *Router) GetStarred2(r *http.Request) (*responses.Subsonic, error) { func (api *Router) GetNowPlaying(r *http.Request) (*responses.Subsonic, error) { ctx := r.Context() + // Return an empty list rather than an error, so clients degrade gracefully + if !conf.Server.Subsonic.EnableGetNowPlaying { + response := newResponse() + response.NowPlaying = &responses.NowPlaying{} + return response, nil + } + npInfo, err := api.scrobbler.GetNowPlaying(ctx) if err != nil { log.Error(r, "Error retrieving now playing list", err) diff --git a/server/subsonic/e2e/subsonic_album_lists_test.go b/server/subsonic/e2e/subsonic_album_lists_test.go index 6d32a3c88..e1ce625c9 100644 --- a/server/subsonic/e2e/subsonic_album_lists_test.go +++ b/server/subsonic/e2e/subsonic_album_lists_test.go @@ -2,6 +2,7 @@ package e2e import ( "github.com/Masterminds/squirrel" + "github.com/navidrome/navidrome/conf" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/server/subsonic/responses" . "github.com/onsi/ginkgo/v2" @@ -239,6 +240,23 @@ var _ = Describe("Album List Endpoints", func() { Expect(resp.NowPlaying).ToNot(BeNil()) Expect(resp.NowPlaying.Entry).To(BeEmpty()) }) + + It("hides active sessions when Subsonic.EnableGetNowPlaying is disabled", func() { + songs, err := ds.MediaFile(ctx).GetAll(model.QueryOptions{Max: 1, Sort: "title"}) + Expect(err).ToNot(HaveOccurred()) + Expect(songs).ToNot(BeEmpty()) + + resp := doReq("reportPlayback", "mediaId", songs[0].ID, "mediaType", "song", + "positionMs", "0", "state", "playing") + Expect(resp.Status).To(Equal(responses.StatusOK)) + + conf.Server.Subsonic.EnableGetNowPlaying = false + + resp = doReq("getNowPlaying") + + Expect(resp.Status).To(Equal(responses.StatusOK)) + Expect(resp.NowPlaying.Entry).To(BeEmpty()) + }) }) Describe("GetRandomSongs", func() {