A few years ago I would constantly burn whatever I was cooking. The story was always the same: I would put something on the stove, go back to the computer, and wait until the smoke detector reminded me I had burned dinner, again. Eventually I wrote a simple bash script using zenity to act as a sort of egg timer. My timer is linked to meta-T. Once called it prompts you to type in the number of minutes you want to be reminded in. This worked very well and I haven't burned any food in years! After a while though, I wanted a few more features.




timer.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #!/bin/bash #Mark Feineigle 2014 03 14 #Wait x time, then play sound/note & prompt for input. On input "0" close, on input "-ge 1" loop END_SOUND="/home/egg/.sounds/river_done.wav" #FUNCTIONS timer () { while [ $TIME -ge 1 ] 2>/dev/null #loop while TIME >0 do if [ $1 == "-m" ]; then let TIME=$TIME*60 #multiply for minutes TITLE="Minutes";TEXT="minutes" #set labels for use in zenity else TITLE="Seconds";TEXT="seconds" #set labels for use in zenity fi sleep $TIME #sleep for TIME aplay $END_SOUND > /dev/null 2>&1 & #play sound, suppress output, run in background if [ $NOTE != "" ] 2>/dev/null; then #if there is a NOTE, display it zenity --title="Reminder" --info --text="$NOTE" fi export TIME=`zenity --title="$TITLE" --entry --text="More $TEXT?"` #input TIME from GUI if [ $TIME == "0" -o $TIME == "" ] 2>/dev/null; then #if TIME = 0 of null exit 0 fi NOTE="" #clear old note if [ $TIME -ge 11 ] 2>/dev/null; then #if TIME is longer than x export NOTE=`zenity --title="Reminder" --entry --text="Note?"` # input NOTE from GUI fi done exit 0 } #START OF MAIN if [ "$1" == "-s" -a "$2" -ge 1 ] 2>/dev/null; then #if the 1st arg is "-s" and #the 2nd arg is >=1 TIME="$2";NOTE="$3" #set 2nd/3rd args as TIME/NOTE timer $1 #pass $1 (-s) to timer function elif [ "$1" == "-s" -a "$2" == "" ]; then #if no 2nd arg export TIME=`zenity --title="Seconds" --entry --text="How many seconds?"` #read SECONDS if [ $TIME == "0" -o $TIME == "" ] 2>/dev/null; then #if 0 or null exit 0 fi if [ $TIME -ge 3 ] 2>/dev/null; then #if TIME longer than x export NOTE=`zenity --title="Reminder" --entry --text="Note?"` # add NOTE from GUI fi timer $1 #$TIME $NOTE #call timer function, exported TIME/NOTE = no passing needed? elif [ "$1" == "-m" -a "$2" -ge 1 ] 2>/dev/null; then #if 1st arg is "-m" and 2nd arg is >0 TIME="$2";NOTE="$3" #set 2nd/3rd args as TIME/NOTE timer $1 #pass $1 (-m) to timer function elif [ "$1" == "-m" -a "$2" == "" ]; then #GUI prompt for integer #return MINUTES from GUI export TIME=`zenity --title="Minutes" --entry --text="How many minutes?"` if [ $TIME == "0" -o $TIME == "" ] 2>/dev/null; then #if 0 of null exit 0 fi if [ $TIME -ge 9 ] 2>/dev/null; then #if TIME longer than x # add NOTE from GUI export NOTE=`zenity --title="Reminder" --entry --text="Note?"` fi timer $1 #$TIME $NOTE #call timer function, exported TIME/NOTE = no passing needed? elif [ "$1" -ge 1 ] 2>/dev/null; then #if 1st arg is >0 TIME="$1";NOTE="" #set TINE as 1st arg, NOTE as null timer -m #call timer function with $1 = "=m" else printf "minutes usage = $0 [MINUTES]\n" printf " = $0 -m [MINUTES]\n\n" #display help on any non-defined useage printf "seconds usage = $0 -s [SECONDS]\n\n" printf "this help = $0 -h\n" printf " = $0 --help\n\n" fi exit 0 |
Finding an excuse to learn some Qt, I wrote a new version of the timer in python. This version works much the same way, but with a few extra features. After an alarm sounds the program starts counting up, letting you know how long ago the initial alarm sounded. Next, it emits its alarm sound every 5 minutes after the initial alarm sounds. This isn't too important when used as an egg timer, but now it can be issued a 0 minute timer that alerts immediately and then counts up. It keeps track of how long has been spent on a particular task and also sounds off with 5 minute metering.


