z_mirror/dotfiles

git clone https://git.raiguard.me/z_mirror/dotfiles

Caleb HeuerRevert "Trying out tofi"9b06fc2

tangere
7.6 KiB317 linesraw
1#!/usr/bin/env bash
2#      _                                  _     _            _              _    _
3#   __| |_ __ ___   ___ _ __  _   _      | |__ | |_   _  ___| |_ ___   ___ | |_ | |__
4#  / _` | '_ ` _ \ / _ \ '_ \| | | |_____| '_ \| | | | |/ _ \ __/ _ \ / _ \| __|| '_ \
5# | (_| | | | | | |  __/ | | | |_| |_____| |_) | | |_| |  __/ || (_) | (_) | |_ | | | |
6#  \__,_|_| |_| |_|\___|_| |_|\__,_|     |_.__/|_|\__,_|\___|\__\___/ \___/ \__||_| |_|
7#
8# Author: Nick Clyde (clydedroid)
9# dmenu support by: Layerex
10#
11# A script that generates a dmenu menu that uses bluetoothctl to
12# connect to bluetooth devices and display status info.
13#
14# Inspired by networkmanager-dmenu (https://github.com/firecat53/networkmanager-dmenu)
15# Thanks to x70b1 (https://github.com/polybar/polybar-scripts/tree/master/polybar-scripts/system-bluetooth-bluetoothctl)
16#
17# Depends on:
18#   Arch repositories: dmenu, bluez-utils (contains bluetoothctl)
19
20# Constants
21divider="---------"
22goback="Back"
23
24# Checks if bluetooth controller is powered on
25power_on() {
26    if bluetoothctl show | grep -F -q "Powered: yes"; then
27        return 0
28    else
29        return 1
30    fi
31}
32
33# Toggles power state
34toggle_power() {
35    if power_on; then
36        bluetoothctl power off
37        show_menu
38    else
39        if rfkill list bluetooth | grep -F -q 'blocked: yes'; then
40            rfkill unblock bluetooth && sleep 3
41        fi
42        bluetoothctl power on
43        show_menu
44    fi
45}
46
47# Checks if controller is scanning for new devices
48scan_on() {
49    if bluetoothctl show | grep -F -q "Discovering: yes"; then
50        echo "Scan: on"
51        return 0
52    else
53        echo "Scan: off"
54        return 1
55    fi
56}
57
58# Toggles scanning state
59toggle_scan() {
60    if scan_on; then
61        kill "$(pgrep -F -f "bluetoothctl scan on")"
62        bluetoothctl scan off
63        show_menu
64    else
65        bluetoothctl scan on &
66        echo "Scanning..."
67        sleep 5
68        show_menu
69    fi
70}
71
72# Checks if controller is able to pair to devices
73pairable_on() {
74    if bluetoothctl show | grep -F -q "Pairable: yes"; then
75        echo "Pairable: on"
76        return 0
77    else
78        echo "Pairable: off"
79        return 1
80    fi
81}
82
83# Toggles pairable state
84toggle_pairable() {
85    if pairable_on; then
86        bluetoothctl pairable off
87        show_menu
88    else
89        bluetoothctl pairable on
90        show_menu
91    fi
92}
93
94# Checks if controller is discoverable by other devices
95discoverable_on() {
96    if bluetoothctl show | grep -F -q "Discoverable: yes"; then
97        echo "Discoverable: on"
98        return 0
99    else
100        echo "Discoverable: off"
101        return 1
102    fi
103}
104
105# Toggles discoverable state
106toggle_discoverable() {
107    if discoverable_on; then
108        bluetoothctl discoverable off
109        show_menu
110    else
111        bluetoothctl discoverable on
112        show_menu
113    fi
114}
115
116# Checks if a device is connected
117device_connected() {
118    device_info=$(bluetoothctl info "$1")
119    if echo "$device_info" | grep -F -q "Connected: yes"; then
120        return 0
121    else
122        return 1
123    fi
124}
125
126# Toggles device connection
127toggle_connection() {
128    if device_connected "$1"; then
129        bluetoothctl disconnect "$1"
130        # device_menu "$device"
131    else
132        bluetoothctl connect "$1"
133        # device_menu "$device"
134    fi
135}
136
137# Checks if a device is paired
138device_paired() {
139    device_info=$(bluetoothctl info "$1")
140    if echo "$device_info" | grep -F -q "Paired: yes"; then
141        echo "Paired: yes"
142        return 0
143    else
144        echo "Paired: no"
145        return 1
146    fi
147}
148
149# Toggles device paired state
150toggle_paired() {
151    if device_paired "$1"; then
152        bluetoothctl remove "$1"
153        device_menu "$device"
154    else
155        bluetoothctl pair "$1"
156        device_menu "$device"
157    fi
158}
159
160# Checks if a device is trusted
161device_trusted() {
162    device_info=$(bluetoothctl info "$1")
163    if echo "$device_info" | grep -F -q "Trusted: yes"; then
164        echo "Trusted: yes"
165        return 0
166    else
167        echo "Trusted: no"
168        return 1
169    fi
170}
171
172# Toggles device connection
173toggle_trust() {
174    if device_trusted "$1"; then
175        bluetoothctl untrust "$1"
176        device_menu "$device"
177    else
178        bluetoothctl trust "$1"
179        device_menu "$device"
180    fi
181}
182
183# Prints a short string with the current bluetooth status
184# Useful for status bars like polybar, etc.
185print_status() {
186    if power_on; then
187        printf ''
188
189        mapfile -t paired_devices < <(bluetoothctl paired-devices | grep -F Device | cut -d ' ' -f 2)
190        counter=0
191
192        for device in "${paired_devices[@]}"; do
193            if device_connected "$device"; then
194                device_alias="$(bluetoothctl info "$device" | grep -F "Alias" | cut -d ' ' -f 2-)"
195
196                if [ $counter -gt 0 ]; then
197                    printf ", %s" "$device_alias"
198                else
199                    printf " %s" "$device_alias"
200                fi
201
202                ((counter++))
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    options="$connected\n$paired\n$trusted\n$divider\n$goback\nExit"
228
229    # Open dmenu menu, read chosen option
230    chosen="$(echo -e "$options" | run_dmenu "$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 dmenu 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 -F Device | cut -d ' ' -f 3-)
261
262        # Get controller flags
263        scan=$(scan_on)
264        pairable=$(pairable_on)
265        discoverable=$(discoverable_on)
266
267        # Options passed to dmenu
268        options="$devices\n$divider\n$power\n$scan\n$pairable\n$discoverable\nExit"
269    else
270        power="Power: off"
271        options="$power\nExit"
272    fi
273
274    # Open dmenu menu, read chosen option
275    chosen="$(echo -e "$options" | run_dmenu "Bluetooth")"
276
277    # Match chosen option to command
278    case $chosen in
279        "" | "$divider")
280            echo "No option chosen."
281            ;;
282        "$power")
283            toggle_power
284            ;;
285        "$scan")
286            toggle_scan
287            ;;
288        "$discoverable")
289            toggle_discoverable
290            ;;
291        "$pairable")
292            toggle_pairable
293            ;;
294        *)
295            device=$(bluetoothctl devices | grep -F "$chosen")
296            # Open a submenu if a device is selected
297            if [[ $device ]]; then device_menu "$device"; fi
298            ;;
299    esac
300}
301
302original_args=("$@")
303
304# dmenu command to pipe into. Extra arguments to dmenu-bluetooth are passed through to dmenu. This
305# allows the user to set fonts, sizes, colours, etc.
306run_dmenu() {
307    fuzzel -d "${original_args[@]}" -p "$1"
308}
309
310case "$1" in
311    --status)
312        print_status
313        ;;
314    *)
315        show_menu
316        ;;
317esac