z_mirror/dotfiles
git clone https://git.raiguard.me/z_mirror/dotfiles
9b06fc2
noctalia
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