~mil/sxmo-utils

55985a8f20ce7add0f85a230904d41189bfcb03c — Stacy Harper a month ago 61451f6
Rework the status bar

Goals of this patch :

- display the signal quality

I used a thermometer icon cause there is no available icon with a
filleable bar o_O

- display the currently used network technology (4g, 3g, etc...)

I used the mapping from:

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/blob/master/include/ModemManager-enums.h#L220

Dylan also said:

Anything from POTS to GPRS = 2G
UMTS to EVDOB = 3G
LTE = 4G
5GNR = 5G

- display the modem infos when modemmonitor is disabled

We want to decorelate the modem monitor from the icon. We still want to
know easily if modem monitor is runing but we also want those modem
infos if not.

- simplify the modem state determination (no state file anymore)

The statusbar probe mmcli itself.

- fix the leading timer without call issue

This was caused by the "pgrep -f" command that was matching itself.
Using a simple "pgrep" looks good enough anyway.

- fix some sxmo_statusbar update spaming issues (vol control)

This one point took me a lot of time to findout a good solution. We want
the USR1 kill to be spamable without causing issue to the displayed bar.
We dont want mid rendered bar (half the icons).
We dont want empty bars (empty stdout line).

I use some variable to store pid, smart waits and a better trap function
to make it to works cleanly. Now we can spam statusbarupdate. Only the
last one will actually redraw the bar.

Signed-off-by: Stacy Harper <contact@stacyharper.net>
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
M scripts/core/sxmo_common.sh => scripts/core/sxmo_common.sh +0 -2
@@ 32,8 32,6 @@ export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
# shellcheck disable=SC2034
export CONTACTFILE="$XDG_CONFIG_HOME/sxmo/contacts.tsv"
# shellcheck disable=SC2034
export MODEMSTATEFILE="$XDG_RUNTIME_DIR/sxmo.modem.state"
# shellcheck disable=SC2034
export UNSUSPENDREASONFILE="$XDG_RUNTIME_DIR/sxmo.suspend.reason"
# shellcheck disable=SC2034
export LASTSTATE="$XDG_RUNTIME_DIR/sxmo.suspend.laststate"

M scripts/core/sxmo_statusbar.sh => scripts/core/sxmo_statusbar.sh +128 -72
@@ 4,54 4,92 @@
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

trap "update" USR1
percenticon() {
	if [ "$1" -lt 20 ]; then
		printf ""
	elif [ "$1" -lt 40 ]; then
		printf ""
	elif [ "$1" -lt 60 ]; then
		printf ""
	elif [ "$1" -lt 80 ]; then
		printf ""
	else
		printf ""
	fi
}

bar() {
	MMCLI="$(mmcli -m any -J)"

update() {
	# In-call.. show length of call
	CALLINFO=" "
	if pgrep -f sxmo_modemcall.sh; then
	if pgrep sxmo_modemcall.sh > /dev/null; then
		NOWS="$(date +"%s")"
		CALLSTARTS="$(date +"%s" -d "$(
			grep -aE 'call_start|call_pickup' "$XDG_DATA_HOME"/sxmo/modem/modemlog.tsv |
			tail -n1 |
			cut -f1
		)")"
		CALLSECONDS="$(echo "$NOWS" - "$CALLSTARTS" | bc)"
		CALLINFO="${CALLSECONDS}s"
		CALLSECONDS="$(printf "%s - %s" "$NOWS" "$CALLSTARTS" | bc)"
		printf "%ss " "$CALLSECONDS"
	fi

	# symbol if wireguard/vpn is connected
	VPN=""
	VPNDEVICE="$(nmcli con show | grep vpn | awk '{ print $4 }')"
	WGDEVICE="$(nmcli con show | grep wireguard | awk '{ print $4 }')"
	if [ -n "$VPNDEVICE" ] && [ "$VPNDEVICE" != "--" ]; then
		VPN=""
	elif [ -n "$WGDEVICE" ] && [ "$WGDEVICE" != "--" ]; then
		VPN=""
	MODEMSTATUS=""
	if [ -z "$MMCLI" ]; then
		printf ""
	else
		MODEMSTATUS="$(printf %s "$MMCLI" | jq -r .modem.generic.state)"
		case "$MODEMSTATUS" in
			locked)
				printf ""
				;;
			registered|connected)
				MODEMSIGNAL="$(printf %s "$MMCLI" | jq -r '.modem.generic."signal-quality".value')"
				percenticon "$MODEMSIGNAL"
				;;
			disconnected)
				printf "ﲁ"
				;;
		esac
	fi

	if [ "$MODEMSTATUS" = "connected" ]; then
		printf " "
		USEDTECHS="$(printf %s "$MMCLI" | jq -r '.modem.generic."access-technologies"[]')"
		case "$USEDTECHS" in
			*5gnr*)
				printf 5g # no icon yet
				;;
			*lte*)
				printf ﰒ
				;;
			*umts*|*hsdpa*|*hsupa*|*hspa*|*1xrtt*|*evdo0*|*evdoa*|*evdob*)
				printf ﰑ
				;;
			*edge*)
				printf E
				;;
			*pots*|*gsm*|*gprs*)
				printf ﰐ
				;;
		esac
	fi

	if pgrep -f sxmo_modemmonitor.sh > /dev/null; then
		printf " "
	fi

	# W symbol if wireless is connect
	WIRELESS=""
	WLANSTATE="$(tr -d "\n" < /sys/class/net/wlan0/operstate)"
	if [ "$WLANSTATE" = "up" ]; then
		WIRELESS=""
		printf " "
	fi

	# M symbol if modem monitoring is on & modem present
	MODEMMON=""
	if [ -f "$MODEMSTATEFILE" ]; then
		MODEMSTATE="$(cat "$MODEMSTATEFILE")"
		if [ locked = "$MODEMSTATE" ]; then
			MODEMMON=""
		elif [ registered = "$MODEMSTATE" ]; then
			MODEMMON=""
		elif [ connected = "$MODEMSTATE" ]; then
			MODEMMON=""
		elif [ failed = "$MODEMSTATE" ] || [ disconnected = "$MODEMSTATE" ]; then
			MODEMMON=""
		else
			MODEMMON=""
		fi
	# symbol if wireguard/vpn is connected
	VPNDEVICE="$(nmcli con show | grep vpn | awk '{ print $4 }')"
	WGDEVICE="$(nmcli con show | grep wireguard | awk '{ print $4 }')"
	if [ -n "$VPNDEVICE" ] && [ "$VPNDEVICE" != "--" ]; then
		printf " "
	elif [ -n "$WGDEVICE" ] && [ "$WGDEVICE" != "--" ]; then
		printf " "
	fi

	# Find battery and get percentage + status


