Give Sound the whole story, and keep the buttons inside the card

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 11:39:16 -04:00
parent 9bc68ba358
commit b58371bb35
38 changed files with 3884 additions and 213 deletions
+133
View File
@@ -94,6 +94,13 @@ elif [[ $1 == "status" ]]; then
fi
SH
cat >"$scratch/bin/pw-play" <<'SH'
#!/bin/bash
printf 'pw-play' >>"$OSD_TEST_LOG"
printf ' <%s>' "$@" >>"$OSD_TEST_LOG"
printf '\n' >>"$OSD_TEST_LOG"
SH
cat >"$scratch/bin/qs" <<'SH'
#!/bin/bash
printf 'qs' >>"$OSD_TEST_LOG"
@@ -104,10 +111,31 @@ SH
chmod +x "$scratch/bin/"*
# The blip and the over-amplification limit are both read out of Panama's own
# settings.json, so every run below gets its own config root. Without this the
# helper would read Gabriel's real preferences and the assertions would pass or
# fail depending on which switches he happens to have on.
blip_sound="$scratch/blip.oga"
: >"$blip_sound"
mkdir -p "$scratch/config-default"
# Write a settings.json for one run. No arguments means no file at all, which
# is what a fresh install looks like: the helper must fall back to the schema
# defaults rather than treating an absent file as an error.
settings_root() {
local name="$1" body="${2:-}" root="$scratch/config-$name"
rm -rf "$root"
mkdir -p "$root/panama"
[[ -n "$body" ]] && printf '%s\n' "$body" >"$root/panama/settings.json"
printf '%s' "$root"
}
run_helper() {
local runtime="${OSD_RUNTIME_DIR:-$scratch/runtime-default}"
mkdir -p "$runtime"
PATH="$scratch/bin:$PATH" OSD_TEST_LOG="$log" \
XDG_CONFIG_HOME="${OSD_CONFIG_HOME:-$scratch/config-default}" \
PANAMA_OSD_BLIP_SOUND="${OSD_BLIP_SOUND:-$blip_sound}" \
OSD_TEST_FAIL_QS="${OSD_TEST_FAIL_QS:-false}" \
PANAMA_OSD_STRICT="${PANAMA_OSD_STRICT:-false}" \
PANAMA_OSD_BRIGHTNESS_HELPER="$scratch/bin/panama-brightness" \
@@ -132,6 +160,31 @@ assert_line() {
}
}
# The blip is backgrounded and never waited on -- deliberately, so it cannot sit
# between the key press and the OSD. Which means the line may land after the
# helper has already exited, and asserting it needs a moment rather than an
# instant. Waiting here also keeps a slow blip from bleeding into the next
# case's freshly truncated log.
await_line() {
local expected="$1"
for _ in $(seq 1 60); do
grep -Fqx -- "$expected" "$log" && return 0
sleep 0.05
done
printf 'osd helper contract: missing call\n%s\nactual:\n' "$expected" >&2
cat "$log" >&2
exit 1
}
refute_line() {
local unexpected="$1" why="$2"
if grep -Fq -- "$unexpected" "$log"; then
printf 'osd helper contract: %s\nunexpected: %s\nactual:\n' "$why" "$unexpected" >&2
cat "$log" >&2
exit 1
fi
}
: >"$log"
run_helper volume up 6
assert_line 'wpctl <set-volume> <-l> <1> <@DEFAULT_AUDIO_SINK@> <6%+>'
@@ -148,6 +201,86 @@ WPCTL_OUTPUT='Volume: 0.72 [MUTED]' run_helper microphone toggle
assert_line 'wpctl <set-mute> <@DEFAULT_AUDIO_SOURCE@> <toggle>'
assert_line 'qs <ipc> <call> <osd> <progress> <microphone-muted> <72> <100> <Muted>'
# ── Over-amplification: the ceiling is a setting, not a constant ─────────────
# `wpctl set-volume` clamps to 1.0 unless told otherwise, and it clamps the
# *result* -- so the limit has to be on the down step too. Without it, coming
# down from 130% would snap to 100% instead of stepping to 124%, which reads as
# the slider jumping on its own.
: >"$log"
OSD_CONFIG_HOME="$(settings_root overamp '{"overAmplification": true}')" \
run_helper volume up 6
assert_line 'wpctl <set-volume> <-l> <1.5> <@DEFAULT_AUDIO_SINK@> <6%+>'
: >"$log"
OSD_CONFIG_HOME="$(settings_root overamp '{"overAmplification": true}')" \
run_helper volume down 6
assert_line 'wpctl <set-volume> <-l> <1.5> <@DEFAULT_AUDIO_SINK@> <6%->'
# The microphone is not part of the bargain: no amount of gain past 100% makes
# a capture device better, and the Sound page's input slider stays 0-100 to
# match.
: >"$log"
OSD_CONFIG_HOME="$(settings_root overamp '{"overAmplification": true}')" \
run_helper microphone up 6
assert_line 'wpctl <set-volume> <-l> <1> <@DEFAULT_AUDIO_SOURCE@> <6%+>'
refute_line '<-l> <1.5> <@DEFAULT_AUDIO_SOURCE@>' \
'over-amplification leaked onto the microphone'
: >"$log"
OSD_CONFIG_HOME="$(settings_root plain '{"overAmplification": false}')" \
run_helper volume up 6
assert_line 'wpctl <set-volume> <-l> <1> <@DEFAULT_AUDIO_SINK@> <6%+>'
# A settings file that predates the key, and a settings file that is not JSON
# at all, both mean "off" rather than "no volume keys work today".
: >"$log"
OSD_CONFIG_HOME="$(settings_root nokey '{"barBackdrop": true}')" run_helper volume up 6
assert_line 'wpctl <set-volume> <-l> <1> <@DEFAULT_AUDIO_SINK@> <6%+>'
: >"$log"
OSD_CONFIG_HOME="$(settings_root broken '{not json')" run_helper volume up 6
assert_line 'wpctl <set-volume> <-l> <1> <@DEFAULT_AUDIO_SINK@> <6%+>'
assert_line 'qs <ipc> <call> <osd> <progress> <volume> <58> <100> <58%>'
# ── The volume blip ─────────────────────────────────────────────────────────
# Default on, per the schema, so a settings.json that has never been written
# still clicks. Fire-and-forget: the blip must never gate the OSD.
: >"$log"
run_helper volume up 6
await_line "pw-play <$blip_sound>"
assert_line 'qs <ipc> <call> <osd> <progress> <volume> <58> <100> <58%>'
: >"$log"
run_helper volume down 6
await_line "pw-play <$blip_sound>"
: >"$log"
WPCTL_OUTPUT='Volume: 0.58' run_helper volume toggle
await_line "pw-play <$blip_sound>"
: >"$log"
OSD_CONFIG_HOME="$(settings_root silent '{"volumeChangeBlip": false}')" \
run_helper volume up 6
refute_line 'pw-play' 'the blip played with volumeChangeBlip off'
assert_line 'qs <ipc> <call> <osd> <progress> <volume> <58> <100> <58%>'
# Brightness and the microphone are not volume changes.
: >"$log"
run_helper brightness up 5
refute_line 'pw-play' 'a brightness step played the volume blip'
: >"$log"
WPCTL_OUTPUT='Volume: 0.72' run_helper microphone up 6
refute_line 'pw-play' 'a microphone step played the volume blip'
# A distribution without the freedesktop sound theme has no file to play. That
# is a silent desktop, not a broken volume key.
: >"$log"
OSD_BLIP_SOUND="$scratch/nothing-here.oga" run_helper volume up 6
refute_line 'pw-play' 'the blip ran against a file that does not exist'
assert_line 'wpctl <set-volume> <-l> <1> <@DEFAULT_AUDIO_SINK@> <6%+>'
assert_line 'qs <ipc> <call> <osd> <progress> <volume> <58> <100> <58%>'
: >"$log"
run_helper brightness up 5
assert_line 'brightnessctl <-m> <-c> <backlight>'