timer.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | #!/usr/bin/env python #Author: Mark Feineigle #Create Date: 2016/08/21 #Last Modify: 2016/08/22 ''' A replacement for my bash timer script, timer.sh ''' #TODO: better variable names # layout # hide title bar DONE # disables esc to close # icon # highlight tab order import commands #use aplay to play sound import sys #argv for qt from PyQt4 import QtGui, QtCore import time #asctime END_SOUND = "/home/USER/.sounds/quiet_river_done.wav" class myDialog(QtGui.QDialog): '''The 'main' timer window''' def __init__(self, parent=None): super(myDialog, self).__init__(parent) #variables self.counter = 0 #counter self.flag = False #flag for counting or not #text inputs self.inp = QtGui.QLineEdit("0") self.connect(self.inp, QtCore.SIGNAL("returnPressed()"), self.sleepTimerOn) self.note = QtGui.QLineEdit("Note") self.connect(self.note, QtCore.SIGNAL("returnPressed()"), self.sleepTimerOn) #buttons #NOTE this button has no purpose, without it the first button created is # called after sleepTimerOn, no idea... #NOTE now that i've broken sleep into 2 functions, this is required to not # start the counter when a non-int is entered... #NOTE adding a quit button seems to work... self.countbtn = QtGui.QPushButton("Quit", self) #TODO how to link to esc? self.connect(self.countbtn, QtCore.SIGNAL("escapePressed()"), self.quit) #self.countbtn.hide() self.countbtn.clicked.connect(self.quit) self.startbtn = QtGui.QPushButton("On/Off", self) self.startbtn.clicked.connect(self.countToggle) self.sleepbtn = QtGui.QPushButton("Sleep", self) self.sleepbtn.clicked.connect(self.sleepTimerOn) #labels self.msgLbl = QtGui.QLabel("") t = self.formatTime(self.counter) self.counterLbl = QtGui.QLabel( "<font color=white size=6 style='font-family:Monospace;'><b>" +str(t)+ "</b></font>") #grid grid = QtGui.QGridLayout() grid.addWidget(self.counterLbl, 1, 2) #matplot like coords #TODO better layout for changing label size grid.addWidget(self.msgLbl, 1, 1) #matplot like coords grid.addWidget(self.inp, 1, 4) #matplot like coords grid.addWidget(self.note, 2, 1) #matplot like coords grid.addWidget(self.countbtn, 2, 2) grid.addWidget(self.startbtn, 2, 3) grid.addWidget(self.sleepbtn, 2, 4) self.setLayout(grid) self.setWindowTitle("Tick tock mother fucker") self.inp.setFocus() self.show() def sleepTimerOn(self): '''Connected to sleepbtn and inp box. Hides the window and sleeps.''' #print self.flag, "1" self.startTime = time.asctime().split()[3] try: t = int(self.inp.displayText()) #get input self.hide() #if successful in converting to input to int QtCore.QTimer.singleShot(t*60*1000, self.sleepTimerOff) #wait milliseconds then..loop except: sys.exit() #input was not an int finally: self.inp.setFocus() def sleepTimerOff(self): '''Called from sleepTimerOn Resets counter when it wakes up.''' self.stopTime = time.asctime().split()[3] msg = "Slept {} mins\n{}\n{}".format(self.inp.displayText(), self.startTime, self.stopTime) self.msgLbl.setText(msg) self.counter = 0 #start counting up from 0 after timer expires #print self.flag, "2" if self.flag == False: self.countToggle() commands.getoutput("aplay "+END_SOUND) self.show() #print self.flag, "7" def countToggle(self): '''Connected to startbtn''' #print self.flag, "3" self.flag = not self.flag if self.flag: self.countUp() #print self.flag, "6" def countUp(self): '''Counting loop''' #print self.flag, "4" if self.flag: self.counter+=1 if not self.counter%300: print "minute passed" commands.getoutput("aplay "+END_SOUND) t = self.formatTime(self.counter) self.counterLbl.setText( "<font color=white size=6 style='font-family:Monospace'><b>" +str(t)+ "</b></font>") QtCore.QTimer.singleShot(1000, self.countUp) #counts the (milli)seconds #print self.flag, "5" def formatTime(self, t): '''Helper to display nicely formatted times''' minutes = t/60 seconds = t%60 if seconds < 10: seconds = "0"+str(seconds) return str(minutes)+":"+str(seconds) def quit(self): sys.exit() def main(): app = QtGui.QApplication(sys.argv) myDia = myDialog() #TODO hide titlebar # add icon #TODO highlight selected element w/ tab #myDia.setWindowFlags(QtCore.Qt.SplashScreen) #hides the default titlebar #TODO center window on screen and link esc #TODO spacebar to start/stop button myDia.show() app.exec_() if __name__ == '__main__': main() |
2016-10-02 07:38:33
[I am He-Man!]2016-10-07 01:23:36
[I am He-Man!]2016-10-07 01:26:55
[I am He-Man!]2016-10-15 01:26:35
[I am He-Man!]