281 lines
10 KiB
Bash
Executable File
281 lines
10 KiB
Bash
Executable File
#!/bin/sh
|
|
#load config
|
|
. "${XDG_CONFIG_HOME:-$HOME/.config}/bt/config"
|
|
|
|
[ "$AUTOTRUST" = false ] && actions="$(printf '%s\ntrust\n' "$actions")"
|
|
|
|
power(){
|
|
powerstatus="$( bluetoothctl show | grep Powered | awk '{print $2}' )"
|
|
if [ "$powerstatus" = "no" ]; then
|
|
[ "$1" = on ] && bluetoothctl power on
|
|
elif [ "$powerstatus" = "yes" ]; then
|
|
[ "$1" = off ] && bluetoothctl power off
|
|
fi
|
|
}
|
|
|
|
scan(){
|
|
scanstatus="$( bluetoothctl show | grep Discovering | awk '{print $2}' )"
|
|
if [ "$1" = on ]; then
|
|
#sets variable in case scanning was no already on before the start of bt
|
|
[ -f /tmp/bt_start_scan$$ ] || start_scan="$( date +'%s' )"
|
|
if [ "$scanstatus" = "no" ]; then
|
|
bluetoothctl scan on &
|
|
start_scan="$( date +'%s' )"
|
|
fi
|
|
echo "$start_scan" > /tmp/bt_start_scan$$
|
|
elif [ "$1" = off ]; then
|
|
if [ "$scanstatus" = "yes" ]; then
|
|
bluetoothctl scan off
|
|
fi
|
|
fi
|
|
}
|
|
|
|
#Check bluetoothctl paired-devices for new devices to be hardcoded into pair list
|
|
update_pair_list(){
|
|
btctl_paired_devices="$(bluetoothctl paired-devices)"
|
|
if [ -n "$btctl_paired_devices" ]
|
|
then
|
|
btctl_not_in_list="$( echo "$btctl_paired_devices" | grep -vf "$PAIRLIST")"
|
|
[ -n "$btctl_not_in_list" ] && echo "$btctl_not_in_list" >> "$PAIRLIST"
|
|
fi
|
|
}
|
|
|
|
|
|
#start scanning as early as possible to speed up pairing process
|
|
startup(){
|
|
if $AUTOSCAN
|
|
then
|
|
power on
|
|
scan on > /dev/null
|
|
fi
|
|
}
|
|
|
|
|
|
if [ "$1" = "edit" ]; then
|
|
case $2 in
|
|
"pairlist")${EDITOR:-vim} "$PAIRLIST";;
|
|
"blacklist")${EDITOR:-vim} "$BLACKLIST";;
|
|
"aliaslist")${EDITOR:-vim} "$ALIASLIST";;
|
|
*)true;;
|
|
esac
|
|
exit
|
|
fi
|
|
#Sadly needs to be run without '&' for now, since it otherwise breaks start_scan variable
|
|
startup &
|
|
update_pair_list &
|
|
|
|
connected_ids="$(bluetoothctl devices | awk '{print "bluetoothctl info "$2}' | . /dev/stdin | grep -E '(^Device |Connected:)' | sed -e 'N;s/\n/;/' | grep 'Connected: yes' | cut -d' ' -f2,5)"
|
|
|
|
[ -z "$connected_ids" ] ||
|
|
connected_devices="$(echo "$connected_ids" | while read -r id; do
|
|
if grep -q "$id" "$ALIASLIST"; then
|
|
grep "$id" "$ALIASLIST" | cut -d' ' --complement -f1
|
|
else
|
|
grep "$id" "$PAIRLIST" | cut -d' ' --complement -f1,2
|
|
fi
|
|
done)"
|
|
|
|
[ -n "$include_disconnect_option" ] &&
|
|
[ -n "$connected_devices" ] &&
|
|
actions="$(printf "disconnect\n%s" "$actions")"
|
|
|
|
#Compile list of all Bluetooth IDS of paired devices (from bluetoothctl and from hardcoded list)
|
|
bt_IDS="$( ( bluetoothctl paired-devices && cat "$PAIRLIST" ) | awk '{print $2}' | sort -u )"
|
|
|
|
#Compile list of all device Names of paired devices (from bluetoothctl and from hardcoded list)
|
|
paired_devices_with_id="$( ( bluetoothctl paired-devices && cat "$PAIRLIST" ) | sort -u | cut -d' ' --complement -f1)"
|
|
#de-alias
|
|
paired_devices="$(echo "$paired_devices_with_id" | while read -r device_line; do
|
|
id="$(echo "$device_line" | cut -d' ' -f1)"
|
|
if grep -q "$id" "$ALIASLIST"; then
|
|
grep "$id" "$ALIASLIST" | cut -d' ' --complement -f1
|
|
else
|
|
echo "$device_line" | cut -d' ' --complement -f1
|
|
fi
|
|
done)"
|
|
|
|
echo "paired_devices:$paired_devices"
|
|
|
|
disp_devices="$( echo "$paired_devices" | grep -vf "$BLACKLIST" )"
|
|
|
|
#show which devices are connected in menu
|
|
disp_devices_with_links="$(echo "$paired_devices" | while read -r device; do
|
|
printf '%s' "$device"
|
|
if [ -n "$connected_devices" ] &&
|
|
echo "$device" | grep -q "$connected_devices"
|
|
then
|
|
printf '🔗'
|
|
fi
|
|
printf '\n'
|
|
done
|
|
)"
|
|
|
|
#detects current power mode of controller and adjusts options accordingly
|
|
powerstatus="$( bluetoothctl show | grep Powered | awk '{print $2}' )"
|
|
poweroption="$( echo "$powerstatus" | sed 's/yes/power off/; s/no/power on/' )"
|
|
#Don't print empty device list, removes unnecessary empty choice in dmenu
|
|
if [ "$disp_devices" = "" ];then
|
|
choice=$( printf "%s\n%s" "$actions" "$poweroption" |
|
|
dmenu -i -p 'What BT action would you like to perform:')
|
|
else
|
|
choice=$( ( echo "$disp_devices_with_links" && printf "%s\n%s" "$actions" "$poweroption" ) |
|
|
dmenu -i -p 'What BT action would you like to perform:' | tr -d '🔗')
|
|
fi
|
|
|
|
cleanup(){
|
|
scan off
|
|
rm -f /tmp/bt_start_scan*
|
|
pkill -RTMIN+$barsignal $bar
|
|
exit 0
|
|
}
|
|
|
|
pair(){
|
|
#since this function can get called indefinitely, make sure to always be scanning and controller has power in the case that it got deactived by some other process.
|
|
power on
|
|
scan on > /dev/null
|
|
#check whether $SCAN_PERIOD seconds has already passed since starting scanning, if not, wait for the rest of that time.
|
|
start_scan="$(cat /tmp/bt_start_scan$$)"
|
|
if [ $(( $(date +'%s') - $start_scan )) -lt $SCAN_PERIOD ]; then
|
|
sleep_period="$(( $SCAN_PERIOD - $( date +'%s') + $start_scan ))"
|
|
[ "$sleep_period" -gt 1 ] && plural="s"
|
|
notify-send "bt" "Searching for devices, please wait $sleep_period second$plural"
|
|
sleep "$sleep_period"
|
|
fi
|
|
all_devices="$( bluetoothctl devices )"
|
|
if [ "$paired_devices" = "" ]; then
|
|
new_devices="$( echo "$all_devices" | awk '{for (i=3; i<NF; i++) printf $i " "; print $NF}' )"
|
|
bt_IDS="$( echo "$all_devices" | awk '{print $2}' )"
|
|
else
|
|
#echo "$paired_devices" > /tmp/paired_devices$$
|
|
filtered_devices="$( echo "$all_devices" | grep -v "$paired_devices")"
|
|
bt_IDS="$( echo "$filtered_devices" | awk '{print $2}' )"
|
|
new_devices="$( echo "$filtered_devices" | awk '{for (i=3; i<NF; i++) printf $i " "; print $NF}' )"
|
|
#rm /tmp/paired_devices$$
|
|
fi
|
|
[ "$new_devices" = "" ] && options="rescan" || options=$(echo "$new_devices" && echo 'rescan')
|
|
choice=$( echo "$options" | dmenu -l 10 -i -p 'pair with which device?' )
|
|
if [ -n "$choice" ]; then
|
|
if [ "$choice" = "rescan" ]; then
|
|
start_scan="$( date +'%s')"
|
|
echo "$start_scan" > /tmp/bt_start_scan$$
|
|
pair
|
|
else
|
|
dev_no=$( echo "$new_devices" | nl | grep "$choice" | awk '{print $1}')
|
|
dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' )
|
|
#only attempt to connect if pairing succeeds
|
|
bluetoothctl pair "$dev_id" && ( pair_succesful=true && bluetoothctl connect "$dev_id" ) || pair_succesful=false
|
|
if $AUTOTRUST; then
|
|
bluetoothctl trust "$dev_id"
|
|
fi
|
|
#if device is not already hard coded as paired, add to paired devices list
|
|
if $pair_succesful && [ "$( grep "$dev_id" "$PAIRLIST")" = "" ] || [ "$(wc -l < "$PAIRLIST")" -eq 0 ]
|
|
then
|
|
echo to be added to "$PAIRLIST":
|
|
echo Device "$dev_id" "$choice"
|
|
echo Device "$dev_id" "$choice" >> "$PAIRLIST"
|
|
fi
|
|
fi
|
|
fi
|
|
}
|
|
|
|
case $choice in
|
|
"power on") bluetoothctl power on;;
|
|
"power off") bluetoothctl power off;;
|
|
"scan on") bluetoothctl power on && echo power on && sleep 2
|
|
([ -n "$TERMINAL" ] && $TERMINAL -e bluetoothctl scan on ) || st bluetoothctl scan on > /dev/null;;
|
|
"pair") pair;;
|
|
"unpair") choice=$( echo "$paired_devices" | dmenu -l 10 -i -p 'remove which paired device?')
|
|
if [ -n "$choice" ]; then
|
|
dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}')
|
|
dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' )
|
|
bluetoothctl remove "$dev_id"
|
|
#remove device to unpair from hard coded paired devices list
|
|
new_paired_list="$( grep -v "$dev_id" "$PAIRLIST" )"
|
|
if [ "$new_paired_list" != "" ]
|
|
then
|
|
echo "$new_paired_list" > "$PAIRLIST"
|
|
else
|
|
rm -rf "$PAIRLIST"
|
|
touch "$PAIRLIST"
|
|
fi
|
|
fi;;
|
|
|
|
"trust")
|
|
#search through all devices which are connected and only list those as options
|
|
# shellcheck disable=SC1091
|
|
untrusted_devices="$( awk '{print "bluetoothctl info "$2}' "$PAIRLIST" | . /dev/stdin | grep -E '(Alias:|Trusted:)' | sed -e 'N;s/\n/;/;s/^.?*Alias: //' | grep "Trusted: no" | awk -F ';' '{print $1}' )"
|
|
if [ "$( echo "$untrusted_devices" | wc -l )" -gt 0 ]
|
|
then
|
|
choice=$( echo "$untrusted_devices" | dmenu -l 10 -i -p 'remove which paired device?')
|
|
else
|
|
notify-send "bt" "No paired devices that are not trusted"
|
|
fi
|
|
if [ -n "$choice" ]; then
|
|
dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}')
|
|
dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' )
|
|
bluetoothctl trust "$dev_id"
|
|
fi;;
|
|
"disconnect")
|
|
#search through all devices and check which are connected
|
|
#only list those connceted devices as options
|
|
# shellcheck disable=SC1091
|
|
connected_ids="$(bluetoothctl devices | awk '{print "bluetoothctl info "$2}' | . /dev/stdin | grep -E '(^Device |Connected:)' | sed -e 'N;s/\n/;/' | grep 'Connected: yes' | cut -d' ' -f2,5)"
|
|
connected_devices="$(echo "$connected_ids" | while read -r id; do
|
|
if grep -q "$id" "$ALIASLIST"; then
|
|
grep "$id" "$ALIASLIST" | cut -d' ' --complement -f1
|
|
else
|
|
grep "$id" "$PAIRLIST" | cut -d' ' --complement -f1,2
|
|
fi
|
|
done)"
|
|
#only open dmenu prompt if there is more than one connected device
|
|
if [ "$( echo "$connected_devices" | wc -l )" -gt 1 ]
|
|
then
|
|
choice=$( echo "$connected_devices" | dmenu -l 10 -i -p 'disconnect which paired device?')
|
|
else
|
|
choice="$connected_devices"
|
|
fi
|
|
#only there was a choice (instead of canceling the dmenu)
|
|
if [ -n "$choice" ]; then
|
|
dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}')
|
|
dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' )
|
|
bluetoothctl disconnect "$dev_id"
|
|
fi;;
|
|
"blacklist")
|
|
choice=$( echo "$paired_devices" | dmenu -l 10 -i -p 'blacklist which paired device from selection?')
|
|
if [ -n "$choice" ]; then
|
|
echo "$choice" >> "$BLACKLIST"
|
|
fi;;
|
|
*)
|
|
echo "choice: $choice"
|
|
dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}')
|
|
[ "$dev_no" != "" ] && dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}')
|
|
echo "dev_id: $dev_id"
|
|
if [ -n "$dev_id" ]; then
|
|
power on
|
|
if bluetoothctl info "$dev_id" | grep -q "Connected: yes"
|
|
then
|
|
echo Was connceted... disconnecting
|
|
bluetoothctl disconnect "$dev_id"
|
|
else
|
|
if ! bluetoothctl paired-devices | grep -q "$dev_id"; then
|
|
echo "not in paired-devices list, re-adding (device needs to be in pairing mode for this)"
|
|
notify-send "bt" "device not in paired-devices list, re-pairing"
|
|
all_devices="$(bluetoothctl devices | cut -d' ' -f2)"
|
|
if ! echo "$dev_id" | grep -q "$all_devices"; then
|
|
scan on
|
|
echo "Scan on"
|
|
notify-send "bt" "Scanning for new devices..."
|
|
sleep "$SCAN_PERIOD"
|
|
fi
|
|
echo Attempting to pair...
|
|
bluetoothctl pair "$dev_id"
|
|
scan off
|
|
fi
|
|
echo connecting...
|
|
bluetoothctl connect "$dev_id"
|
|
fi
|
|
fi;;
|
|
esac
|
|
|
|
cleanup
|