# 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
#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
#
}
+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=$$
while true; do
if [[ $(lastActivity) != "null" ]]; then
$BEEP > /dev/null 2>&1
- sleep 0.8
+ sleep $DELAY
fi
(sampleTask) &
pid=$!
# 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