50 lines
1.3 KiB
Bash
Executable File
50 lines
1.3 KiB
Bash
Executable File
#!/usr/bin/env zsh
|
|
# Minimal PipeWire sink cycler using starred lines from wpctl status.
|
|
# Deps: pw-dump, jq, wpctl
|
|
|
|
set -euo pipefail
|
|
|
|
# Collect sink IDs (Audio/Sink nodes)
|
|
sinks=($(pw-dump | jq -r '.[] | select(.info.props."media.class"=="Audio/Sink") | .id'))
|
|
(( ${#sinks} )) || exit 0
|
|
|
|
# Get all lines containing a star (default indicators for various classes)
|
|
starred=$(wpctl status | grep -F '*') || true
|
|
|
|
# Extract numbers (IDs) from starred lines (the number before the first dot after the star)
|
|
typeset -a star_ids
|
|
while IFS= read -r line; do
|
|
# Match: * <spaces> <number>.
|
|
if [[ $line =~ [*][[:space:]]*([0-9]+)\. ]]; then
|
|
star_ids+=("${match[1]}")
|
|
fi
|
|
done <<< "$starred"
|
|
|
|
# Find first starred ID that is actually one of our sinks
|
|
current=""
|
|
for cid in "${star_ids[@]}"; do
|
|
for s in "${sinks[@]}"; do
|
|
if [[ $cid == $s ]]; then
|
|
current=$cid
|
|
break 2
|
|
fi
|
|
done
|
|
done
|
|
|
|
# Fallback if no starred sink matched
|
|
[[ -z $current ]] && current=${sinks[1]}
|
|
|
|
# Locate index of current in sinks (zsh arrays are 1-based)
|
|
idx=1
|
|
for i in {1..${#sinks[@]}}; do
|
|
[[ ${sinks[$i]} == "$current" ]] && { idx=$i; break; }
|
|
done
|
|
|
|
# Compute next sink (wrap)
|
|
next=${sinks[$(( (idx % ${#sinks}) + 1 ))]}
|
|
|
|
# Switch default
|
|
wpctl set-default "$next" >/dev/null 2>&1 || exit 1
|
|
|
|
echo "Switched to sink $next"
|