mirror of
https://github.com/navidrome/navidrome.git
synced 2025-12-23 23:18:05 -05:00
fix: Allow nullable ReplayGain and support 0.0 (#4239)
* fix(ui,scanner,subsonic): Allow nullable replaygain and support 0.0 Resolves #4236. Makes the replaygain columns (track/album gain/peak) nullable. Converts the type to a pointer, allowing for 0.0 (a valid value) to be returned from Subsonic. Updates tests for this behavior. * small refactor Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org> Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -91,7 +92,7 @@ var _ = Describe("sendResponse", func() {
|
||||
It("should return a fail response", func() {
|
||||
payload.Song = &responses.Child{OpenSubsonicChild: &responses.OpenSubsonicChild{}}
|
||||
// An +Inf value will cause an error when marshalling to JSON
|
||||
payload.Song.ReplayGain = responses.ReplayGain{TrackGain: math.Inf(1)}
|
||||
payload.Song.ReplayGain = responses.ReplayGain{TrackGain: gg.P(math.Inf(1))}
|
||||
q := r.URL.Query()
|
||||
q.Add("f", "json")
|
||||
r.URL.RawQuery = q.Encode()
|
||||
|
||||
@@ -166,6 +166,52 @@
|
||||
],
|
||||
"displayComposer": "composer 1 \u0026 composer 2",
|
||||
"explicitStatus": "clean"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"isDir": true,
|
||||
"title": "title",
|
||||
"album": "album",
|
||||
"artist": "artist",
|
||||
"track": 1,
|
||||
"year": 1985,
|
||||
"genre": "Rock",
|
||||
"coverArt": "1",
|
||||
"size": 8421341,
|
||||
"contentType": "audio/flac",
|
||||
"suffix": "flac",
|
||||
"starred": "2016-03-02T20:30:00Z",
|
||||
"transcodedContentType": "audio/mpeg",
|
||||
"transcodedSuffix": "mp3",
|
||||
"duration": 146,
|
||||
"bitRate": 320,
|
||||
"isVideo": false,
|
||||
"bpm": 0,
|
||||
"comment": "",
|
||||
"sortName": "",
|
||||
"mediaType": "",
|
||||
"musicBrainzId": "",
|
||||
"isrc": [],
|
||||
"genres": [],
|
||||
"replayGain": {
|
||||
"trackGain": 0,
|
||||
"albumGain": 0,
|
||||
"trackPeak": 0,
|
||||
"albumPeak": 0,
|
||||
"baseGain": 0,
|
||||
"fallbackGain": 0
|
||||
},
|
||||
"channelCount": 0,
|
||||
"samplingRate": 0,
|
||||
"bitDepth": 0,
|
||||
"moods": [],
|
||||
"artists": [],
|
||||
"displayArtist": "",
|
||||
"albumArtists": [],
|
||||
"displayAlbumArtist": "",
|
||||
"contributors": [],
|
||||
"displayComposer": "",
|
||||
"explicitStatus": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
<artist id="2" name="artist2"></artist>
|
||||
</contributors>
|
||||
</song>
|
||||
<song id="2" isDir="true" title="title" album="album" artist="artist" track="1" year="1985" genre="Rock" coverArt="1" size="8421341" contentType="audio/flac" suffix="flac" starred="2016-03-02T20:30:00Z" transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="146" bitRate="320" isVideo="false">
|
||||
<replayGain trackGain="0" albumGain="0" trackPeak="0" albumPeak="0" baseGain="0" fallbackGain="0"></replayGain>
|
||||
</song>
|
||||
</album>
|
||||
</subsonic-response>
|
||||
|
||||
@@ -112,6 +112,37 @@
|
||||
],
|
||||
"displayComposer": "composer 1 \u0026 composer 2",
|
||||
"explicitStatus": "clean"
|
||||
},
|
||||
{
|
||||
"id": "",
|
||||
"isDir": false,
|
||||
"isVideo": false,
|
||||
"bpm": 0,
|
||||
"comment": "",
|
||||
"sortName": "",
|
||||
"mediaType": "",
|
||||
"musicBrainzId": "",
|
||||
"isrc": [],
|
||||
"genres": [],
|
||||
"replayGain": {
|
||||
"trackGain": 0,
|
||||
"albumGain": 0,
|
||||
"trackPeak": 0,
|
||||
"albumPeak": 0,
|
||||
"baseGain": 0,
|
||||
"fallbackGain": 0
|
||||
},
|
||||
"channelCount": 0,
|
||||
"samplingRate": 0,
|
||||
"bitDepth": 0,
|
||||
"moods": [],
|
||||
"artists": [],
|
||||
"displayArtist": "",
|
||||
"albumArtists": [],
|
||||
"displayAlbumArtist": "",
|
||||
"contributors": [],
|
||||
"displayComposer": "",
|
||||
"explicitStatus": ""
|
||||
}
|
||||
],
|
||||
"id": "1",
|
||||
|
||||
@@ -25,5 +25,8 @@
|
||||
<artist id="4" name="composer2"></artist>
|
||||
</contributors>
|
||||
</child>
|
||||
<child id="" isDir="false" isVideo="false">
|
||||
<replayGain trackGain="0" albumGain="0" trackPeak="0" albumPeak="0" baseGain="0" fallbackGain="0"></replayGain>
|
||||
</child>
|
||||
</directory>
|
||||
</subsonic-response>
|
||||
|
||||
@@ -546,16 +546,16 @@ type ItemGenre struct {
|
||||
}
|
||||
|
||||
type ReplayGain struct {
|
||||
TrackGain float64 `xml:"trackGain,omitempty,attr" json:"trackGain,omitempty"`
|
||||
AlbumGain float64 `xml:"albumGain,omitempty,attr" json:"albumGain,omitempty"`
|
||||
TrackPeak float64 `xml:"trackPeak,omitempty,attr" json:"trackPeak,omitempty"`
|
||||
AlbumPeak float64 `xml:"albumPeak,omitempty,attr" json:"albumPeak,omitempty"`
|
||||
BaseGain float64 `xml:"baseGain,omitempty,attr" json:"baseGain,omitempty"`
|
||||
FallbackGain float64 `xml:"fallbackGain,omitempty,attr" json:"fallbackGain,omitempty"`
|
||||
TrackGain *float64 `xml:"trackGain,omitempty,attr" json:"trackGain,omitempty"`
|
||||
AlbumGain *float64 `xml:"albumGain,omitempty,attr" json:"albumGain,omitempty"`
|
||||
TrackPeak *float64 `xml:"trackPeak,omitempty,attr" json:"trackPeak,omitempty"`
|
||||
AlbumPeak *float64 `xml:"albumPeak,omitempty,attr" json:"albumPeak,omitempty"`
|
||||
BaseGain *float64 `xml:"baseGain,omitempty,attr" json:"baseGain,omitempty"`
|
||||
FallbackGain *float64 `xml:"fallbackGain,omitempty,attr" json:"fallbackGain,omitempty"`
|
||||
}
|
||||
|
||||
func (r ReplayGain) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||
if r.TrackGain == 0 && r.AlbumGain == 0 && r.TrackPeak == 0 && r.AlbumPeak == 0 && r.BaseGain == 0 && r.FallbackGain == 0 {
|
||||
if r.TrackGain == nil && r.AlbumGain == nil && r.TrackPeak == nil && r.AlbumPeak == nil && r.BaseGain == nil && r.FallbackGain == nil {
|
||||
return nil
|
||||
}
|
||||
type replayGain ReplayGain
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
. "github.com/navidrome/navidrome/server/subsonic/responses"
|
||||
"github.com/navidrome/navidrome/utils/gg"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -213,7 +214,7 @@ var _ = Describe("Responses", func() {
|
||||
Context("with data", func() {
|
||||
BeforeEach(func() {
|
||||
response.Directory = &Directory{Id: "1", Name: "N"}
|
||||
child := make([]Child, 1)
|
||||
child := make([]Child, 2)
|
||||
t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC)
|
||||
child[0] = Child{
|
||||
Id: "1", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1,
|
||||
@@ -227,7 +228,7 @@ var _ = Describe("Responses", func() {
|
||||
Isrc: []string{"ISRC-1", "ISRC-2"},
|
||||
BPM: 127, ChannelCount: 2, SamplingRate: 44100, BitDepth: 16,
|
||||
Moods: []string{"happy", "sad"},
|
||||
ReplayGain: ReplayGain{TrackGain: 1, AlbumGain: 2, TrackPeak: 3, AlbumPeak: 4, BaseGain: 5, FallbackGain: 6},
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(1.0), AlbumGain: gg.P(2.0), TrackPeak: gg.P(3.0), AlbumPeak: gg.P(4.0), BaseGain: gg.P(5.0), FallbackGain: gg.P(6.0)},
|
||||
DisplayArtist: "artist 1 & artist 2",
|
||||
Artists: []ArtistID3Ref{
|
||||
{Id: "1", Name: "artist1"},
|
||||
@@ -247,6 +248,9 @@ var _ = Describe("Responses", func() {
|
||||
},
|
||||
ExplicitStatus: "clean",
|
||||
}
|
||||
child[1].OpenSubsonicChild = &OpenSubsonicChild{
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(0.0), AlbumGain: gg.P(0.0), TrackPeak: gg.P(0.0), AlbumPeak: gg.P(0.0), BaseGain: gg.P(0.0), FallbackGain: gg.P(0.0)},
|
||||
}
|
||||
response.Directory.Child = child
|
||||
})
|
||||
|
||||
@@ -309,13 +313,18 @@ var _ = Describe("Responses", func() {
|
||||
Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac",
|
||||
Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3",
|
||||
Duration: 146, BitRate: 320, Starred: &t,
|
||||
}, {
|
||||
Id: "2", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1,
|
||||
Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac",
|
||||
Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3",
|
||||
Duration: 146, BitRate: 320, Starred: &t,
|
||||
}}
|
||||
songs[0].OpenSubsonicChild = &OpenSubsonicChild{
|
||||
Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}},
|
||||
Comment: "a comment", MediaType: MediaTypeSong, MusicBrainzId: "4321", SortName: "sorted song",
|
||||
Isrc: []string{"ISRC-1"},
|
||||
Moods: []string{"happy", "sad"},
|
||||
ReplayGain: ReplayGain{TrackGain: 1, AlbumGain: 2, TrackPeak: 3, AlbumPeak: 4, BaseGain: 5, FallbackGain: 6},
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(1.0), AlbumGain: gg.P(2.0), TrackPeak: gg.P(3.0), AlbumPeak: gg.P(4.0), BaseGain: gg.P(5.0), FallbackGain: gg.P(6.0)},
|
||||
BPM: 127, ChannelCount: 2, SamplingRate: 44100, BitDepth: 16,
|
||||
DisplayArtist: "artist1 & artist2",
|
||||
Artists: []ArtistID3Ref{
|
||||
@@ -334,6 +343,9 @@ var _ = Describe("Responses", func() {
|
||||
DisplayComposer: "composer 1 & composer 2",
|
||||
ExplicitStatus: "clean",
|
||||
}
|
||||
songs[1].OpenSubsonicChild = &OpenSubsonicChild{
|
||||
ReplayGain: ReplayGain{TrackGain: gg.P(0.0), AlbumGain: gg.P(0.0), TrackPeak: gg.P(0.0), AlbumPeak: gg.P(0.0), BaseGain: gg.P(0.0), FallbackGain: gg.P(0.0)},
|
||||
}
|
||||
response.AlbumWithSongsID3.AlbumID3 = album
|
||||
response.AlbumWithSongsID3.Song = songs
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user