timer-run: use system sound instead of generated PCM beep

Replace the Python sine-wave generator and raw PCM piping with
paplay playing alarm-clock-elapsed.oga, falling back to
canberra-gtk-play. Also export PULSE_RUNTIME_PATH for the detached
setsid process so paplay can find the PipeWire-Pulse socket.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
The_miro 2026-05-11 09:23:24 +02:00
parent d2c0c1ae1f
commit 968031ae11
1 changed files with 10 additions and 41 deletions

View File

@ -8,14 +8,14 @@
TOTAL="${1:?missing seconds}"
LABEL="${2:-}"
# ── source the user environment if running without a login shell ───────────────
# When launched from Hyprland keybind → kitty → exec, the process inherits
# kitty's env which already has DBUS_SESSION_BUS_ADDRESS, XDG_RUNTIME_DIR etc.
# But after setsid detach those are preserved since we don't re-login.
# We do need to make sure XDG_RUNTIME_DIR is set for pipewire/pulse socket paths.
# ── ensure runtime dir env vars are set for audio/dbus in detached context ────
if [[ -z "${XDG_RUNTIME_DIR:-}" ]]; then
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
fi
# paplay resolves the PulseAudio/PipeWire socket via PULSE_RUNTIME_PATH
if [[ -z "${PULSE_RUNTIME_PATH:-}" ]]; then
export PULSE_RUNTIME_PATH="${XDG_RUNTIME_DIR}/pulse"
fi
# ── detach from terminal immediately ──────────────────────────────────────────
# Preserve the full environment across the setsid re-exec (no login shell).
@ -70,41 +70,10 @@ if command -v notify-send &>/dev/null; then
fi
# ── audio alert ───────────────────────────────────────────────────────────────
# pw-play / paplay need PIPEWIRE_RUNTIME_DIR or PULSE_RUNTIME_PATH which live
# under XDG_RUNTIME_DIR — already ensured above.
_ALARM_SOUND="/usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga"
_beep_pcm() {
python3 - <<'PYEOF'
import struct, math, sys
RATE = 44100
FREQ = 880.0
VOL = 0.65
BEEPS = 3
DUR = 0.55
GAP = 0.18
def sine(freq, secs):
n = int(RATE * secs)
return [int(VOL * 32767 * math.sin(2 * math.pi * freq * i / RATE)) for i in range(n)]
def silence(secs):
return [0] * int(RATE * secs)
samples = []
for i in range(BEEPS):
samples += sine(FREQ, DUR)
if i < BEEPS - 1:
samples += silence(GAP)
sys.stdout.buffer.write(struct.pack(f'<{len(samples)}h', *samples))
PYEOF
}
if command -v pw-play &>/dev/null; then
_beep_pcm | pw-play --rate=44100 --channels=1 --format=s16 - 2>/dev/null
elif command -v paplay &>/dev/null; then
_beep_pcm | paplay --raw --rate=44100 --channels=1 --format=s16le - 2>/dev/null
elif command -v aplay &>/dev/null; then
_beep_pcm | aplay -q -r 44100 -c 1 -f S16_LE - 2>/dev/null
if command -v paplay &>/dev/null && [[ -f "$_ALARM_SOUND" ]]; then
paplay "$_ALARM_SOUND" 2>/dev/null
elif command -v canberra-gtk-play &>/dev/null; then
canberra-gtk-play --id=alarm-clock-elapsed 2>/dev/null
fi