dotfiles

Alpine Linux dotfiles

git clone git://git.lin.moe/dotfiles.git

  1#!/bin/sh
  2#             __ _       _     _            _              _   _
  3#  _ __ ___  / _(_)     | |__ | |_   _  ___| |_ ___   ___ | |_| |__
  4# | '__/ _ \| |_| |_____| '_ \| | | | |/ _ \ __/ _ \ / _ \| __| '_ \
  5# | | | (_) |  _| |_____| |_) | | |_| |  __/ || (_) | (_) | |_| | | |
  6# |_|  \___/|_| |_|     |_.__/|_|\__,_|\___|\__\___/ \___/ \__|_| |_|
  7#
  8# Author: Nick Clyde (clydedroid)
  9#
 10# A script that generates a rofi menu that uses bluetoothctl to
 11# connect to bluetooth devices and display status info.
 12#
 13# Inspired by networkmanager-dmenu (https://github.com/firecat53/networkmanager-dmenu)
 14# Thanks to x70b1 (https://github.com/polybar/polybar-scripts/tree/master/polybar-scripts/system-bluetooth-bluetoothctl)
 15#
 16# Depends on:
 17#   Arch repositories: rofi, bluez-utils (contains bluetoothctl), bc
 18
 19# Constants
 20divider="---------"
 21goback="Back"
 22
 23# Checks if bluetooth controller is powered on
 24power_on() {
 25    if bluetoothctl show | grep -q "Powered: yes"; then
 26        return 0
 27    else
 28        return 1
 29    fi
 30}
 31
 32# Toggles power state
 33toggle_power() {
 34    if power_on; then
 35        bluetoothctl power off
 36        show_menu
 37    else
 38        if rfkill list bluetooth | grep -q 'blocked: yes'; then
 39            rfkill unblock bluetooth && sleep 3
 40        fi
 41        bluetoothctl power on
 42        show_menu
 43    fi
 44}
 45
 46# Checks if controller is scanning for new devices
 47scan_on() {
 48    if bluetoothctl show | grep -q "Discovering: yes"; then
 49        echo "Scan: on"
 50        return 0
 51    else
 52        echo "Scan: off"
 53        return 1
 54    fi
 55}
 56
 57# Toggles scanning state
 58toggle_scan() {
 59    if scan_on; then
 60        kill $(pgrep -f "bluetoothctl --timeout 5 scan on")
 61        bluetoothctl scan off
 62        show_menu
 63    else
 64        bluetoothctl --timeout 5 scan on
 65        echo "Scanning..."
 66        show_menu
 67    fi
 68}
 69
 70# Checks if controller is able to pair to devices
 71pairable_on() {
 72    if bluetoothctl show | grep -q "Pairable: yes"; then
 73        echo "Pairable: on"
 74        return 0
 75    else
 76        echo "Pairable: off"
 77        return 1
 78    fi
 79}
 80
 81# Toggles pairable state
 82toggle_pairable() {
 83    if pairable_on; then
 84        bluetoothctl pairable off
 85        show_menu
 86    else
 87        bluetoothctl pairable on
 88        show_menu
 89    fi
 90}
 91
 92# Checks if controller is discoverable by other devices
 93discoverable_on() {
 94    if bluetoothctl show | grep -q "Discoverable: yes"; then
 95        echo "Discoverable: on"
 96        return 0
 97    else
 98        echo "Discoverable: off"
 99        return 1
100    fi
101}
102
103# Toggles discoverable state
104toggle_discoverable() {
105    if discoverable_on; then
106        bluetoothctl discoverable off
107        show_menu
108    else
109        bluetoothctl discoverable on
110        show_menu
111    fi
112}
113
114# Checks if a device is connected
115device_connected() {
116    device_info=$(bluetoothctl info "$1")
117    if echo "$device_info" | grep -q "Connected: yes"; then
118        return 0
119    else
120        return 1
121    fi
122}
123
124# Toggles device connection
125toggle_connection() {
126    if device_connected "$1"; then
127        bluetoothctl disconnect "$1"
128        device_menu "$device"
129    else
130        bluetoothctl connect "$1"
131        device_menu "$device"
132    fi
133}
134
135# Checks if a device is paired
136device_paired() {
137    device_info=$(bluetoothctl info "$1")
138    if echo "$device_info" | grep -q "Paired: yes"; then
139        echo "Paired: yes"
140        return 0
141    else
142        echo "Paired: no"
143        return 1
144    fi
145}
146
147# Toggles device paired state
148toggle_paired() {
149    if device_paired "$1"; then
150        bluetoothctl remove "$1"
151        device_menu "$device"
152    else
153        bluetoothctl pair "$1"
154        device_menu "$device"
155    fi
156}
157
158# Checks if a device is trusted
159device_trusted() {
160    device_info=$(bluetoothctl info "$1")
161    if echo "$device_info" | grep -q "Trusted: yes"; then
162        echo "Trusted: yes"
163        return 0
164    else
165        echo "Trusted: no"
166        return 1
167    fi
168}
169
170# Toggles device connection
171toggle_trust() {
172    if device_trusted "$1"; then
173        bluetoothctl untrust "$1"
174        device_menu "$device"
175    else
176        bluetoothctl trust "$1"
177        device_menu "$device"
178    fi
179}
180
181# Backwards-compatible function to print paired devices.
182paired_devices() {
183    if [ -n "$(bluetoothctl version | cut -d ' ' -f 2 | awk -F. '($1 > 5 || $1 == 5 && $2 > 64)')" ]; then
184        bluetoothctl devices Paired
185    else
186        bluetoothctl paired-devices
187    fi
188}
189
190
191# Prints a short string with the current bluetooth status
192# Useful for status bars like polybar, etc.
193print_status() {
194    if power_on; then
195        printf ''
196        sep=""
197        paired_devices | grep Device | cut -d ' ' -f 2 |
198        while IFS= read -r device; do
199            if device_connected "$device"; then
200                device_alias=$(bluetoothctl info "$device" | grep "Alias" | cut -d ' ' -f 2-)
201                printf "$sep %s" "$device_alias"
202                sep=","
203            fi
204        done
205        printf "\n"
206    else
207        echo ""
208    fi
209}
210
211# A submenu for a specific device that allows connecting, pairing, and trusting
212device_menu() {
213    device=$1
214
215    # Get device name and mac address
216    device_name=$(echo "$device" | cut -d ' ' -f 3-)
217    mac=$(echo "$device" | cut -d ' ' -f 2)
218
219    # Build options
220    if device_connected "$mac"; then
221        connected="Connected: yes"
222    else
223        connected="Connected: no"
224    fi
225    paired=$(device_paired "$mac")
226    trusted=$(device_trusted "$mac")
227
228    # Open rofi menu, read chosen option
229    chosen="$(printf "%s\n%s\n%s\n%s\n%s\nExit\n" "$connected" "$paired" "$trusted" "$divider" "$goback" \
230        | $rofi_command "$device_name")"
231
232    # Match chosen option to command
233    case "$chosen" in
234        "" | "$divider")
235            echo "No option chosen."
236            ;;
237        "$connected")
238            toggle_connection "$mac"
239            ;;
240        "$paired")
241            toggle_paired "$mac"
242            ;;
243        "$trusted")
244            toggle_trust "$mac"
245            ;;
246        "$goback")
247            show_menu
248            ;;
249    esac
250}
251
252# Opens a rofi menu with current bluetooth status and options to connect
253show_menu() {
254    # Get menu options
255    if power_on; then
256        power="Power: on"
257
258        # Human-readable names of devices, one per line
259        # If scan is off, will only list paired devices
260        devices=$(bluetoothctl devices | grep Device | cut -d ' ' -f 3-)
261
262        # Get controller flags
263        scan=$(scan_on)
264        pairable=$(pairable_on)
265        discoverable=$(discoverable_on)
266
267        # Open rofi menu, read chosen option
268        chosen="$(printf "%s\n%s\n%s\n%s\n%s\n%s\nExit\n" \
269                  "$devices" "$divider" "$power" "$scan" "$pairable" "$discoverable" \
270                  | $rofi_command "Bluetooth")"
271    else
272        power="Power: off"
273        # Open rofi menu, read chosen option
274        chosen="$(printf "%s\nExit\n" "$power" | $rofi_command "Bluetooth")"
275    fi
276
277
278    # Match chosen option to command
279    case "$chosen" in
280        "" | "$divider")
281            echo "No option chosen."
282            ;;
283        "$power")
284            toggle_power
285            ;;
286        "$scan")
287            toggle_scan
288            ;;
289        "$discoverable")
290            toggle_discoverable
291            ;;
292        "$pairable")
293            toggle_pairable
294            ;;
295        *)
296            device=$(bluetoothctl devices | grep "$chosen")
297            # Open a submenu if a device is selected
298            if [ "$device" ]; then device_menu "$device"; fi
299            ;;
300    esac
301}
302
303# Rofi command to pipe into, can add any options here
304rofi_command="rofi -dmenu $* -p"
305
306case "$1" in
307    --status)
308        print_status
309        ;;
310    *)
311        show_menu
312        ;;
313esac