From 81e6189ebe2130cd7c6e30e67086eca8fac03a33 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Fri, 16 Oct 2026 09:08:36 +0000 Subject: [PATCH] sync: keep every replayGain element's fields A second element for the same song cleared whatever the first one set, because each field was assigned unconditionally and an absent attribute parses to null. No server is known to split the object across elements, but the merge costs nothing and the alternative loses fields silently. Also covers peaks arriving without gains, which the existing cases did not. --- .../data/source/subsonic/SubsonicXml.kt | 8 ++-- .../data/source/subsonic/SubsonicXmlTest.kt | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt b/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt index ede024ca..eaa31944 100644 --- a/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt +++ b/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt @@ -210,10 +210,10 @@ internal class SongDraft( } fun addReplayGain(attrs: Attributes) { - trackGain = attrs.floatAttr("trackGain") - albumGain = attrs.floatAttr("albumGain") - trackPeak = attrs.floatAttr("trackPeak") - albumPeak = attrs.floatAttr("albumPeak") + attrs.floatAttr("trackGain")?.let { trackGain = it } + attrs.floatAttr("albumGain")?.let { albumGain = it } + attrs.floatAttr("trackPeak")?.let { trackPeak = it } + attrs.floatAttr("albumPeak")?.let { albumPeak = it } } fun toSong(): Song = diff --git a/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt b/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt index db26724b..a33750e2 100644 --- a/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt +++ b/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt @@ -231,6 +231,47 @@ class SubsonicXmlTest { assertEquals(null, songs[1].albumPeak) } + @Test + fun mapsReplayGainPeaksWithoutGains() { + val songs = + songs( + """ + + + + + + + + """.trimIndent(), + ) + + assertEquals(null, songs.single().trackGain) + assertEquals(null, songs.single().albumGain) + assertEquals(0.98f, songs.single().trackPeak) + assertEquals(0.99f, songs.single().albumPeak) + } + + @Test + fun keepsTheFieldsOfEveryReplayGainElement() { + val songs = + songs( + """ + + + + + + + + + """.trimIndent(), + ) + + assertEquals(-3.2f, songs.single().trackGain) + assertEquals(0.98f, songs.single().trackPeak) + } + @Test fun ignoresNonFiniteReplayGainValues() { val songs =