From 6c065870b5191ef8fb46db8f226bf143753f396f Mon Sep 17 00:00:00 2001 From: Deluan Date: Tue, 28 Apr 2026 19:46:12 -0400 Subject: [PATCH] feat(smartplaylist): add ReplayGain fields to criteria system Expose the four ReplayGain database columns (rg_album_gain, rg_album_peak, rg_track_gain, rg_track_peak) as first-class numeric criteria fields for smart playlists. This allows users to filter tracks by ReplayGain values, e.g. finding tracks with album gain below a threshold. --- model/criteria/fields.go | 4 ++++ persistence/criteria_sql.go | 4 ++++ persistence/criteria_sql_test.go | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/model/criteria/fields.go b/model/criteria/fields.go index 20c0048b3..37b4cc017 100644 --- a/model/criteria/fields.go +++ b/model/criteria/fields.go @@ -72,6 +72,10 @@ var fieldMap = map[string]FieldInfo{ "mbz_recording_id": {Name: "mbz_recording_id"}, "mbz_release_track_id": {Name: "mbz_release_track_id"}, "mbz_release_group_id": {Name: "mbz_release_group_id"}, + "rgalbumgain": {Name: "rgalbumgain", Numeric: true}, + "rgalbumpeak": {Name: "rgalbumpeak", Numeric: true}, + "rgtrackgain": {Name: "rgtrackgain", Numeric: true}, + "rgtrackpeak": {Name: "rgtrackpeak", Numeric: true}, "library_id": {Name: "library_id", Numeric: true}, // Backward compatibility: albumtype is an alias for the releasetype tag. diff --git a/persistence/criteria_sql.go b/persistence/criteria_sql.go index 8fca6b2a2..123ec29eb 100644 --- a/persistence/criteria_sql.go +++ b/persistence/criteria_sql.go @@ -111,6 +111,10 @@ var smartPlaylistFields = map[string]smartPlaylistField{ "mbz_recording_id": {expr: "media_file.mbz_recording_id"}, "mbz_release_track_id": {expr: "media_file.mbz_release_track_id"}, "mbz_release_group_id": {expr: "media_file.mbz_release_group_id"}, + "rgalbumgain": {expr: "media_file.rg_album_gain"}, + "rgalbumpeak": {expr: "media_file.rg_album_peak"}, + "rgtrackgain": {expr: "media_file.rg_track_gain"}, + "rgtrackpeak": {expr: "media_file.rg_track_peak"}, "library_id": {expr: "media_file.library_id"}, "random": {order: "random()"}, "value": {expr: "value"}, diff --git a/persistence/criteria_sql_test.go b/persistence/criteria_sql_test.go index a2212c4e5..c93465735 100644 --- a/persistence/criteria_sql_test.go +++ b/persistence/criteria_sql_test.go @@ -59,6 +59,10 @@ var _ = Describe("Smart playlist criteria SQL", func() { Entry("role is", criteria.Is{"artist": "u2"}, "exists (select 1 from json_tree(media_file.participants, '$.artist') where key='name' and value = ?)", "u2"), Entry("role contains", criteria.Contains{"composer": "Lennon"}, "exists (select 1 from json_tree(media_file.participants, '$.composer') where key='name' and value LIKE ?)", "%Lennon%"), Entry("role not contains", criteria.NotContains{"artist": "u2"}, "not exists (select 1 from json_tree(media_file.participants, '$.artist') where key='name' and value LIKE ?)", "%u2%"), + // ReplayGain fields + Entry("rgAlbumGain is", criteria.Is{"rgAlbumGain": 0}, "media_file.rg_album_gain = ?", 0), + Entry("rgAlbumGain gt", criteria.Gt{"rgAlbumGain": -6.0}, "media_file.rg_album_gain > ?", -6.0), + Entry("rgTrackPeak lt", criteria.Lt{"rgTrackPeak": 1.0}, "media_file.rg_track_peak < ?", 1.0), // isMissing — tags Entry("isMissing tag [true]", criteria.IsMissing{"genre": true}, "not exists (select 1 from json_tree(media_file.tags, '$.genre') where key='value')"),