From f4ee396394133115bfdaf32cf79d96c6f0d0c49e Mon Sep 17 00:00:00 2001 From: Stacy Harper Date: Tue, 13 Apr 2021 17:41:59 +0200 Subject: [PATCH] Rework the incoming call pickup/discard behavior * The sxmo_modemmonitor.sh will now run a new sxmo_modemcall.sh dedicated menu to Pickup, Hangup or Mute the call. It will not write notifications anymore. * We now can mute the ring with the new pickup menu. With the default hook, this will stop the ringtone like the missed_call would do. * The sxmo_modemcall.sh now use a new sxmo_proximitylock.sh which will lock the screen when putting the phone in front of the ear. This script should be smart enough to work smoothly with a crust context. To achieve this, the proximity_lock will only disable the initial lock (the one who want to go back in crust after some seconds) if the phone moved a little bit and is not in your pocket. So forgetting the phone in a table or not earing the ring in your bag will not empty the battery. You'll find the phone in crust with notifications. * The sxmo_modemcall.sh do not monitor finished calls anymore. We leave it with hangup or being killed by sxmo_modemmonitor.sh. This simplify the call script and prevent double deleting mmcli calls. I had to use pids and wait commands to fix and issue and make the script killeable by the monitor. Plus, only the monitor will now delete calls. The call script should be precise on what happen using cached files. * Discarded and hanged up calls are two different behavior with different script (by default use the same linked ones) * Fixed a bug where sometime ringing was started twice. I think this is cause by the new checkforincomingcalls in the connected state change. We now use a file to test if the call already has been managed. Signed-off-by: Stacy Harper Signed-off-by: Maarten van Gompel --- configs/default_hooks/discard | 5 ++ configs/default_hooks/mute_ring | 5 ++ scripts/core/sxmo_lock.sh | 9 ++- scripts/core/sxmo_movement.sh | 19 ++++++ scripts/core/sxmo_proximitylock.sh | 41 +++++++++++++ scripts/modem/sxmo_modemcall.sh | 98 ++++++++++++++++++++---------- scripts/modem/sxmo_modemmonitor.sh | 41 +++++++------ 7 files changed, 167 insertions(+), 51 deletions(-) create mode 100644 configs/default_hooks/discard create mode 100644 configs/default_hooks/mute_ring create mode 100644 scripts/core/sxmo_movement.sh create mode 100644 scripts/core/sxmo_proximitylock.sh diff --git a/configs/default_hooks/discard b/configs/default_hooks/discard new file mode 100644 index 0000000..a8307c1 --- /dev/null +++ b/configs/default_hooks/discard @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +# This script is executed (asynchronously) when you discard an incoming call + +exec "$(dirname "$0")/missed_call" "$@" diff --git a/configs/default_hooks/mute_ring b/configs/default_hooks/mute_ring new file mode 100644 index 0000000..85eb49f --- /dev/null +++ b/configs/default_hooks/mute_ring @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +# This script is executed (asynchronously) when you mute an incoming call + +exec "$(dirname "$0")/missed_call" "$@" diff --git a/scripts/core/sxmo_lock.sh b/scripts/core/sxmo_lock.sh index 791dd5c..c5f274f 100755 --- a/scripts/core/sxmo_lock.sh +++ b/scripts/core/sxmo_lock.sh @@ -4,11 +4,18 @@ # shellcheck source=scripts/core/sxmo_common.sh . "$(dirname "$0")/sxmo_common.sh" +finish() { + kill $LOCKPID +} +trap 'finish' TERM INT + if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/lock" ]; then "$XDG_CONFIG_HOME/sxmo/hooks/lock" fi pkill -9 lisgd -sxmo_screenlock "$@" +sxmo_screenlock "$@" & +LOCKPID="$!" +wait $LOCKPID [ "$(xrandr | grep DSI-1 | cut -d ' ' -f 5)" = "right" ] && ORIENTATION=1 || ORIENTATION=0 sxmo_lisgdstart.sh -o $ORIENTATION & if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/unlock" ]; then diff --git a/scripts/core/sxmo_movement.sh b/scripts/core/sxmo_movement.sh new file mode 100644 index 0000000..2c4b5ce --- /dev/null +++ b/scripts/core/sxmo_movement.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env sh + +anglevel_x_raw_bus="$(find /sys/ -name 'in_anglvel_x_raw')" +anglx() { + cat "$anglevel_x_raw_bus" +} + +waitmovement() { + initialpos="$(anglx)" + while true; do + pos="$(anglx)" + movement="$(echo "$initialpos" - "$pos" | bc)" + [ 0 -gt "$movement" ] && movement="$(echo "$movement * -1" | bc)" + [ 10 -lt "$movement" ] && return + sleep 0.5 + done +} + +"$@" diff --git a/scripts/core/sxmo_proximitylock.sh b/scripts/core/sxmo_proximitylock.sh new file mode 100644 index 0000000..3834873 --- /dev/null +++ b/scripts/core/sxmo_proximitylock.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env sh + +finish() { + kill $(jobs -p) + [ free = "$STATE" ] && [ true = "$WASLOCKED" ] && sxmo_lock.sh & + exit 0 +} + +trap 'finish' TERM INT + +proximity_raw_bus="$(find /sys/ -name 'in_proximity_raw')" +distance() { + cat "$proximity_raw_bus" +} + +TARGET=30 + +mainloop() { + while true; do + distance="$(distance)" + if [ locked = "$STATE" ] && [ "$distance" -lt "$TARGET" ]; then + pkill -f sxmo_lock.sh + STATE=free + elif [ free = "$STATE" ] && [ "$distance" -gt "$TARGET" ]; then + sxmo_lock.sh --screen-off & + STATE=locked + fi + sleep 0.5 + done +} + +pgrep -f sxmo_lock.sh > /dev/null && STATE=locked || STATE=free +if [ locked = "$STATE" ]; then + WASLOCKED=true + + # we dont want to loose the initial lock if the phone is forgotten somewhere + # without proximity as this will prevent going back to crust + sxmo_movement.sh waitmovement +fi + +mainloop diff --git a/scripts/modem/sxmo_modemcall.sh b/scripts/modem/sxmo_modemcall.sh index 49ef212..fd8e9b9 100755 --- a/scripts/modem/sxmo_modemcall.sh +++ b/scripts/modem/sxmo_modemcall.sh @@ -14,14 +14,7 @@ modem_n() { finish() { - # E.g. hangup all calls, switch back to default audio, notify user, and die sxmo_vibratepine 1000 & - mmcli -m "$(modem_n)" --voice-hangup-all - for CALLID in $( - mmcli -m "$(modem_n)" --voice-list-calls | grep -oE "Call\/[0-9]+" | cut -d'/' -f2 - ); do - mmcli -m "$(modem_n)" --voice-delete-call "$CALLID" - done if [ -f "$ALSASTATEFILE" ]; then alsactl --file "$ALSASTATEFILE" restore else @@ -32,12 +25,14 @@ finish() { echo "sxmo_modemcall: $1">&2 notify-send "$1" fi - kill -9 0 - pkill -9 dmenu #just in case the call menu survived somehow? + kill $LOCKPID + pkill -9 dmenu exit 1 } gracefulexit() { + kill $MAINPID + wait $MAINPID finish "Call ended" } @@ -57,6 +52,20 @@ vid_to_number() { tr -d ' ' } +number_to_contactname() { + NUMBER="$(echo "$1" | sed "s/^0\([0-9]\{9\}\)$/${DEFAULT_NUMBER_PREFIX:-0}\1/")" + CONTACT=$(sxmo_contacts.sh --all | + grep "^$NUMBER:" | + cut -d':' -f 2 | + sed 's/^[ \t]*//;s/[ \t]*$//' #strip leading/trailing whitespace + ) + if [ -n "$CONTACT" ]; then + echo "$CONTACT" + else + echo "Unknown ($NUMBER)" + fi +} + log_event() { EVT_HANDLE="$1" EVT_VID="$2" @@ -88,7 +97,6 @@ toggleflagset() { acceptcall() { CALLID="$1" - rm "$NOTIFDIR/incomingcall_${CALLID}_notification"* 2>dev/null #there can be multiple actionable notifications for one call (pickup/discard) echo "sxmo_modemcall: Attempting to initialize CALLID $CALLID">&2 DIRECTION="$( mmcli --voice-status -o "$CALLID" -K | @@ -118,14 +126,20 @@ acceptcall() { hangup() { CALLID="$1" - rm "$NOTIFDIR/incomingcall_${CALLID}_notification"* 2>dev/null #there can be multiple actionable notifications for one call (pickup/discard) - if [ ! -f "$CACHEDIR/${CALLID}.pickedupcall" ]; then + if [ -f "$CACHEDIR/${CALLID}.pickedupcall" ]; then + rm -f "$CACHEDIR/${CALLID}.pickedupcall" + touch "$CACHEDIR/${CALLID}.hangedupcall" #this signals that we hanged up this call to other asynchronously running processes + log_event "call_hangup" "$CALLID" + else #this call was never picked up and hung up immediately, so it is a discarded call touch "$CACHEDIR/${CALLID}.discardedcall" #this signals that we discarded this call to other asynchronously running processes + if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/discard" ]; then + echo "sxmo_modemcall: Invoking discard hook (async)">&2 + "$XDG_CONFIG_HOME/sxmo/hooks/discard" & + fi + log_event "call_discard" "$CALLID" fi modem_cmd_errcheck -m "$(modem_n)" -o "$CALLID" --hangup - log_event "call_hangup" "$CALLID" - modem_cmd_errcheck -m "$(modem_n)" --voice-delete-call="$CALLID" finish "Call with $NUMBER terminated" exit 0 } @@ -153,23 +167,6 @@ incallsetup() { toggleflagset "-2" } -incallmonitor() { - CALLID="$1" - while true; do - sxmo_statusbarupdate.sh - if mmcli -m "$(modem_n)" -K -o "$CALLID" | grep -E "^call.properties.state.+terminated"; then - #note: deletion will be handled asynchronously by sxmo_modemmonitor's checkforfinishedcalls() - if [ "$NUMBER" = "--" ]; then - finish "Call with unknown number terminated" - else - finish "Call with $NUMBER terminated" - fi - fi - echo "sxmo_modemcall: Call still in progress">&2 - sleep 3 - done -} - incallmenuloop() { echo "sxmo_modemcall: Current flags are $FLAGS">&2 CHOICES=" @@ -225,9 +222,44 @@ dtmfmenu() { pickup() { acceptcall "$1" incallsetup "$1" - incallmonitor "$1" & incallmenuloop "$1" } +mute() { + touch "$CACHEDIR/$1.mutedring" #this signals that we muted this ring + if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/mute_ring" ]; then + echo "sxmo_modemmonitor: Invoking mute_ring hook (async)">&2 + "$XDG_CONFIG_HOME/sxmo/hooks/mute_ring" "$CONTACTNAME" & + fi + log_event "ring_mute" "$1" + finish "Ringing with $NUMBER muted" +} + +incomingcallmenu() { + NUMBER=$(vid_to_number "$1") + CONTACTNAME=$(number_to_contactname "$NUMBER") + + # wait for sxmo to be unlocked to display menus + while pgrep sxmo_screenlock > /dev/null; do sleep 0.3; done + PICKED="$( + printf %b "$icon_phn Pickup\n$icon_phx Hangup\n$icon_mut Mute\n" | + dmenu -c -l 5 -p "$CONTACTNAME" + )" + + if echo "$PICKED" | grep -q "Pickup"; then + pickup "$1" + elif echo "$PICKED" | grep -q "Hangup"; then + hangup "$1" + elif echo "$PICKED" | grep -q "Mute"; then + mute "$1" + fi +} + modem_n || finish "Couldn't determine modem number - is modem online?" -"$@" + +sxmo_proximitylock.sh & +LOCKPID="$!" + +"$@" & +MAINPID="$!" +wait $MAINPID diff --git a/scripts/modem/sxmo_modemmonitor.sh b/scripts/modem/sxmo_modemmonitor.sh index bbac2fc..1f64631 100755 --- a/scripts/modem/sxmo_modemmonitor.sh +++ b/scripts/modem/sxmo_modemmonitor.sh @@ -72,31 +72,44 @@ checkforfinishedcalls() { ); do FINISHEDNUMBER="$(lookupnumberfromcallid "$FINISHEDCALLID")" mmcli -m "$(modem_n)" --voice-delete-call "$FINISHEDCALLID" - rm -f "$NOTIFDIR/incomingcall_${FINISHEDCALLID}_notification"* #there may be multiple actionable notification for one call - if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/missed_call" ]; then - echo "sxmo_modemmonitor: Invoking missed call hook (async)">&2 - "$XDG_CONFIG_HOME/sxmo/hooks/missed_call" "$CONTACTNAME" & - fi + rm -f "$CACHEDIR/${FINISHEDCALLID}.monitoredcall" TIME="$(date --iso-8601=seconds)" mkdir -p "$LOGDIR" if [ -f "$CACHEDIR/${FINISHEDCALLID}.discardedcall" ]; then + #this call was discarded echo "sxmo_modemmonitor: Discarded call from $FINISHEDNUMBER">&2 rm -f "$CACHEDIR/${FINISHEDCALLID}.discardedcall" printf %b "$TIME\tcall_discarded\t$FINISHEDNUMBER\n" >> "$LOGDIR/modemlog.tsv" elif [ -f "$CACHEDIR/${FINISHEDCALLID}.pickedupcall" ]; then #this call was picked up - pkill -f sxmo_modemcall.sh #kill call (softly) in case it is still in progress (remote party hung up) + pkill -f sxmo_modemcall.sh echo "sxmo_modemmonitor: Finished call from $FINISHEDNUMBER">&2 rm -f "$CACHEDIR/${FINISHEDCALLID}.pickedupcall" printf %b "$TIME\tcall_finished\t$FINISHEDNUMBER\n" >> "$LOGDIR/modemlog.tsv" + elif [ -f "$CACHEDIR/${FINISHEDCALLID}.hangedupcall" ]; then + #this call was hanged up + echo "sxmo_modemmonitor: Finished call from $FINISHEDNUMBER">&2 + rm -f "$CACHEDIR/${FINISHEDCALLID}.hangedupcall" + printf %b "$TIME\tcall_finished\t$FINISHEDNUMBER\n" >> "$LOGDIR/modemlog.tsv" + elif [ -f "$CACHEDIR/${FINISHEDCALLID}.mutedring" ]; then + #this ring was muted up + echo "sxmo_modemmonitor: Muted ring from $FINISHEDNUMBER">&2 + rm -f "$CACHEDIR/${FINISHEDCALLID}.mutedring" + printf %b "$TIME\tring_muted\t$FINISHEDNUMBER\n" >> "$LOGDIR/modemlog.tsv" else #this is a missed call # Add a notification for every missed call + pkill -f sxmo_modemcall.sh echo "sxmo_modemmonitor: Missed call from $FINISHEDNUMBER">&2 printf %b "$TIME\tcall_missed\t$FINISHEDNUMBER\n" >> "$LOGDIR/modemlog.tsv" + if [ -x "$XDG_CONFIG_HOME/sxmo/hooks/missed_call" ]; then + echo "sxmo_modemmonitor: Invoking missed call hook (async)">&2 + "$XDG_CONFIG_HOME/sxmo/hooks/missed_call" "$CONTACTNAME" & + fi + CONTACT="$(lookupcontactname "$FINISHEDNUMBER")" sxmo_notificationwrite.sh \ random \ @@ -113,7 +126,10 @@ checkforincomingcalls() { grep -Eo '[0-9]+ incoming \(ringing-in\)' | grep -Eo '[0-9]+' )" - echo "$VOICECALLID" | grep -v . && rm -f "$NOTIFDIR/incomingcall*" && return + [ -z "$VOICECALLID" ] && return + + [ -f "$CACHEDIR/${VOICECALLID}.monitoredcall" ] && return # prevent multiple rings + touch "$CACHEDIR/${VOICECALLID}.monitoredcall" #this signals that we handled the call # Determine the incoming phone number echo "sxmo_modemmonitor: Incoming Call:">&2 @@ -131,16 +147,7 @@ checkforincomingcalls() { mkdir -p "$LOGDIR" printf %b "$TIME\tcall_ring\t$INCOMINGNUMBER\n" >> "$LOGDIR/modemlog.tsv" - sxmo_notificationwrite.sh \ - "$NOTIFDIR/incomingcall_${VOICECALLID}_notification" \ - "sxmo_modemcall.sh pickup '$VOICECALLID'" \ - none \ - "Pickup - $CONTACTNAME" & - sxmo_notificationwrite.sh \ - "$NOTIFDIR/incomingcall_${VOICECALLID}_notification_discard" \ - "sxmo_modemcall.sh hangup '$VOICECALLID'" \ - none \ - "Discard - $CONTACTNAME" & + sxmo_modemcall.sh incomingcallmenu "$VOICECALLID" & echo "sxmo_modemmonitor: Call from number: $INCOMINGNUMBER (VOICECALLID: $VOICECALLID)">&2 }