dotfiles/bin/rice-bt
Sarthak 7f41cf7a82 replace the old dotfiles with the sakura line rice
The bare $HOME repo is gone. This is now the rice: install.sh, rice-*
scripts in bin/, configs in home/ linked into $HOME, theme templates, st
and the particle wallpaper. Clone to ~/rice and run install.sh.
2026-09-14 19:44:44 +05:30

100 lines
4.5 KiB
Bash
Executable file

#!/usr/bin/env bash
# rice-bt - bluetooth state for the eww panel, and the actions it runs.
#
# rice-bt list JSON: power, discovery, paired and nearby devices
# rice-bt power on|off|toggle
# rice-bt scan look for new devices for 15 seconds
# rice-bt toggle <MAC> connect or disconnect; new devices are paired and trusted first
# rice-bt forget <MAC>
#
# Device names are chosen by the device, so the panel only ever passes MAC
# addresses, and every MAC is checked before it is used.
set -uo pipefail
run="${XDG_RUNTIME_DIR:-/tmp}/rice"
mkdir -p "$run"
say() { rice-notify send "$1" "${2:-}" -i bluetooth; }
poke() { date +%s%N > "$run/bt.rev"; }
mac_ok() { [[ ${1:-} =~ ^([0-9A-F]{2}:){5}[0-9A-F]{2}$ ]] || { echo "rice-bt: not a MAC address: '${1:-}'" >&2; exit 2; }; }
powered() { bluetoothctl show 2>/dev/null | grep -q 'Powered: yes'; }
glyph() {
case "$1" in
audio-headset|audio-headphones) echo 󰋋 ;;
audio-card) echo 󰓃 ;;
input-keyboard) echo 󰌌 ;;
input-mouse) echo 󰍽 ;;
input-gaming) echo 󰊴 ;;
phone) echo 󰏲 ;;
computer) echo 󰍹 ;;
*) echo 󰂯 ;;
esac
}
device_json() {
local mac="$1" info name icon paired connected battery
info=$(bluetoothctl info "$mac" 2>/dev/null)
name=$(sed -n 's/^\s*Alias: //p' <<<"$info" | head -n1)
icon=$(sed -n 's/^\s*Icon: //p' <<<"$info" | head -n1)
paired=$(grep -q 'Paired: yes' <<<"$info" && echo true || echo false)
connected=$(grep -q 'Connected: yes' <<<"$info" && echo true || echo false)
battery=$(sed -n 's/^\s*Battery Percentage: .*(\([0-9]*\))/\1/p' <<<"$info" | head -n1)
jq -cn --arg mac "$mac" --arg name "${name:-$mac}" --arg glyph "$(glyph "$icon")" \
--argjson paired "$paired" --argjson connected "$connected" --arg battery "$battery" \
'{mac: $mac, name: $name, glyph: $glyph, paired: $paired, connected: $connected,
battery: (if $battery == "" then "" else $battery + "%" end),
sub: (if $connected then "connected" elif $paired then "paired" else "tap to pair" end)}'
}
list() {
local on=false discovering=false paired="[]" nearby="[]" mac
if powered; then
on=true
bluetoothctl show 2>/dev/null | grep -q 'Discovering: yes' && discovering=true
paired=$(bluetoothctl devices Paired 2>/dev/null | awk '{ print $2 }' | grep -E '^([0-9A-F]{2}:){5}[0-9A-F]{2}$' |
while read -r mac; do device_json "$mac"; done | jq -cs 'sort_by(.connected | not)')
nearby=$(comm -23 <(bluetoothctl devices 2>/dev/null | awk '{ print $2 }' | sort) \
<(bluetoothctl devices Paired 2>/dev/null | awk '{ print $2 }' | sort) |
grep -E '^([0-9A-F]{2}:){5}[0-9A-F]{2}$' | head -n 8 |
while read -r mac; do device_json "$mac"; done | jq -cs '[.[] | select(.name != .mac)]')
fi
jq -cn --argjson powered "$on" --argjson discovering "$discovering" \
--argjson paired "$paired" --argjson nearby "$nearby" \
'{powered: $powered, discovering: $discovering, paired: $paired, nearby: $nearby,
connected: ([$paired[] | select(.connected)] | length)}'
}
case "${1:-}" in
list) list ;;
power)
case "${2:-toggle}" in
on) rfkill unblock bluetooth 2>/dev/null; bluetoothctl power on >/dev/null ;;
off) bluetoothctl power off >/dev/null ;;
*) if powered; then bluetoothctl power off >/dev/null; else rfkill unblock bluetooth 2>/dev/null; bluetoothctl power on >/dev/null; fi ;;
esac
poke ;;
scan)
powered || bluetoothctl power on >/dev/null
setsid -f bluetoothctl --timeout 15 scan on >/dev/null 2>&1
poke ;;
toggle)
mac_ok "${2:-}"; mac="$2"
info=$(bluetoothctl info "$mac" 2>/dev/null)
name=$(sed -n 's/^\s*Alias: //p' <<<"$info" | head -n1)
if grep -q 'Connected: yes' <<<"$info"; then
bluetoothctl disconnect "$mac" >/dev/null && say "Disconnected" "$name"
else
if ! grep -q 'Paired: yes' <<<"$info"; then
bluetoothctl --timeout 20 pair "$mac" >/dev/null 2>&1 || { say "Pairing failed" "$name"; exit 1; }
bluetoothctl trust "$mac" >/dev/null
fi
bluetoothctl --timeout 15 connect "$mac" >/dev/null 2>&1 && say "Connected" "$name" || say "Could not connect" "$name"
fi
poke ;;
forget)
mac_ok "${2:-}"
bluetoothctl remove "$2" >/dev/null && say "Forgot device" "$2"
poke ;;
*) sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//'; exit 2 ;;
esac