@@ 62,55 100,60 @@ update() {
		fi
	done

	printf " "
	if [ "$BATSTATUS" = "C" ]; then
		if [ "$PCT" -lt 20 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 30 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 40 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 60 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 80 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 90 ]; then
			BATSTATUS="$PCT% "
			printf ""
		else
			BATSTATUS="$PCT% "
			printf ""
		fi
	else
		if [ "$PCT" -lt 10 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 20 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 30 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 40 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 50 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 60 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 70 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 80 ]; then
			BATSTATUS="$PCT% "
			printf ""
		elif [ "$PCT" -lt 90 ]; then
			BATSTATUS="$PCT% "
			printf ""
		else
			BATSTATUS="$PCT% "
			printf ""
		fi
	fi

	[ -z "$SXMO_BAR_HIDE_BAT_PER" ] && printf " %s%%" "$PCT"

	printf " "

	# Volume
	AUDIODEV="$(sxmo_audiocurrentdevice.sh)"
	AUDIOSYMBOL=$(echo "$AUDIODEV" | cut -c1)
	AUDIOSYMBOL="$(printf %s "$AUDIODEV" | cut -c1)"
	if [ "$AUDIOSYMBOL" = "L" ] || [ "$AUDIOSYMBOL" = "N" ]; then
		AUDIOSYMBOL="" #speakers or none, use no special symbol
		printf "" #speakers or none, use no special symbol
	elif [ "$AUDIOSYMBOL" = "H" ]; then
		AUDIOSYMBOL=" "
		printf " "
	elif [ "$AUDIOSYMBOL" = "E" ]; then
		AUDIOSYMBOL=" " #earpiece
		printf " " #earpiece
	fi
	VOL=0
	[ "$AUDIODEV" = "None" ] || VOL="$(


@@ 121,32 164,45 @@ update() {
		xargs printf %.0f
	)"
	if [ "$AUDIODEV" != "None" ]; then
		if [ "$VOL" -eq 0 ]; then
			VOLUMESYMBOL="ﱝ"
		elif [ "$VOL" -lt 25 ]; then
			VOLUMESYMBOL="奄"
		elif [ "$VOL" -gt 75 ]; then
			VOLUMESYMBOL="墳"
		else
			VOLUMESYMBOL="奔"
		if [ "$VOL" -gt 66 ]; then
			printf ""
		elif [ "$VOL" -gt 33 ]; then
			printf ""
		elif [ "$VOL" -gt 0 ]; then
			printf ""
		elif [ "$VOL" -eq 0 ]; then
			printf "ﱝ"
		fi
	fi
	# Time
	TIME="$(date +%R)"

	BAR="$(echo "${CALLINFO} ${MODEMMON} ${WIRELESS} ${VPN} ${AUDIOSYMBOL}${VOLUMESYMBOL} ${BATSTATUS} ${TIME}" | sed 's| \+| |g')"
	printf " %s\0" "$(date +%R)"
}

	case "$(sxmo_wm.sh)" in
		sway) printf "%s\n" "$BAR";;
		dwm) xsetroot -name "$BAR";;
	esac
WM="$(sxmo_wm.sh)"

forceupdate() {
	kill "$SLEEPID"
}
trap "forceupdate" USR1

# E.g. on first boot justs to make sure the bar comes in quickly
update
update() {
	BAR="$(bar)"
	[ -z "$SLEEPID" ] && return # to prevent mid rendering interuption
	printf %s "$BAR" | case "$WM" in
		sway|ssh) xargs -0 printf "%s\n";;
		dwm) xargs -0 xsetroot -name;;
	esac
}

