feat(subsonic): add option to disable getNowPlaying

- Add Subsonic.EnableGetNowPlaying configuration, enabled by default
- Return an empty response when the endpoint is disabled
This commit is contained in:
Deluan 2026-09-14 17:33:56 -04:00
commit 847570966b
3 changed files with 28 additions and 0 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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() {