~mil/sxmo-devel

sxmo-utils: WIP: sxmo_bluetoothmenu.sh: allow to select the default controller v1 PROPOSED

Willow Barraco: 1
 WIP: sxmo_bluetoothmenu.sh: allow to select the default controller

 1 files changed, 173 insertions(+), 57 deletions(-)
#1214743 test.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~mil/sxmo-devel/patches/51674/mbox | git am -3
Learn more about email & git

[PATCH sxmo-utils] WIP: sxmo_bluetoothmenu.sh: allow to select the default controller Export this patch

Being able to select between multiple controller become necessary
when you connect a bluetooth dongle to any devices wich already have an
internal bluetooth hardware. Atm we use the default controller, which is
completely random, and based on which one the daemons detected first.

To do so, we re-implement most of the bluetoothctl command using expect.

It is lighter and smarter than spaming the bluetoothctl commands. It
also simplify the scanning jobs, because we can do both scanning and
connecting with the same bluetoothctl interactive client.
And it also become necessary to allow the users to select the controller they
want. Because the bluetoothctl command only allow to run one command. We can not
chain "select $ctn" and "connect $dev" by example.

This also stop displaying some bluetoothctl prompt on a background
terminal. To debug, the user can just run sxmo_bluetoothmenu.sh in a
terminal.

Also contains some minor code improvements.

Signed-off-by: Willow Barraco <contact@willowbarraco.fr>
---
To be considered as an early WIP. I'd like to get feedback about using expect.
I pretty enjoyed discovering this tool today, and think it fit well in the sxmo
toolbox.
I'll sit on this patch for a while, to detect issues, and to make it bullet-proof.

 scripts/core/sxmo_bluetoothmenu.sh | 230 ++++++++++++++++++++++-------
 1 file changed, 173 insertions(+), 57 deletions(-)

diff --git a/scripts/core/sxmo_bluetoothmenu.sh b/scripts/core/sxmo_bluetoothmenu.sh
index 8aaadc55..9d0f10f5 100755
--- a/scripts/core/sxmo_bluetoothmenu.sh
+++ b/scripts/core/sxmo_bluetoothmenu.sh
@@ -12,9 +12,7 @@ set -e

SIMPLE_MODE=yes

_prompt() {
	sxmo_dmenu.sh -i "$@"
}
controller="$(bluetoothctl list | grep "\[default\]" | cut -d" " -f2)"

