bin/waybar-audio-output-selector 2.0 KiB raw
1
#!/bin/sh
2
3
sinks=$(pactl -f json list sinks | jq -r '.[] | [.name, .description] | @tsv')
4
default=$(pactl get-default-sink)
5
choices=$(
6
  printf '%s\n' "$sinks" |
7
    awk -F '\t' -v current="$default" 'NF {
8
      marker = ($1 == current) ? "* " : "  "
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 \
39
      --with-nth=2 --accept-nth=1 --only-match --no-run-if-empty
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
59
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
78
79
pactl set-default-sink "$sink"
80
pactl list sink-inputs short | awk '{ print $1 }' | while read -r input; do
81
  pactl move-sink-input "$input" "$sink"
82
done