From 10868cab37e7dadf247d5da78f5eb5e69bcb6c9d Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Mon, 19 Oct 2026 09:52:38 +0200 Subject: notifications: resolve the sound keys and choose a balloon's sound Co-Authored-By: Claude Opus 5.5 --- shared/NotifyConfig.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'shared/NotifyConfig.js') diff --git a/shared/NotifyConfig.js b/shared/NotifyConfig.js index ff522c4..143168f 100644 --- a/shared/NotifyConfig.js +++ b/shared/NotifyConfig.js @@ -13,7 +13,7 @@ // ~/.config/notifyd/config.json, resolved over its defaults. notifyd reads // the same file for timeouts and caps (its config.go clamps the same way); -// the balloon keys are this side's alone. Tested by test_notify_config.js. +// the balloon keys and `sounds` are this side's alone. Tested by test_notify_config.js. const corners = ["top-left", "top-right", "bottom-left", "bottom-right"]; @@ -25,6 +25,8 @@ function defaults() { balloons: { screen: "DP-1", corner: "bottom-right" }, dndPassCritical: true, muted: [], + sounds: { low: "", normal: "", critical: "" }, + soundTheme: "freedesktop", }; } @@ -38,6 +40,7 @@ function resolve(raw) { if (!raw || typeof raw !== "object") return d; const t = raw.timeouts || {}; const b = raw.balloons || {}; + const s = raw.sounds || {}; return { timeouts: { low: seconds(t.low, d.timeouts.low), @@ -52,6 +55,12 @@ function resolve(raw) { }, dndPassCritical: typeof raw.dndPassCritical === "boolean" ? raw.dndPassCritical : d.dndPassCritical, muted: Array.isArray(raw.muted) ? raw.muted.filter(a => typeof a === "string") : d.muted, + sounds: { + low: typeof s.low === "string" ? s.low : d.sounds.low, + normal: typeof s.normal === "string" ? s.normal : d.sounds.normal, + critical: typeof s.critical === "string" ? s.critical : d.sounds.critical, + }, + soundTheme: typeof raw.soundTheme === "string" && raw.soundTheme !== "" ? raw.soundTheme : d.soundTheme, }; } @@ -61,3 +70,11 @@ function withheld(cfg, n, dnd) { if (cfg.muted.indexOf(n.app) >= 0) return true; return dnd && !(n.urgency === "critical" && cfg.dndPassCritical); } + +// The file a balloon plays, "" for none: the app's suppress-sound wins, then +// the app's own sound (notifyd resolved its hints), then the urgency's. +function soundFor(cfg, n) { + if (n.silent) return ""; + if (n.sound) return n.sound; + return cfg.sounds[n.urgency] || ""; +} -- cgit v1.2.3