aboutsummaryrefslogtreecommitdiffstats
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/NotifyConfig.js19
-rw-r--r--shared/test_notify_config.js18
2 files changed, 35 insertions, 2 deletions
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] || "";
+}
diff --git a/shared/test_notify_config.js b/shared/test_notify_config.js
index b58fbde..c7bc2cc 100644
--- a/shared/test_notify_config.js
+++ b/shared/test_notify_config.js
@@ -18,7 +18,7 @@ const assert = require("assert");
const src = fs.readFileSync(__dirname + "/NotifyConfig.js", "utf8")
.replace(/^\.pragma library$/m, "");
-const C = new Function(src + "\nreturn { defaults, resolve, withheld };")();
+const C = new Function(src + "\nreturn { defaults, resolve, withheld, soundFor };")();
// Nothing, or garbage, is the defaults.
assert.deepStrictEqual(C.resolve(undefined), C.defaults());
@@ -48,4 +48,20 @@ assert.strictEqual(C.withheld(cfg, n("ok", "normal"), true), true);
assert.strictEqual(C.withheld(cfg, n("ok", "critical"), true), false);
assert.strictEqual(C.withheld(C.resolve({ dndPassCritical: false }), n("ok", "critical"), true), true);
+// Sounds: strings only, empty theme falls back.
+const s = C.resolve({ sounds: { low: "/a.oga", normal: 3 }, soundTheme: "" });
+assert.deepStrictEqual(s.sounds, { low: "/a.oga", normal: "", critical: "" });
+assert.strictEqual(s.soundTheme, "freedesktop");
+assert.strictEqual(C.resolve({ soundTheme: "mine" }).soundTheme, "mine");
+
+// soundFor: silent beats everything, the app's sound beats the urgency's.
+const sc = C.resolve({ sounds: { low: "", normal: "/n.oga", critical: "/c.oga" } });
+const sn = (urgency, sound, silent) => ({ app: "x", urgency, sound, silent });
+assert.strictEqual(C.soundFor(sc, sn("normal", "", false)), "/n.oga");
+assert.strictEqual(C.soundFor(sc, sn("low", "", false)), "");
+assert.strictEqual(C.soundFor(sc, sn("low", "/app.oga", false)), "/app.oga");
+assert.strictEqual(C.soundFor(sc, sn("critical", "/app.oga", true)), "");
+// An old daemon publishes neither field.
+assert.strictEqual(C.soundFor(sc, { app: "x", urgency: "critical" }), "/c.oga");
+
console.log("ok");