while :
do
	sleep 30 & wait
	update
	sleep 10 &
	SLEEPID=$!

	update &
	UPDATEID=$!

	wait "$SLEEPID"
	unset SLEEPID
	wait "$UPDATEID"
done

M scripts/modem/sxmo_modemmonitor.sh => scripts/modem/sxmo_modemmonitor.sh +2 -31
@@ 12,8 12,6 @@ err() {
}

gracefulexit() {
	rm "$MODEMSTATEFILE"
	sxmo_statusbarupdate.sh
	sleep 1
	echo "sxmo_modemmonitor: gracefully exiting (on signal or after error)">&2
	kill -9 0


@@ 223,17 221,9 @@ checkfornewtexts() {
}

initialmodemstatus() {
	touch "$MODEMSTATEFILE"
	state=$(mmcli -m "$(modem_n)")
	if echo "$state" | grep -q -E "^.*state:.*connected.*$"; then
		echo connected > "$MODEMSTATEFILE"
	elif echo "$state" | grep -q -E "^.*state:.*registered.*$"; then
		echo registered > "$MODEMSTATEFILE"
	elif echo "$state" | grep -q -E "^.*state:.*locked.*$"; then
		echo locked > "$MODEMSTATEFILE"
	if echo "$state" | grep -q -E "^.*state:.*locked.*$"; then
		pidof unlocksim || sxmo_hooks.sh unlocksim &
	else
		echo unknown > "$MODEMSTATEFILE"
	fi
}



@@ 243,6 233,7 @@ mainloop() {
	checkforincomingcalls
	checkfornewtexts

	initialmodemstatus

	# Monitor for incoming calls
	dbus-monitor --system "interface='org.freedesktop.ModemManager1.Modem.Voice',type='signal',member='CallAdded'" | \


@@ 262,11 253,6 @@ mainloop() {
			echo "$line" | grep -E "^signal" && checkforfinishedcalls
		done &

	#Monitor for modem state changes
	# arg1 holds the new state: MM_MODEM_STATE_FAILED = -1, MM_MODEM_STATE_UNKNOWN = 0, ... MM_MODEM_STATE_REGISTERED=8, MM_MODEM_STATE_CONNECTED = 11
	initialmodemstatus
	sxmo_statusbarupdate.sh

	dbus-monitor --system "interface='org.freedesktop.ModemManager1.Modem',type='signal',member='StateChanged'" | \
		while read -r line; do
			if echo "$line" | grep -E "^signal.*StateChanged"; then


@@ 274,25 260,14 @@ mainloop() {
				read -r oldstate #unused but we need to read past it
				read -r newstate
				if echo "$newstate" | grep "int32 2"; then
					echo locked > "$MODEMSTATEFILE"
					pidof unlocksim || sxmo_hooks.sh unlocksim &
				elif echo "$newstate" | grep "int32 8"; then
					echo registered > "$MODEMSTATEFILE"
					#if there is a PIN entry menu open, kill it:
					# shellcheck disable=SC2009
					ps aux | grep dmenu | grep PIN | gawk '{ print $1 }' | xargs kill
					checkforfinishedcalls
					checkforincomingcalls
					checkfornewtexts
				elif echo "$newstate" | grep "int32 11"; then
					echo connected > "$MODEMSTATEFILE"
					#3G/2G/4G available
				elif echo "$newstate" | grep "int32 -1"; then
					echo failed > "$MODEMSTATEFILE"
				elif echo "$newstate" | grep "int32 3"; then
					echo disabled > "$MODEMSTATEFILE"
				else
					echo unknown > "$MODEMSTATEFILE"
				fi
				sxmo_statusbarupdate.sh
			fi


@@ 316,7 291,6 @@ mainloop() {
					echo "sxmo_modemmonitor: modem not found, waiting for modem... (try #$TRIES)">&2
					sleep 3
					if [ "$TRIES" -eq 10 ]; then
						echo failed > "$MODEMSTATEFILE"
						echo "sxmo_modemmonitor: forcing modem restart">&2
						sxmo_modemmonitortoggle.sh restart #will kill the modemmonitor too
						break


@@ 331,9 305,6 @@ mainloop() {
	wait
	wait
	wait

	rm "$MODEMSTATEFILE" 2>/dev/null
	sxmo_statusbarupdate.sh
}



M scripts/modem/sxmo_modemmonitortoggle.sh => scripts/modem/sxmo_modemmonitortoggle.sh +1 -1
@@ 99,7 99,6 @@ on() {
	while ! printf %s "$(mmcli -L)" 2> /dev/null | grep -qoE 'Modem\/([0-9]+)'; do
		TRIES=$((TRIES+1))
		if [ "$TRIES" -eq 10 ]; then
			printf "failed\n" > "$MODEMSTATEFILE"
			notify-send --urgency=critical "We failed to start the modem monitor. We may need hard reboot."
		fi
		sleep 5


@@ 128,4 127,5 @@ case "$1" in
	off) off;;
esac

sleep 1
sxmo_statusbarupdate.sh