Improve audio output selector
9490234f03b29e981cfb4899a0eb26f9069046bf
Work with bluetooth speakers.
1 parent
aacdce45
bin/waybar-audio-output-selector
+69 -10
| 1 | 1 | #!/bin/sh |
|
| 2 | 2 | ||
| 3 | 3 | sinks=$(pactl -f json list sinks | jq -r '.[] | [.name, .description] | @tsv') |
|
| 4 | - | ||
| 5 | - | [ -n "$sinks" ] || exit 1 |
|
| 6 | - | ||
| 7 | 4 | default=$(pactl get-default-sink) |
|
| 8 | - | sink=$( |
|
| 5 | + | choices=$( |
|
| 9 | 6 | printf '%s\n' "$sinks" | |
|
| 10 | - | awk -F '\t' -v current="$default" '{ |
|
| 7 | + | awk -F '\t' -v current="$default" 'NF { |
|
| 11 | 8 | marker = ($1 == current) ? "* " : " " |
|
| 12 | - | printf "%s\t%s%s\n", $1, marker, $2 |
|
| 13 | - | }' | |
|
| 14 | - | fuzzel --dmenu --hide-prompt --lines=6 --width=64 \ |
|
| 9 | + | icon = index($1, "bluez_output.") == 1 ? "" : "" |
|
| 10 | + | printf "sink:%s\t%s%s %s\n", $1, marker, icon, $2 |
|
| 11 | + | }' |
|
| 12 | + | ) |
|
| 13 | + | ||
| 14 | + | while read -r prefix address name; do |
|
| 15 | + | [ "$prefix" = Device ] || continue |
|
| 16 | + | ||
| 17 | + | info=$(bluetoothctl info "$address") |
|
| 18 | + | case "$info" in |
|
| 19 | + | *"UUID: Audio Sink"*) ;; |
|
| 20 | + | *) continue ;; |
|
| 21 | + | esac |
|
| 22 | + | ||
| 23 | + | device_key=$(printf '%s' "$address" | tr ':' '_') |
|
| 24 | + | case "$sinks" in |
|
| 25 | + | *"bluez_output.$device_key."*) continue ;; |
|
| 26 | + | esac |
|
| 27 | + | ||
| 28 | + | choices="${choices}${choices:+ |
|
| 29 | + | }bluetooth:$address $name" |
|
| 30 | + | done <<EOF |
|
| 31 | + | $(bluetoothctl devices Paired) |
|
| 32 | + | EOF |
|
| 33 | + | ||
| 34 | + | [ -n "$choices" ] || exit 1 |
|
| 35 | + | ||
| 36 | + | selection=$( |
|
| 37 | + | printf '%s\n' "$choices" | |
|
| 38 | + | fuzzel --dmenu --hide-prompt --lines=6 --width=64 \ |
|
| 15 | 39 | --with-nth=2 --accept-nth=1 --only-match --no-run-if-empty |
|
| 16 | - | ) || exit 0 |
|
| 40 | + | ) || exit 0 |
|
| 41 | + | ||
| 42 | + | [ -n "$selection" ] || exit 1 |
|
| 43 | + | ||
| 44 | + | case "$selection" in |
|
| 45 | + | sink:*) |
|
| 46 | + | sink=${selection#sink:} |
|
| 47 | + | case "$sink" in |
|
| 48 | + | bluez_output.*) |
|
| 49 | + | device_key=${sink#bluez_output.} |
|
| 50 | + | device_key=${device_key%%.*} |
|
| 51 | + | address=$(printf '%s' "$device_key" | tr '_' ':') |
|
| 52 | + | bluetoothctl connect "$address" || exit 1 |
|
| 53 | + | ;; |
|
| 54 | + | esac |
|
| 55 | + | ;; |
|
| 56 | + | bluetooth:*) |
|
| 57 | + | address=${selection#bluetooth:} |
|
| 58 | + | bluetoothctl connect "$address" || exit 1 |
|
| 17 | 59 | ||
| 18 | - | [ -n "$sink" ] || exit 1 |
|
| 60 | + | device_key=$(printf '%s' "$address" | tr ':' '_') |
|
| 61 | + | attempts=0 |
|
| 62 | + | while [ "$attempts" -lt 20 ]; do |
|
| 63 | + | sink=$( |
|
| 64 | + | pactl -f json list sinks | |
|
| 65 | + | jq -r --arg prefix "bluez_output.$device_key." \ |
|
| 66 | + | 'first(.[] | select(.name | startswith($prefix)) | .name) // empty' |
|
| 67 | + | ) |
|
| 68 | + | [ -n "$sink" ] && break |
|
| 69 | + | sleep 0.25 |
|
| 70 | + | attempts=$((attempts + 1)) |
|
| 71 | + | done |
|
| 72 | + | [ -n "$sink" ] || exit 1 |
|
| 73 | + | ;; |
|
| 74 | + | *) |
|
| 75 | + | exit 1 |
|
| 76 | + | ;; |
|
| 77 | + | esac |
|
| 19 | 78 | ||
| 20 | 79 | pactl set-default-sink "$sink" |
|
| 21 | 80 | pactl list sink-inputs short | awk '{ print $1 }' | while read -r input; do |
|
| 22 | 81 | pactl move-sink-input "$input" "$sink" |
|
| 23 | 82 | done |