update
This commit is contained in:
parent
c05bae722b
commit
f9df806b6d
9 changed files with 189 additions and 0 deletions
141
user/audio-resume-recover.sh
Executable file
141
user/audio-resume-recover.sh
Executable file
|
|
@ -0,0 +1,141 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
readonly ECHO_ADDRESS="44:D5:CC:C8:64:39"
|
||||
readonly ECHO_SINK_UUID="0000110b-0000-1000-8000-00805f9b34fb"
|
||||
readonly ECHO_CARD="bluez_card.44_D5_CC_C8_64_39"
|
||||
readonly ECHO_SINK="bluez_output.44_D5_CC_C8_64_39.1"
|
||||
readonly KOKORO_SERVICE="kokoro.service"
|
||||
readonly VOXTYPE_SERVICE="voxtype.service"
|
||||
readonly STARTUP_DELAY_SECONDS=3
|
||||
readonly RETRY_DELAY_SECONDS=2
|
||||
readonly MAX_RETRIES=15
|
||||
|
||||
log() {
|
||||
printf 'audio-resume: %s\n' "$*"
|
||||
}
|
||||
|
||||
fail() {
|
||||
local message="$1"
|
||||
|
||||
log "ERROR: ${message}"
|
||||
notify-send --urgency=critical "Audio resume failed" "${message}" >/dev/null 2>&1 || true
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_for_pipewire() {
|
||||
local attempt
|
||||
|
||||
for ((attempt = 1; attempt <= MAX_RETRIES; attempt++)); do
|
||||
if pactl info >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
sleep "${RETRY_DELAY_SECONDS}"
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
echo_sink_exists() {
|
||||
pactl list short sinks 2>/dev/null | awk -v sink="${ECHO_SINK}" '$2 == sink { found = 1 } END { exit !found }'
|
||||
}
|
||||
|
||||
echo_sink_is_running() {
|
||||
pactl list sinks 2>/dev/null | awk -v sink="${ECHO_SINK}" '
|
||||
$1 == "Name:" { selected = ($2 == sink) }
|
||||
selected && $1 == "State:" && $2 == "RUNNING" { found = 1 }
|
||||
END { exit !found }
|
||||
'
|
||||
}
|
||||
|
||||
connect_echo_output() {
|
||||
local attempt
|
||||
|
||||
bluetoothctl power on >/dev/null 2>&1 || true
|
||||
|
||||
for ((attempt = 1; attempt <= MAX_RETRIES; attempt++)); do
|
||||
log "Connecting Echo output profile (attempt ${attempt}/${MAX_RETRIES})"
|
||||
bluetoothctl connect "${ECHO_ADDRESS}" "${ECHO_SINK_UUID}" >/dev/null 2>&1 || true
|
||||
|
||||
if echo_sink_exists; then
|
||||
pactl set-card-profile "${ECHO_CARD}" a2dp-sink >/dev/null 2>&1 || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
sleep "${RETRY_DELAY_SECONDS}"
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_kokoro() {
|
||||
local attempt
|
||||
|
||||
for ((attempt = 1; attempt <= MAX_RETRIES; attempt++)); do
|
||||
if test -S "${XDG_RUNTIME_DIR}/kokoro.sock"; then
|
||||
return 0
|
||||
fi
|
||||
sleep "${RETRY_DELAY_SECONDS}"
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
verify_playback() {
|
||||
local attempt
|
||||
|
||||
/usr/local/src/kokora/say "Audio resumed." || return 1
|
||||
|
||||
for ((attempt = 1; attempt <= MAX_RETRIES; attempt++)); do
|
||||
if echo_sink_is_running; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
main() {
|
||||
sleep "${STARTUP_DELAY_SECONDS}"
|
||||
|
||||
# Do not leave an always-open pw-cat stream attached while rebuilding the
|
||||
# Bluetooth and PipeWire graph.
|
||||
systemctl --user stop "${KOKORO_SERVICE}" || true
|
||||
bluetoothctl disconnect "${ECHO_ADDRESS}" >/dev/null 2>&1 || true
|
||||
|
||||
log "Restarting PipeWire and WirePlumber with the Echo disconnected"
|
||||
systemctl --user restart pipewire.service pipewire-pulse.service wireplumber.service \
|
||||
|| fail "PipeWire or WirePlumber could not be restarted."
|
||||
|
||||
# pipewire.service wants Kokoro, so make sure it remains out of the way
|
||||
# until the correct Echo output profile has been established.
|
||||
systemctl --user stop "${KOKORO_SERVICE}" || true
|
||||
|
||||
wait_for_pipewire \
|
||||
|| fail "PipeWire did not become ready after resume."
|
||||
|
||||
connect_echo_output \
|
||||
|| fail "The Echo connected without a usable A2DP output."
|
||||
|
||||
# Voxtype keeps an ALSA output stream open for sound cues. Recreate it
|
||||
# after PipeWire and the default output have been rebuilt.
|
||||
log "Restarting Voxtype after the Echo output is ready"
|
||||
systemctl --user restart "${VOXTYPE_SERVICE}" \
|
||||
|| fail "Voxtype could not be restarted."
|
||||
|
||||
log "Starting Kokoro after the Echo output is ready"
|
||||
systemctl --user start "${KOKORO_SERVICE}" \
|
||||
|| fail "Kokoro could not be started."
|
||||
|
||||
wait_for_kokoro \
|
||||
|| fail "Kokoro started without creating its socket."
|
||||
|
||||
verify_playback \
|
||||
|| fail "The Echo sink appeared, but playback did not become active."
|
||||
|
||||
log "Audio recovery completed successfully"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Loading…
Add table
Add a link
Reference in a new issue