_device_list() {
	bluetoothctl devices | \
@@ -63,31 +61,49 @@ _restart_bluetooth() {
}

_full_reconnection() {
	sxmo_terminal.sh sh -c "
notify-send 'Make the device discoverable'
	notify-send 'Make the device discoverable'
	expect - "$controller" "$1" <<-'EOF'
		lassign $argv controller mac

bluetoothctl remove '$1'
sxmo_jobs.sh start bluetooth_scan bluetoothctl --timeout 300 scan on
		spawn bluetoothctl -a NoInputNoOutput

sleep 5
		send -- "select $controller\r"

while : ; do
	timeout 7 bluetoothctl connect '$1'
	if bluetoothctl info '$1'  | grep -q 'Connected: yes'; then
		break
	fi
	sleep 1
done
"
	sxmo_jobs.sh stop bluetooth_scan
}
		send -- "remove $mac\r"
		expect {
			"Device has been removed" {
				expect "Device $mac"
			}
			"Device $mac not available"
		}

_notify_failure() {
	notify-send "Something failed"
		send -- "scan on\r"
		expect "Discovery started"
		send -- "devices\r"

		set timeout 5
		expect {
			timeout {send -- "devices\r"; exp_continue}
			"Device $mac" {
				sleep 1
				send -- "connect $mac\r"
				expect {
					"Connection successful" {send -- "exit\r"}
					"Operation already in progress" {sleep 1; exp_continue}
					timeout {
						sleep 1
						send -- "connect $mac\r"
						exp_continue
					}
				}
			}
		}
		wait
	EOF
}

_can_fail() {
	"$@" || _notify_failure
	"$@" || notify-send "Something failed"
}

_show_toggle() {
@@ -103,9 +119,30 @@ toggle_connection() {
	MAC="$(printf "%s\n" "$DEVICE" | awk '{print $NF}')"

	if printf "%s\n" "$PICK" | grep -q "$icon_a2x"; then
		_can_fail timeout 7 sxmo_terminal.sh bluetoothctl disconnect "$MAC"
		_can_fail expect - "$controller" "$MAC" <<-'EOF'
			lassign $argv controller mac
			set timeout 7
			spawn bluetoothctl -a NoInputNoOutput
			send -- "select $controller\r"
			send -- "disconnect $mac\r"
			expect "Successful disconnected"
			send -- "exit\r"
			wait
		EOF
	else
		_can_fail timeout 7 sxmo_terminal.sh bluetoothctl connect "$MAC"
		_can_fail expect - "$controller" "$MAC" <<-'EOF'
			lassign $argv controller mac
			set timeout 7
			spawn bluetoothctl -a NoInputNoOutput
			send -- "select $controller\r"
			send -- "connect $mac\r"
			expect {
				"Operation already in progress" {sleep 1}
				"Connection successful"
			}
			send -- "exit\r"
			wait
		EOF
	fi
}

@@ -121,17 +158,16 @@ device_loop() {
		CONNECTED="$(printf "%s\n" "$INFO" | grep "Connected:" | awk '{print $NF}')"

		PICK="$(
			cat <<EOF |
$icon_ret Return
$icon_rld Refresh
Paired $(_show_toggle "$PAIRED")
Trusted $(_show_toggle "$TRUSTED")
Connected $(_show_toggle "$CONNECTED")
Blocked $(_show_toggle "$BLOCKED")
$icon_ror Clean re-connection
$icon_trh Remove
EOF
			_prompt -p "$DEVICE" -I "$INDEX"
			cat <<-EOF | sxmo_dmenu.sh -i -p "$DEVICE" -I "$INDEX"
				$icon_ret Return
				$icon_rld Refresh
				Paired $(_show_toggle "$PAIRED")
				Trusted $(_show_toggle "$TRUSTED")
				Connected $(_show_toggle "$CONNECTED")
				Blocked $(_show_toggle "$BLOCKED")
				$icon_ror Clean re-connection
				$icon_trh Remove
			EOF
		)"

		case "$PICK" in
@@ -145,23 +181,68 @@ EOF
				;;
			"Paired $icon_tof")
				INDEX=2
				_can_fail timeout 7 sxmo_terminal.sh bluetoothctl "$MAC"
				_can_fail expect - "$controller" "$MAC" <<-'EOF'
					lassign $argv controller mac
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "pair $mac\r"
					expect "Pairing successful"
					send -- "exit\r"
					wait
				EOF
				;;
			"Trusted $icon_ton")
				INDEX=3
				_can_fail sxmo_terminal.sh bluetoothctl untrust "$MAC"
				_can_fail expect - "$controller" "$MAC" <<-'EOF'
					lassign $argv controller mac
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "untrust $mac\r"
					expect "untrust succeeded"
					send -- "exit\r"
					wait
				EOF
				;;
			"Trusted $icon_tof")
				INDEX=3
				_can_fail sxmo_terminal.sh bluetoothctl trust "$MAC"
				_can_fail expect - "$controller" "$MAC" <<-'EOF'
					lassign $argv controller mac
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "trust $mac\r"
					expect "trust succeeded"
					send -- "exit\r"
					wait
				EOF
				;;
			"Connected $icon_ton")
				INDEX=4
				_can_fail timeout 7 sxmo_terminal.sh bluetoothctl disconnect "$MAC"
				_can_fail expect - "$controller" "$MAC" <<-'EOF'
					lassign $argv controller mac
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "disconnect $mac\r"
					expect "Successful disconnected"
					send -- "exit\r"
					wait
				EOF
				;;
			"Connected $icon_tof")
				INDEX=4
				_can_fail timeout 7 sxmo_terminal.sh bluetoothctl "$MAC"
				_can_fail expect - "$controller" "$MAC" <<-'EOF'
					lassign $argv controller mac
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "connect $mac\r"
					expect "Connection successful"
					send -- "exit\r"
					wait
				EOF
				;;
			"Blocked $icon_ton")
				INDEX=5
