Skip to content

Instantly share code, notes, and snippets.

@fstanis
Last active April 30, 2021 14:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fstanis/afe918cde04e27fc151d2e8359ff351c to your computer and use it in GitHub Desktop.
Save fstanis/afe918cde04e27fc151d2e8359ff351c to your computer and use it in GitHub Desktop.
pacmd with extensions
#!/bin/bash
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
# This script provides a few extensions to pacmd, the tool used to reconfigure
# a running PulseAudio sound server during runtime.
# Added commands:
# exists-card Checks if card exists (args: name)
# exists-sink Checks if sink exists (args: name)
# exists-source Checks if source exists (args: name)
# await-card Blocks until card exists (args: name)
# move-all-to-sink Set the default sink and move all sink inputs to it (args: index|name)
# move-all-to-source Set the default source and move all source outputs to it (args: index|name)
# sinks-muted Checks if all sinks are muted
# sources-muted Checks if all sources are muted
# toggle-sinks-mute Mutes or unmutes all sinks
# toggle-sources-mute Mutes or unmutes all sources
# bluez-card-name Generates card name used by bluez (args: mac)
# bluez-a2dp-sink-name Generates an A2DP sink name used by bluez (args: mac)
# Unrecognized commands are passed to pacmd.
pacmd_exists() {
[[ "${2}" ]] || die "Must specify ${1} name"
pacmd "list-${1}s" | grep -Fq -e "name: <${2}>" -e "index: ${2}"
}
pacmd_await() {
while ! pacmd_exists "${1}" "${2}"; do
sleep 1
done
}
pacmd_indexes() {
pacmd "list-${1}s" | grep -Po 'index: \K\d+'
}
pacmd_move_all_to() {
pacmd "set-default-${1}" "${3}" || exit 1
for index in $(pacmd_indexes "${1}-${2}"); do
pacmd "move-${1}-${2}" "$index" "${3}"
done
}
pacmd_is_muted() {
! pacmd list-${1}s | grep -Pq 'muted:\s+no'
}
pacmd_mute() {
for index in $(pacmd_indexes ${1}); do
pacmd "set-${1}-mute" "$index" "${2}"
done
}
pacmd_mute_toggle() {
if pacmd_is_muted "${1}"; then
pacmd_mute "${1}" false
else
pacmd_mute "${1}" true
fi
}
bluez_name() {
[[ "${2}" ]] || die "Must specify mac address"
local address="${2//:/_}"
case "$1" in
card)
local card="bluez_card.${address}"
echo "$card"
pacmd_exists card "$card"
;;
a2dp_sink)
local sink="bluez_sink.$address.a2dp_sink"
echo "$sink"
pacmd_exists sink "$sink"
;;
hsp_sink)
local sink="bluez_sink.$address.headset_head_unit"
echo "$sink"
pacmd_exists sink "$sink"
;;
hsp_source)
local source="bluez_source.$address.headset_head_unit"
echo "$source"
pacmd_exists source "$source"
;;
esac
}
die() {
echo "$1" >&2 && exit 1
}
main() {
case "$1" in
exists-card)
pacmd_exists card "$2"
;;
exists-sink)
pacmd_exists sink "$2"
;;
exists-source)
pacmd_exists source "$2"
;;
await-card)
pacmd_await card "$2"
;;
move-all-to-sink)
pacmd_move_all_to sink input "$2"
;;
move-all-to-source)
pacmd_move_all_to source output "$2"
;;
sinks-muted)
pacmd_is_muted sink
;;
sources-muted)
pacmd_is_muted source
;;
toggle-sinks-mute)
pacmd_mute_toggle sink
;;
toggle-sources-mute)
pacmd_mute_toggle source
;;
bluez-card-name)
bluez_name card "$2"
;;
bluez-a2dp-sink-name)
bluez_name a2dp_sink "$2"
;;
bluez-hsp-sink-name)
bluez_name hsp_sink "$2"
;;
bluez-hsp-source-name)
bluez_name hsp_source "$2"
;;
*)
pacmd "$@"
;;
esac
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment