#!/usr/bin/env bash set -Eeuo pipefail sink_ids=() current_index=-1 while IFS=$'\t' read -r id is_default; do [[ -n "$id" ]] || continue sink_ids+=("$id") [[ "$is_default" == true ]] && current_index=$((${#sink_ids[@]} - 1)) done < <( wpctl status -n | awk ' /^Audio$/ {in_audio = 1; next} /^Video$/ {in_audio = 0; in_sinks = 0} in_audio && /Sinks:/ {in_sinks = 1; next} /Sources:/ {in_sinks = 0} in_audio && in_sinks && match($0, /[0-9]+\./) { id = substr($0, RSTART, RLENGTH - 1) print id "\t" (index($0, "*") ? "true" : "false") } ' ) ((${#sink_ids[@]} > 0)) || exit 0 next_index=$(((current_index + 1) % ${#sink_ids[@]})) next_sink_id="${sink_ids[$next_index]}" wpctl set-default "$next_sink_id" # Move existing playback streams too; set-default alone only affects new ones. while read -r stream_id; do [[ -n "$stream_id" ]] || continue if wpctl inspect "$stream_id" 2>/dev/null | grep -q 'media.class = "Stream/Output/Audio"'; then wpctl set-target "$stream_id" "$next_sink_id" 2>/dev/null || true fi done < <( wpctl status -n | awk ' /^Audio$/ {in_audio = 1; next} /^Video$/ {in_audio = 0; in_streams = 0} in_audio && /Streams:/ {in_streams = 1; next} in_audio && in_streams && match($0, /[0-9]+\./) { print substr($0, RSTART, RLENGTH - 1) } ' ) sink_name=$( wpctl inspect "$next_sink_id" \ | awk -F' = ' '/node.nick/ {gsub(/^"|"$/, "", $2); print $2; exit}' ) [[ -n "$sink_name" ]] || sink_name="Output $next_sink_id" notify-send -a Waybar -u low -r 9102 "Audio output changed" "$sink_name"