forked from cdown/btmenu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbluetooth_dmenu
executable file
·154 lines (135 loc) · 4.99 KB
/
bluetooth_dmenu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/bin/sh
IFS='
'
MAXLINES=15
tempfile="/tmp/bluethoothdmenudevicelist.txt"
width=0
mode="Connect"
connectedTo=""
# USER DEFINED VARIABLES
# ----------------------
SERVICE="org.bluez"
OBJ_SELF="/org/bluez/hci0"
OBJ_TEMPLATE="/org/bluez/hci0/dev_"
INTERFACE_SELF="org.bluez.Adapter1"
INTERFACE="org.bluez.Device1"
# Prefixes these were needed because i didn't know that substring indexing was not POSIX compliant
# Prefix for previously paired devices, these have to be added in busctl
DELIM_DEVICES=""
# Prefix for empty/blank lines
DELIM_SPACE="¦"
# Prefix for properties, in the properties section
DELIM_PROPS="|"
set +x $mode
unset $mode
busctl tree org.bluez > $tempfile
while read mac; do
t=$(echo "${mac##*/dev_}"| grep -v "└─/org")
a=${t%%/*}
#Discard repeats due to there being "sub-adresses"
if [ -z "$a" ] || [ "$a" != "$t" ]; then
continue;
fi
isConnected=$(busctl get-property $SERVICE $OBJ_TEMPLATE"$a" $INTERFACE Connected)
b=$(busctl get-property $SERVICE $OBJ_TEMPLATE"$a" $INTERFACE Alias)
b=${b##s }
#If you're wondering why im saving the adress, im assuming it can be different than the a variable, i also use it to display on dmenu
c=$(busctl get-property $SERVICE $OBJ_TEMPLATE"$a" $INTERFACE Address)
c=${c##s }
if [ "$isConnected" = "b true" ]; then
connectedTo="$c"
#echo $connectedTo;
fi
set +x "$@" "$a" "$b" "$c";
done < $tempfile
unset a; unset b; unset c;
#echo "$#"
notify() {
msg=${1?BUG: no message}
is_error=${2}
if command -v notify-send >/dev/null 2>&1; then
notify-send "btmenu" "$msg" # TODO: escaping
fi
if [ "$is_error" ]; then
printf 'ERROR: %s\n' "$msg" >&2
else
printf '%s\n' "$msg"
fi
unset msg is_error
}
setwidth(){
width=0
for str in "$@"; do
[ $width -lt ${#str} ] && width=${#str}
done
}
execute_mode() {
selected="$DELIM_DEVICES"
mode=${1?BUG: missing mode}
case $mode in
Connect)
preposition=to
;;
Disconnect)
preposition=from
;;
esac
if [ ! "${2}" ]; then
notify "No devices found. Are they registered with D-Bus?"
return 2
fi
setwidth "$@"
inc=$(($#))
while [ $inc -ge 2 ]; do
selected="$DELIM_DEVICES"
tellar=$(eval printf "%s" \"\$\{$inc\}\");
inc=$((inc-1))
if [ "$connectedTo" = "$tellar" ]; then
selected="$DELIM_DEVICES ---"
fi
aussie=$(eval printf "%s" \"\$\{$inc\}\" | cut -d\" -f 2 );
demon="$demon"$(printf "%-5s%-${width}s%s»" "$selected" "$aussie" "$tellar");
inc=$((inc-2))
done
#Apparently in posix shells += is undefined so yeah i had to go back in "cleaness"
#MAYBETODO maybe we could set like a "pointer" in the list to set which
demon=$(echo "$demon" | sed -E "s/»/\n/g")
demon="$demon"$(printf \\n%s "$DELIM_SPACE")
demon="$demon"$(printf \\n${DELIM_PROPS}Powered%s "$(busctl get-property $SERVICE $OBJ_SELF $INTERFACE_SELF Powered | sed -E "s/b/:/")")
demon="$demon"$(printf \\n${DELIM_PROPS}Discoverable%s "$(busctl get-property $SERVICE $OBJ_SELF $INTERFACE_SELF Discoverable | sed -E "s/b/:/")")
demon="$demon"$(printf \\n${DELIM_PROPS}Pairable%s "$(busctl get-property $SERVICE $OBJ_SELF $INTERFACE_SELF Pairable | sed -E "s/b/:/")")
name=$(printf '%s\n' "$demon" | dmenu -l $MAXLINES -p "btmenu")
unset aussie tellar demon inc
#the idea is that an adress presented on the device may be corrupted or mismatch the one saved on busctl but for now i will do it the lazy way
#TODO theres most likely an error in case of a device having a name containing a " although i haven't researched it
mac=$(echo "$name" | cut -d\" -f 2)
if [ "${name##$DELIM_DEVICES}" != "$name" ]; then
#TODO Theres an error in case of a device having a name containing a -
if [ "${name##"$DELIM_DEVICES ---"}" != "$name" ]; then
mode="Disconnect"
#$name=${name:5}
fi
mac=$( echo "$mac" | sed -e "s/:/_/g" )
notify "Attempting to $mode $preposition $mac"
final=$(printf "busctl call $SERVICE $OBJ_TEMPLATE%s $INTERFACE %s " "$mac" "$mode")
mkfifo output
eval "$final" 2> output & while read -r line
do
notify "$line"
done < output
rm output
elif [ "${name##$DELIM_PROPS}" != "$name" ]; then
name="${name##|}"
#TODO fix this mess without sed, add some logic to it
state=$(echo "$name" | cut -d\: -f 2 | sed -e "s/ true/false/"| sed -e "s/ false/true/")
name=$(echo "$name" | cut -d\: -f 1)
notify "Changing property [${name}] to ${state}"
mac=$(echo "busctl set-property $SERVICE $OBJ_SELF $INTERFACE_SELF $name b $state")
eval "$mac"
else
echo "Exiting, due to lack of relevant input"
fi
unset mode name mac preposition state
exit
}
execute_mode "$@"