From 6a39613d42dae91bed00db67b017689a61a66366 Mon Sep 17 00:00:00 2001 From: mzeinali Date: Thu, 21 Jul 2022 02:43:29 +0430 Subject: [PATCH 1/4] Add bluetooth script --- .local/bin/dmenubluetooth | 308 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100755 .local/bin/dmenubluetooth diff --git a/.local/bin/dmenubluetooth b/.local/bin/dmenubluetooth new file mode 100755 index 00000000..d624738f --- /dev/null +++ b/.local/bin/dmenubluetooth @@ -0,0 +1,308 @@ +#!/usr/bin/env bash +# +# Author: Nick Clyde (clydedroid) +# +# A script that generates a that uses bluetoothctl with dmenu to +# connect to bluetooth devices and display status info. +# +# Inspired by networkmanager-dmenu (https://github.com/firecat53/networkmanager-dmenu) +# Thanks to x70b1 (https://github.com/polybar/polybar-scripts/tree/master/polybar-scripts/system-bluetooth-bluetoothctl) +# +# Depends on: +# Arch repositories: dmenu, bluez-utils (contains bluetoothctl) +# This is a modification of rofi-bluetooth script to work with dmenu +# Original script: https://github.com/nickclyde/rofi-bluetooth + +# Constants +divider="<🔗-⚒>" +goback="Back" + +# Checks if bluetooth controller is powered on +power_on() { + if bluetoothctl show | grep -q "Powered: yes"; then + return 0 + else + return 1 + fi +} + +# Toggles power state +toggle_power() { + if power_on; then + bluetoothctl power off + show_menu + else + if rfkill list bluetooth | grep -q 'blocked: yes'; then + rfkill unblock bluetooth && sleep 3 + fi + bluetoothctl power on + show_menu + fi +} + +# Checks if controller is scanning for new devices +scan_on() { + if bluetoothctl show | grep -q "Discovering: yes"; then + echo "Scan: on" + return 0 + else + echo "Scan: off" + return 1 + fi +} + +# Toggles scanning state +toggle_scan() { + if scan_on; then + kill $(pgrep -f "bluetoothctl scan on") + bluetoothctl scan off + show_menu + else + bluetoothctl scan on & + echo "Scanning..." + sleep 5 + show_menu + fi +} + +# Checks if controller is able to pair to devices +pairable_on() { + if bluetoothctl show | grep -q "Pairable: yes"; then + echo "Pairable: on" + return 0 + else + echo "Pairable: off" + return 1 + fi +} + +# Toggles pairable state +toggle_pairable() { + if pairable_on; then + bluetoothctl pairable off + show_menu + else + bluetoothctl pairable on + show_menu + fi +} + +# Checks if controller is discoverable by other devices +discoverable_on() { + if bluetoothctl show | grep -q "Discoverable: yes"; then + echo "Discoverable: on" + return 0 + else + echo "Discoverable: off" + return 1 + fi +} + +# Toggles discoverable state +toggle_discoverable() { + if discoverable_on; then + bluetoothctl discoverable off + show_menu + else + bluetoothctl discoverable on + show_menu + fi +} + +# Checks if a device is connected +device_connected() { + device_info=$(bluetoothctl info "$1") + if echo "$device_info" | grep -q "Connected: yes"; then + return 0 + else + return 1 + fi +} + +# Toggles device connection +toggle_connection() { + if device_connected $1; then + bluetoothctl disconnect $1 + device_menu "$device" + else + bluetoothctl connect $1 + device_menu "$device" + fi +} + +# Checks if a device is paired +device_paired() { + device_info=$(bluetoothctl info "$1") + if echo "$device_info" | grep -q "Paired: yes"; then + echo "Paired: yes" + return 0 + else + echo "Paired: no" + return 1 + fi +} + +# Toggles device paired state +toggle_paired() { + if device_paired $1; then + bluetoothctl remove $1 + device_menu "$device" + else + bluetoothctl pair $1 + device_menu "$device" + fi +} + +# Checks if a device is trusted +device_trusted() { + device_info=$(bluetoothctl info "$1") + if echo "$device_info" | grep -q "Trusted: yes"; then + echo "Trusted: yes" + return 0 + else + echo "Trusted: no" + return 1 + fi +} + +# Toggles device connection +toggle_trust() { + if device_trusted $1; then + bluetoothctl untrust $1 + device_menu "$device" + else + bluetoothctl trust $1 + device_menu "$device" + fi +} + +# Prints a short string with the current bluetooth status +# Useful for status bars like polybar, etc. +print_status() { + if power_on; then + printf '' + + mapfile -t paired_devices < <(bluetoothctl paired-devices | grep Device | cut -d ' ' -f 2) + counter=0 + + for device in "${paired_devices[@]}"; do + if device_connected $device; then + device_alias=$(bluetoothctl info $device | grep "Alias" | cut -d ' ' -f 2-) + + if [ $counter -gt 0 ]; then + printf ", %s" "$device_alias" + else + printf " %s" "$device_alias" + fi + + ((counter++)) + fi + done + printf "\n" + else + echo "" + fi +} + +# A submenu for a specific device that allows connecting, pairing, and trusting +device_menu() { + device=$1 + + # Get device name and mac address + device_name=$(echo $device | cut -d ' ' -f 3-) + mac=$(echo $device | cut -d ' ' -f 2) + + # Build options + if device_connected $mac; then + connected="Connected: yes" + else + connected="Connected: no" + fi + paired=$(device_paired $mac) + trusted=$(device_trusted $mac) + options="$connected\n$paired\n$trusted\n$divider\n$goback\nExit" + + # Open dmenu, read chosen option + chosen="$(echo -e "$options" | $dmenu_command "$device_name")" + + # Match chosen option to command + case $chosen in + "" | $divider) + echo "No option chosen." + ;; + $connected) + toggle_connection $mac + ;; + $paired) + toggle_paired $mac + ;; + $trusted) + toggle_trust $mac + ;; + $goback) + show_menu + ;; + esac +} + +# Opens dmenu with current bluetooth status and options to connect +show_menu() { + # Get menu options + if power_on; then + power="Power: on" + + # Human-readable names of devices, one per line + # If scan is off, will only list paired devices + devices=$(bluetoothctl devices | grep Device | cut -d ' ' -f 3-) + + # Get controller flags + scan=$(scan_on) + pairable=$(pairable_on) + discoverable=$(discoverable_on) + + # Options passed to dmenu + options="$devices\n$divider\n$power\n$scan\n$pairable\n$discoverable\nExit" + else + power="Power: off" + options="$power\nExit" + fi + + # Open dmenu, read chosen option + chosen="$(echo -e "$options" | $dmenu_command "Bluetooth")" + + # Match chosen option to command + case $chosen in + "" | $divider) + echo "No option chosen." + ;; + $power) + toggle_power + ;; + $scan) + toggle_scan + ;; + $discoverable) + toggle_discoverable + ;; + $pairable) + toggle_pairable + ;; + *) + device=$(bluetoothctl devices | grep "$chosen") + # Open a submenu if a device is selected + if [[ $device ]]; then device_menu "$device"; fi + ;; + esac +} + +# Dmenu command to pipe into, can add any options here +dmenu_command="dmenu -i -p" + +case "$1" in + --status) + print_status + ;; + *) + show_menu + ;; +esac From 89345a4a9bd9e8cb954a42f8b13f42cac315c7dd Mon Sep 17 00:00:00 2001 From: appeasementPolitik <108810900+appeasementPolitik@users.noreply.github.com> Date: Mon, 12 Sep 2022 19:46:21 +0000 Subject: [PATCH 2/4] Rewrite to POSIX sh --- .local/bin/dmenubluetooth | 342 ++++++++++++++------------------------ 1 file changed, 121 insertions(+), 221 deletions(-) diff --git a/.local/bin/dmenubluetooth b/.local/bin/dmenubluetooth index d624738f..ee2e4090 100755 --- a/.local/bin/dmenubluetooth +++ b/.local/bin/dmenubluetooth @@ -1,8 +1,8 @@ -#!/usr/bin/env bash +#!/bin/sh # # Author: Nick Clyde (clydedroid) # -# A script that generates a that uses bluetoothctl with dmenu to +# A script that generates a dmenu prompt that uses bluetoothctl to # connect to bluetooth devices and display status info. # # Inspired by networkmanager-dmenu (https://github.com/firecat53/networkmanager-dmenu) @@ -10,299 +10,199 @@ # # Depends on: # Arch repositories: dmenu, bluez-utils (contains bluetoothctl) -# This is a modification of rofi-bluetooth script to work with dmenu +# This is a modification of rofi-bluetooth script to work with dmenu # Original script: https://github.com/nickclyde/rofi-bluetooth # Constants -divider="<🔗-⚒>" -goback="Back" +divider='<🔗-⚒>' +goback='Back' + +# Dmenu command to pipe into, can add any options here +dmenu_command='dmenu -i -p' # Checks if bluetooth controller is powered on power_on() { - if bluetoothctl show | grep -q "Powered: yes"; then - return 0 - else - return 1 - fi + bluetoothctl show | grep -q 'Powered: yes' && return 0 || return 1 } # Toggles power state toggle_power() { - if power_on; then - bluetoothctl power off - show_menu - else - if rfkill list bluetooth | grep -q 'blocked: yes'; then - rfkill unblock bluetooth && sleep 3 - fi - bluetoothctl power on - show_menu - fi + if power_on; then + bluetoothctl power off + show_menu + else + rfkill list bluetooth | grep -q 'blocked: yes' && rfkill unblock bluetooth && sleep 3 + + bluetoothctl power on + show_menu + fi } # Checks if controller is scanning for new devices scan_on() { - if bluetoothctl show | grep -q "Discovering: yes"; then - echo "Scan: on" - return 0 - else - echo "Scan: off" - return 1 - fi + bluetoothctl show | grep -q 'Discovering: yes' && + echo 'Scan: on' && return 0 || + { echo 'Scan: off' && return 1; } } # Toggles scanning state toggle_scan() { - if scan_on; then - kill $(pgrep -f "bluetoothctl scan on") - bluetoothctl scan off - show_menu - else - bluetoothctl scan on & - echo "Scanning..." - sleep 5 - show_menu - fi + scan_on && + kill "$(pgrep -f 'bluetoothctl scan on')" && bluetoothctl scan off && show_menu || + { bluetoothctl scan on & echo 'Scanning...' && sleep 5 && show_menu; } } # Checks if controller is able to pair to devices pairable_on() { - if bluetoothctl show | grep -q "Pairable: yes"; then - echo "Pairable: on" - return 0 - else - echo "Pairable: off" - return 1 - fi + bluetoothctl show | grep -q 'Pairable: yes' && + echo 'Pairable: on' && return 0 || + { echo 'Pairable: off' && return 1; } } # Toggles pairable state toggle_pairable() { - if pairable_on; then - bluetoothctl pairable off - show_menu - else - bluetoothctl pairable on - show_menu - fi + pairable_on && + bluetoothctl pairable off && show_menu || + { bluetoothctl pairable on && show_menu; } } # Checks if controller is discoverable by other devices discoverable_on() { - if bluetoothctl show | grep -q "Discoverable: yes"; then - echo "Discoverable: on" - return 0 - else - echo "Discoverable: off" - return 1 - fi + bluetoothctl show | grep -q 'Discoverable: yes' && + echo 'Discoverable: on' && return 0 || + { echo 'Discoverable: off' && return 1; } } # Toggles discoverable state toggle_discoverable() { - if discoverable_on; then - bluetoothctl discoverable off - show_menu - else - bluetoothctl discoverable on - show_menu - fi + discoverable_on && + bluetoothctl discoverable off && show_menu || + { bluetoothctl discoverable on && show_menu; } } # Checks if a device is connected device_connected() { - device_info=$(bluetoothctl info "$1") - if echo "$device_info" | grep -q "Connected: yes"; then - return 0 - else - return 1 - fi + device_info=$(bluetoothctl info "$1") + + echo "$device_info" | grep -q 'Connected: yes' && return 0 || return 1 } # Toggles device connection toggle_connection() { - if device_connected $1; then - bluetoothctl disconnect $1 - device_menu "$device" - else - bluetoothctl connect $1 - device_menu "$device" - fi + device_connected "$1" && + bluetoothctl disconnect "$1" && device_menu "$device" || + { bluetoothctl connect "$1" && device_menu "$device"; } } # Checks if a device is paired device_paired() { - device_info=$(bluetoothctl info "$1") - if echo "$device_info" | grep -q "Paired: yes"; then - echo "Paired: yes" - return 0 - else - echo "Paired: no" - return 1 - fi + device_info=$(bluetoothctl info "$1") + + echo "$device_info" | grep -q 'Paired: yes' && + echo 'Paired: yes' && return 0 || + { echo 'Paired: no' && return 1; } } # Toggles device paired state toggle_paired() { - if device_paired $1; then - bluetoothctl remove $1 - device_menu "$device" - else - bluetoothctl pair $1 - device_menu "$device" - fi + device_paired "$1" && + bluetoothctl remove "$1" && device_menu "$device" || + { bluetoothctl pair "$1" && device_menu "$device"; } } # Checks if a device is trusted device_trusted() { - device_info=$(bluetoothctl info "$1") - if echo "$device_info" | grep -q "Trusted: yes"; then - echo "Trusted: yes" - return 0 - else - echo "Trusted: no" - return 1 - fi + device_info=$(bluetoothctl info "$1") + + echo "$device_info" | grep -q 'Trusted: yes' && + echo 'Trusted: yes' && return 0 || + { echo 'Trusted: no' && return 1; } } # Toggles device connection toggle_trust() { - if device_trusted $1; then - bluetoothctl untrust $1 - device_menu "$device" - else - bluetoothctl trust $1 - device_menu "$device" - fi -} - -# Prints a short string with the current bluetooth status -# Useful for status bars like polybar, etc. -print_status() { - if power_on; then - printf '' - - mapfile -t paired_devices < <(bluetoothctl paired-devices | grep Device | cut -d ' ' -f 2) - counter=0 - - for device in "${paired_devices[@]}"; do - if device_connected $device; then - device_alias=$(bluetoothctl info $device | grep "Alias" | cut -d ' ' -f 2-) - - if [ $counter -gt 0 ]; then - printf ", %s" "$device_alias" - else - printf " %s" "$device_alias" - fi - - ((counter++)) - fi - done - printf "\n" - else - echo "" - fi + device_trusted "$1" && + bluetoothctl untrust "$1" && device_menu "$device" || + { bluetoothctl trust "$1" && device_menu "$device"; } } # A submenu for a specific device that allows connecting, pairing, and trusting device_menu() { - device=$1 + device=$1 - # Get device name and mac address - device_name=$(echo $device | cut -d ' ' -f 3-) - mac=$(echo $device | cut -d ' ' -f 2) + # Get device name and mac address + device_name=$(echo "$device" | cut -d ' ' -f 3-) + mac=$(echo "$device" | cut -d ' ' -f 2) - # Build options - if device_connected $mac; then - connected="Connected: yes" - else - connected="Connected: no" - fi - paired=$(device_paired $mac) - trusted=$(device_trusted $mac) - options="$connected\n$paired\n$trusted\n$divider\n$goback\nExit" + # Build options + device_connected "$mac" && + connected='Connected: yes' || + connected='Connected: no' - # Open dmenu, read chosen option - chosen="$(echo -e "$options" | $dmenu_command "$device_name")" + paired=$(device_paired "$mac") + trusted=$(device_trusted "$mac") + options="${connected}\n${paired}\n${trusted}\n${divider}\n${goback}\nExit" - # Match chosen option to command - case $chosen in - "" | $divider) - echo "No option chosen." - ;; - $connected) - toggle_connection $mac - ;; - $paired) - toggle_paired $mac - ;; - $trusted) - toggle_trust $mac - ;; - $goback) - show_menu - ;; - esac + # Open dmenu, read chosen option + chosen="$(printf '%b' "$options" | $dmenu_command "$device_name")" + + # Match chosen option to command + case $chosen in + "" | "$divider") + echo 'No option chosen.' ;; + "$connected") + toggle_connection "$mac" ;; + "$paired") + toggle_paired "$mac" ;; + "$trusted") + toggle_trust "$mac" ;; + "$goback") + show_menu ;; + esac } # Opens dmenu with current bluetooth status and options to connect show_menu() { - # Get menu options - if power_on; then - power="Power: on" + # Get menu options + if power_on; then + power='Power: on' - # Human-readable names of devices, one per line - # If scan is off, will only list paired devices - devices=$(bluetoothctl devices | grep Device | cut -d ' ' -f 3-) + # Human-readable names of devices, one per line + # If scan is off, will only list paired devices + devices=$(bluetoothctl devices | cut -d ' ' -f 3-) - # Get controller flags - scan=$(scan_on) - pairable=$(pairable_on) - discoverable=$(discoverable_on) + # Get controller flags + scan=$(scan_on) + pairable=$(pairable_on) + discoverable=$(discoverable_on) - # Options passed to dmenu - options="$devices\n$divider\n$power\n$scan\n$pairable\n$discoverable\nExit" - else - power="Power: off" - options="$power\nExit" - fi + # Options passed to dmenu + options="${devices}\n${divider}\n${power}\n${scan}\n${pairable}\n${discoverable}\nExit" + else + power='Power: off' + options="$power\nExit" + fi - # Open dmenu, read chosen option - chosen="$(echo -e "$options" | $dmenu_command "Bluetooth")" + # Open dmenu, read chosen option + chosen="$(printf '%b' "$options" | $dmenu_command 'Bluetooth')" - # Match chosen option to command - case $chosen in - "" | $divider) - echo "No option chosen." - ;; - $power) - toggle_power - ;; - $scan) - toggle_scan - ;; - $discoverable) - toggle_discoverable - ;; - $pairable) - toggle_pairable - ;; - *) - device=$(bluetoothctl devices | grep "$chosen") - # Open a submenu if a device is selected - if [[ $device ]]; then device_menu "$device"; fi - ;; - esac + # Match chosen option to command + case $chosen in + "" | "$divider") + echo 'No option chosen.' ;; + "$power") + toggle_power ;; + "$scan") + toggle_scan ;; + "$discoverable") + toggle_discoverable ;; + "$pairable") + toggle_pairable ;; + *) + device=$(bluetoothctl devices | grep "$chosen") + # Open a submenu if a device is selected + [ -n "$device" ] && device_menu "$device" ;; + esac } -# Dmenu command to pipe into, can add any options here -dmenu_command="dmenu -i -p" - -case "$1" in - --status) - print_status - ;; - *) - show_menu - ;; -esac +show_menu From 930dd4e574a223d51bc8f974eb302b5c86b04f02 Mon Sep 17 00:00:00 2001 From: appeasementPolitik <108810900+appeasementPolitik@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:17:39 +0000 Subject: [PATCH 3/4] Compatibility with dwmblocks, and some extra improvements --- .local/bin/dmenubluetooth | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.local/bin/dmenubluetooth b/.local/bin/dmenubluetooth index ee2e4090..8d56765f 100755 --- a/.local/bin/dmenubluetooth +++ b/.local/bin/dmenubluetooth @@ -29,11 +29,13 @@ power_on() { toggle_power() { if power_on; then bluetoothctl power off + pkill -RTMIN+2 "${STATUSBAR:-dwmblocks}" show_menu else rfkill list bluetooth | grep -q 'blocked: yes' && rfkill unblock bluetooth && sleep 3 bluetoothctl power on + pkill -RTMIN+2 "${STATUSBAR:-dwmblocks}" show_menu fi } @@ -48,8 +50,8 @@ scan_on() { # Toggles scanning state toggle_scan() { scan_on && - kill "$(pgrep -f 'bluetoothctl scan on')" && bluetoothctl scan off && show_menu || - { bluetoothctl scan on & echo 'Scanning...' && sleep 5 && show_menu; } + pkill -f 'bluetoothctl scan on' && bluetoothctl scan off && show_menu || + { bluetoothctl scan on & notify-send 'Scanning...' && sleep 5 && show_menu; } } # Checks if controller is able to pair to devices @@ -108,6 +110,8 @@ toggle_paired() { device_paired "$1" && bluetoothctl remove "$1" && device_menu "$device" || { bluetoothctl pair "$1" && device_menu "$device"; } + + pkill -RTMIN+2 "${STATUSBAR:-dwmblocks}" } # Checks if a device is trusted @@ -141,15 +145,13 @@ device_menu() { paired=$(device_paired "$mac") trusted=$(device_trusted "$mac") - options="${connected}\n${paired}\n${trusted}\n${divider}\n${goback}\nExit" + options="${connected}\n${paired}\n${trusted}\n${goback}\nExit" # Open dmenu, read chosen option chosen="$(printf '%b' "$options" | $dmenu_command "$device_name")" # Match chosen option to command case $chosen in - "" | "$divider") - echo 'No option chosen.' ;; "$connected") toggle_connection "$mac" ;; "$paired") @@ -158,6 +160,8 @@ device_menu() { toggle_trust "$mac" ;; "$goback") show_menu ;; + *) + exit ;; esac } @@ -177,7 +181,7 @@ show_menu() { discoverable=$(discoverable_on) # Options passed to dmenu - options="${devices}\n${divider}\n${power}\n${scan}\n${pairable}\n${discoverable}\nExit" + options="${devices:+$devices\n$divider\n}${power}\n${scan}\n${pairable}\n${discoverable}\nExit" else power='Power: off' options="$power\nExit" @@ -188,8 +192,8 @@ show_menu() { # Match chosen option to command case $chosen in - "" | "$divider") - echo 'No option chosen.' ;; + "" | "$divider" | 'Exit') + exit ;; "$power") toggle_power ;; "$scan") From bf6bf683cec73e07e02a70c980c4537cf4797cd1 Mon Sep 17 00:00:00 2001 From: appeasementPolitik <108810900+appeasementPolitik@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:20:38 +0000 Subject: [PATCH 4/4] Add sb-bluetooth script --- .local/bin/statusbar/sb-bluetooth | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .local/bin/statusbar/sb-bluetooth diff --git a/.local/bin/statusbar/sb-bluetooth b/.local/bin/statusbar/sb-bluetooth new file mode 100644 index 00000000..b818baa1 --- /dev/null +++ b/.local/bin/statusbar/sb-bluetooth @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Shows names of paired and connected bluetooth devices if bluetooth is on + +case $BLOCK_BUTTON in + 1) dmenubluetooth; pkill -RTMIN+2 dwmblocks ;; + 3) notify-send " Bluetooth module" "\- Shows paired devices. +- Click to configure bluetooth." ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +if bluetoothctl show | grep -q 'Powered: yes'; then + printf '' + + i=0; while IFS= read -r device; do + if bluetoothctl info "$device" | grep -q 'Connected: yes'; then + device_alias=$(bluetoothctl info "$device" | grep 'Alias' | cut -d ' ' -f 2-) + + [ $i = 0 ] && + printf "$device_alias" || + printf ', %s' "$device_alias" + + i=$((i + 1)) + fi + done <<-EOT + $(bluetoothctl devices Paired | cut -d ' ' -f 2) + EOT + + printf "\n" +else + echo '' +fi