Files
nixos/scripts/WMScripts/toggle_audiocables_bar.sh
T
2026-10-06 22:34:05 +02:00

113 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# This script toggles state between a few of my audio cables:
# combine sink -> default_output | hyperx_output
# clementine sink -> combine sink | default_output
# The script also outputs a symbol indicating which configuration is active.
# Usecase: My USB-C headset is a different sink than the one in the laptop; sometimes I want to have audio over the headset, sometimes through the laptop.
# Output symbols
# SYMBOLS=("neither" "co^!cl" "cl^!co" "both")
SYMBOLS=("󰴸 " "󰝚 " "󰓃 " "󰋋 ")
# The sinks to test against
DEFAULT_SINKS=("bluez_output_internal.0A_E6_E0_F9_F1_BE.1" "alsa_output.pci-0000_06_00.6.analog-stereo" "bluez_output.20_18_5B_F0_FC_4A.1" "bluez_output.0A_E6_E0_F9_F1_BE.1" "bluez_output.0A_E6_E0_F9_F1_BE" "bluez_output.0A:E6:E0:F9:F1:BE")
USB_C_SINK="alsa_output.usb-HP__Inc_HyperX_Cloud_III_Wireless_0000000000000000-00.analog-stereo"
COMBINE_SINK="combine"
# awkcommand - a little complicated, but basically tests if the DEFAULT_SINK is connected to the clementine sink (adding +2 if so) or the combine sink (adding +1). This gives a numerical mapping for all 4 states im interested in:
# 0: neither combine,clementine are attached to usb_c_sink
# 1: only combine is attached to usb_c_sink
# 2: only clementine is attached to usb_c_sink
# 3: both combine,clementine are attached to usb_c_sink
read -r -d "" awkcommand << EOF
/$USB_C_SINK:playback_FL/,/$USB_C_SINK:playback_FR/ {
if (\$2 == "combine:monitor_FL") {
state += 1
}
}
/$COMBINE_SINK:playback_FL/,/$COMBINE_SINK:playback_FR/ {
if (\$2 == "clementine:monitor_FL") {
state += 2
}
}
END {
printf "%d\n", state
}
EOF
# Attaches a single sink to a specific source
function attach() {
echo "attaching $1 to $2"
pw-link "$1":monitor_FL "$2":playback_FL
pw-link "$1":monitor_FR "$2":playback_FR
}
# Attaches an array of sinks to a specific source.
# $1 = source (pw monitor)
# $2 = list of sinks to attach
function attachArray() {
name=$2[@]
a=("${!name}")
for sink in "${a[@]}"; do
attach "$1" "$sink"
done
}
# Detaches a single sink from a specific source
function detach() {
echo "detaching $1 from $2"
pw-link -d "$1":monitor_FL "$2":playback_FL
pw-link -d "$1":monitor_FR "$2":playback_FR
}
# Detaches an array of sinks to a specific source.
# $1 = source (pw monitor)
# $2 = list of sinks to attach
function detachArray() {
name=$2[@]
a=("${!name}")
for sink in "${a[@]}"; do
detach "$1" "$sink"
done
}
state=$(pw-link -li | awk "$awkcommand")
IFS=$'\n'
# actually toggle iff we have a $1 telling us to
if [[ "$1" == "toggle" ]];then
case "$2" in
"clementine")
if [[ $state -eq 2 || $state -eq 3 ]]; then
detach "clementine" "$COMBINE_SINK"
attachArray "clementine" "DEFAULT_SINKS"
state=$((state-2))
else
detachArray "clementine" "DEFAULT_SINKS"
attach "clementine" "$COMBINE_SINK"
state=$((state+2))
fi
;;
"combine")
if [[ $state -eq 1 || $state -eq 3 ]]; then
detach "combine" "$USB_C_SINK"
attachArray "combine" "DEFAULT_SINKS"
state=$((state-1))
else
detachArray "combine" "DEFAULT_SINKS"
attach "combine" "$USB_C_SINK"
state=$((state+1))
fi
;;
*)
echo "Unknown option: '$2'"
;;
esac
fi
echo "${SYMBOLS[$state]}"