# shellcheck shell=bash # Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # pulseRecordLib.sh - shared PulseAudio capture helpers. SOURCE, do not run. # # Used by verify-amiga-audio.sh and verify-dos-audio.sh, the two gates that # grade recorded sound because Paula and the Sound Blaster cannot be tapped # register-by-register under fs-uae and DOSBox. # # The recording scheme in both: create a null sink for THIS run, point only # the emulator at it with PULSE_SINK, and record that sink's monitor with # parec. The host's default sink is never touched, so the gates are safe to # run on a desktop that is playing something else, and two gates can never # collide because the sink name carries the pid. # pulseEnsureServer -- locate the audio server, or fail with a real reason. # # A sanitised environment (cron, CI, `env -i`, a systemd unit without the # user session) has no XDG_RUNTIME_DIR, and pactl then reports "no server" # even though one is running -- measured: `env -i make verify-audio` skipped # both recording gates for exactly this. The socket lives at a predictable # path, so derive it before giving up. pulseEnsureServer() { if pactl info >/dev/null 2>&1; then return 0 fi if [ -z "${XDG_RUNTIME_DIR:-}" ] && [ -S "/run/user/$(id -u)/pulse/native" ]; then export XDG_RUNTIME_DIR="/run/user/$(id -u)" if pactl info >/dev/null 2>&1; then return 0 fi fi if [ -z "${PULSE_SERVER:-}" ] && [ -S "/run/user/$(id -u)/pulse/native" ]; then export PULSE_SERVER="unix:/run/user/$(id -u)/pulse/native" if pactl info >/dev/null 2>&1; then return 0 fi fi return 1 } # pulseCreateSink -- echo the module id of a new null sink. pulseCreateSink() { pactl load-module module-null-sink \ sink_name="$1" \ sink_properties=device.description="$1" 2>/dev/null } # pulseUnloadSink -- always call this; a leaked null sink on the # user's audio server is the one lasting side effect these gates can have. pulseUnloadSink() { [ -n "${1:-}" ] && pactl unload-module "$1" 2>/dev/null return 0 }