@@ -175,10 +256,11 @@ EOF
				;;
			"$icon_trh Remove")
				INDEX=7
				(confirm_menu -p "Remove this device ?" \
					&& _can_fail sxmo_terminal.sh bluetoothctl remove "$MAC") \
					|| continue
				return
				if confirm_menu -p "Remove this device ?"; then
					if _can_fail bluetoothctl remove "$MAC"; then
						return
					fi
				fi
				;;
		esac
		sleep 0.5
@@ -188,23 +270,28 @@ EOF
main_loop() {
	INDEX=0
	while : ; do
		INFO="$(bluetoothctl show)"
		INFO="$(bluetoothctl show "$controller")"
		DISCOVERING="$(printf "%s\n" "$INFO" | grep "Discovering:" | awk '{print $NF}')"
		PAIRABLE="$(printf "%s\n" "$INFO" | grep "Pairable:" | awk '{print $NF}')"

		CONTROLLERS="$(bluetoothctl <<-EOF | grep ^Controller | sort -u | sed "s|^Controller|$icon_rss|"
			select $controller
			list
		EOF
		)"
		DEVICES="$(_device_list)"

		PICK="$(
			cat <<EOF |
$icon_cls Close Menu
$icon_rld Refresh
$icon_pwr Restart daemon
Simple mode $(_show_toggle "$SIMPLE_MODE")
Pairable $(_show_toggle "$PAIRABLE")
Discovering $(_show_toggle "$DISCOVERING")
$DEVICES
EOF
			_prompt -p "$icon_bth Bluetooth" -I "$INDEX"
			cat <<-EOF | sxmo_dmenu.sh -i -p "$icon_bth Bluetooth" -I "$INDEX"
				$icon_cls Close Menu
				$icon_rld Refresh
				$icon_pwr Restart daemon
				Simple mode $(_show_toggle "$SIMPLE_MODE")
				Pairable $(_show_toggle "$PAIRABLE")
				Discovering $(_show_toggle "$DISCOVERING")
				$CONTROLLERS
				$DEVICES
			EOF
		)"

		case "$PICK" in
@@ -229,12 +316,30 @@ EOF
				INDEX=3
				;;
			"Pairable $icon_ton")
				bluetoothctl pairable off
				INDEX=4
				_can_fail expect - "$controller" <<-'EOF'
					lassign $argv controller
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "pairable off\r"
					expect "Changing pairable off succeeded"
					send -- "exit\r"
					wait
				EOF
				;;
			"Pairable $icon_tof")
				bluetoothctl pairable on
				INDEX=4
				_can_fail expect - "$controller" <<-'EOF'
					lassign $argv controller
					set timeout 5
					spawn bluetoothctl -a NoInputNoOutput
					send -- "select $controller\r"
					send -- "pairable on\r"
					expect "Changing pairable on succeeded"
					send -- "exit\r"
					wait
				EOF
				;;
			"Discovering $icon_ton")
				INDEX=5
@@ -242,11 +347,22 @@ EOF
				sleep 0.5
				;;
			"Discovering $icon_tof")
				sxmo_jobs.sh start bluetooth_scan bluetoothctl --timeout 60 scan on > /dev/null
				sxmo_jobs.sh start bluetooth_scan expect -c "
					spawn bluetoothctl -a NoInputNoOutput
					send -- \"select $controller\r\"
					send -- \"scan on\r\"
					sleep 60
					send -- \"exit\r\"
					wait
				"
				notify-send "Scanning for 60 seconds"
				INDEX=5
				sleep 0.5
				;;
			"$icon_rss"*)
				INDEX=0
				controller="$(printf %s "$PICK" | cut -d" " -f2)"
				;;
			*)
				INDEX=0

-- 
2.45.0
sxmo-utils/patches/test.yml: SUCCESS in 22s

[WIP: sxmo_bluetoothmenu.sh: allow to select the default controller][0] from [Willow Barraco][1]

[0]: https://lists.sr.ht/~mil/sxmo-devel/patches/51674
[1]: mailto:contact@willowbarraco.fr

✓ #1214743 SUCCESS sxmo-utils/patches/test.yml https://builds.sr.ht/~mil/job/1214743