#!/usr/bin/env bash # ============================================================== # Audio Output Switcher (PipeWire + pactl) # -------------------------------------------------------------- # Author : Kris Yotam (aka. khr1st) # Contact : krisyotam@protonmail.com # License : GNU GPLv3 # Date : 2025-10-21 # -------------------------------------------------------------- # Description: # Interactive utility to select an audio sink and route all # active PipeWire/PulseAudio streams to it using pactl. # Keeps a simple mapping of friendly names to sink IDs. # ============================================================== declare -A DEVICES=( ["AirPods Max"]="bluez_output.90_62_3F_A3_22_43.1" ["Corsair HS65"]="alsa_output.usb-Corsair_Corsair_HS65_SURROUND-00.analog-stereo" ["HDMI Output"]="alsa_output.pci-0000_0c_00.1.hdmi-stereo" ["Onboard Digital"]="alsa_output.pci-0000_0e_00.4.iec958-stereo" ) check_connected() { pactl list short sinks | awk '{print $2}' | grep -q "$1" && echo "Connected" || echo "Not Connected" } echo "───────────────────────────────" echo " Audio Output Switcher" echo "───────────────────────────────" i=1 declare -A CHOICES for name in "${!DEVICES[@]}"; do sink="${DEVICES[$name]}" status=$(check_connected "$sink") printf "%d) %-20s [%s]\n" "$i" "$name" "$status" CHOICES["$i"]="$sink" ((i++)) done echo "───────────────────────────────" read -rp "Select a device: " choice sink="${CHOICES[$choice]}" if [[ -z "$sink" ]]; then echo "Invalid choice. Try again next time, champ." exit 1 fi echo "Setting default sink to $sink..." pactl set-default-sink "$sink" 2>/dev/null inputs=$(pactl list short sink-inputs | awk '{print $1}') if [[ -z "$inputs" ]]; then echo "No active streams. Default updated anyway." else echo "Moving active streams..." for input in $inputs; do pactl move-sink-input "$input" "$sink" done fi echo "Done. If it still doesn’t play, blame Bluetooth, not me."