timeSampler: add ability to cleanup windows by sending SIGUSR1
authorDan White <dan@whiteaudio.com>
Fri, 10 Aug 2018 18:56:22 +0000 (13:56 -0500)
committerDan White <dan@whiteaudio.com>
Fri, 10 Aug 2018 18:56:22 +0000 (13:56 -0500)
timeSampler

index 522f023a62ea7e1a4922687796bea211e3577469..c9f1625b7b9802d813ff30e6429c674158f7cf92 100755 (executable)
@@ -2,31 +2,47 @@
 
 # fire off subshells which periodically ask for what I am
 # currently doing.  Subshells keep the periodicity independent
-# of response time to the script
+# of response time to the script.
+#
+# Sending the PID of the main script (stored in ~/.timesampler.pid)
+# a SIGUSR1 signal will kill all open windows.  Useful when returning from time
+# away from the desktop.
 #
 # Depends:
 #   * sound player (edit BEEP)
 #   * "at" utility (debian: apt-get install at)
+#   * zenity
 #
-# (C) 2010--2016 Dan White <dan@whiteaudio.com> under GPLv3
+# (C) 2010--2018 Dan White <dan@whiteaudio.com> under GPLv3
 
 # idea from: http://wiki.43folders.com/index.php/Time_sampling
 
 #
 # Various ways to make a beep sound
 #
+# Modify BEEP to fit your environment and choice of sound.
+#
 #BEEP="beep -f707 -n -f500"
 #BEEP="beep -f707 -n -f500 -n -f707"
 #BEEP="dcop knotify default notify notify Me notext KDE_Vox_Ahem.ogg nofile 1 0"
 #BEEP="play /home/dan/tmp/pop.wav"
-BEEP="aplay /home/dan/tmp/pop.wav"
+#BEEP="aplay /home/dan/tmp/pop.wav"
+
+# works as long as the last component isn't a symlink
+THISDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+BEEP="aplay $THISDIR/pop.wav"
+
+
+# the delay time between playing the sound and showing the window
+# which makes it easy to hear the pop, pause typing, then dismiss the window
+# when in the middle of otherwise typing
+DELAY=0.8
 
 #
 # Interval between popups
 #
 MINUTES=6 #to give 10/hour
 
-#
 # Only allow this many popups active at a time.  Overnight or long away-from-
 # computer intervals don't clog the UI.
 #MAXJOBS=$((1*60/$MINUTES))  #as number of hours
@@ -48,11 +64,29 @@ BACKUPFILE="$HOME/.timeSampler.all"
 #index of the last buffer entry
 BUFFER_END=$(($MAXJOBS-1))
 
-#put something in the buffer to start
-for i in $(seq 0 $BUFFER_END); do
-    buffer[$i]="$i"
+
+# find the largest positive integer we can store
+# make sure it is larger than the kernel's max PID
+# use this number as a fake PID to fill the buffer
+MAX_PID=$(cat /proc/sys/kernel/pid_max)
+for i in $(seq 31 128); do
+    N=$(( (2**i) - 1 ))
+    if [ $N -lt 0 ]; then 
+        break
+    else
+        if [ $N -gt $MAX_PID ]; then
+            FAKE_PID=$N
+        else
+            echo "Cannot find a suitable fake process ID, aborting!"
+            exit 1
+        fi
+    fi
 done
+echo "fake PID: $FAKE_PID"
 
+for i in $(seq 0 $BUFFER_END); do
+    buffer[$i]=$FAKE_PID
+done
 
 
 #
@@ -131,6 +165,17 @@ function fifoPushKillOldest {
 }
 
 
+function cleanup {
+    # Kill all running dialogs
+    echo "caught signal!"
+    for i in $(seq 0 $BUFFER_END); do
+        fifoPushKillOldest $FAKE_PID
+    done
+}
+
+# Sending the main process a USR1 signal will close all open dialogs
+trap cleanup SIGUSR1
+
 
 
 thispid=$$
@@ -139,7 +184,7 @@ echo "$thispid" > ~/.timeSampler.pid
 while true; do
     if [[ $(lastActivity) != "null" ]]; then
         $BEEP > /dev/null 2>&1
-        sleep 0.8
+        sleep $DELAY
     fi
     (sampleTask) &
     pid=$!
@@ -147,12 +192,15 @@ while true; do
     # store PID in FIFO and kill the oldest
     fifoPushKillOldest $pid
 
+    # Sleep for the majority of the interval so we can catch SIGUSR1 right
+    # away, last number is a fudge factor to ensure we wakeup early enough
+    sleeptime=$(($MINUTES*60 - 5))
+    # using bg + wait allows us to catch signals while waiting
+    sleep $sleeptime &
+    wait $!
 
-    # Old way, sleep for a bit
-    #sleep $(($MINUTES*60 - 1))
-
-    # New way: stop, then send myself a continue at an exact MINUTES boundary
-    #send a continue signal to myself in the future
+    # New way: stop, then send myself a (future) continue at an exact MINUTES
+    # boundary
     echo "kill -CONT $thispid" | at now + $(nexttime) minutes > /dev/null 2>&1
 
     #stop myself, will resume when above "at" command fires