---
Davin Pearson http://davin.50webs.com
(require 'd-time)
(progn
  (setq meal-timer--on nil)
  (setq meal-timer--stopped-time nil)
  (setq meal-timer--foo nil)
  (setq meal-timer--secs nil)
  (setq meal-timer--filename "~/.meal-timer.el")
  (setq meal-timer--added-mma nil)
  (setq meal-timer--timer nil)
  (setq meal-timer--paused nil)
  (setq meal-timer--last-command-pause nil)
  (setq meal-timer--last-command-on    nil)
  )
(defun meal-timer (minutes)
  (interactive "nEnter Meal Timer (minutes): ")
  (let ((seconds nil))
            (if (< minutes 0)
        (error "You cannot enter a negative time"))
        (setq seconds (* 60.0 minutes))
    (setq meal-timer--duration (d-seconds-to-readable-string seconds nil t))
    (setq meal-timer--secs seconds)
                    (start-meal-timer seconds)
    ))
(defmacro d-with-buffer (buf &rest x)
  `(save-excursion
     (find-file (eval ,buf))
     (goto-char (point-min))
     (progn ,@x)
     (save-buffer)
     (kill-buffer)
     t
     ))
(defun stop-meal-timer ()
  (interactive)
  (cond
   (meal-timer--last-command-on
    (setq meal-timer--last-command-on nil))
   (t
    (d-error "Tried to stop timer while timer is already stopped")))      (setq meal-timer--on nil)
  (setq meal-timer--secs         (d-seconds-of-time-difference
         meal-timer--stopped-time (current-time)))
  (if meal-timer--timer (cancel-timer meal-timer--timer))
  (setq meal-timer--stopped-time nil)
  (setq meal-timer--foo nil)
    (when (file-exists-p meal-timer--filename)
    (delete-file meal-timer--filename))
  )
(defun start-meal-timer (secs)
  (interactive)
  (cond
   ((not meal-timer--last-command-on)
    (setq meal-timer--last-command-on t))
   (t
    (d-error "Tried to start timer while timer is already started")))
  (setq meal-timer--on t)
    (setq meal-timer--stopped-time (current-time))
  (setq meal-timer--stopped-time (d-add-seconds secs meal-timer--stopped-time))
      (setq meal-timer--secs secs)
  (setq meal-timer--duration (d-seconds-to-readable-string meal-timer--secs nil t))
    (setq meal-timer--timer (run-with-timer meal-timer--secs nil 'meal-timer-function))
    (meal-timer-save)
  )
(defun meal-timer-function ()
      (stop-meal-timer)
  (setq meal-timer--on           nil)
  (setq meal-timer--stopped-time nil)
  (setq meal-timer--secs         nil)
  (setq meal-timer--foo          nil)
  (setq meal-timer--paused       nil)
  (cancel-timer meal-timer--timer)
  (if (fboundp 'd-fonts) (d-fonts))
  (sit-for 1)
  (let (f)
    (setq f "completed-meal-timer.wav")
    (if (file-exists-p f)
        (play-sound (list 'sound :file f :volume .99)))
    (setq f "c:/sound-samples/emacs/completed-meal-timer.wav")
    (if (file-exists-p f)
        (play-sound (list 'sound :file f :volume .99)))
    (setq f "/media/www/C1TB/sound-samples/emacs/completed-meal-timer.wav")
    (if (file-exists-p f)
        (play-sound (list 'sound :file f :volume 1.0)))
    )
  (d-beeps "Meal timer expired at %s elasped=%s" (d-time--get-stamp) meal-timer--duration)
  (if (fboundp 'd-fonts) (d-fonts))
  (redraw-display)
  )
(when (not meal-timer--added-mma)
  (setq minor-mode-alist (cons '(:eval (meal-timer-get-string)) minor-mode-alist))
  (setq meal-timer--added-mma t))
(defun meal-timer-save ()
  (d-with-buffer
   meal-timer--filename
   (erase-buffer)
   (goto-char (point-min))
      (insert "(progn\n"
                      )
   (insert "  (setq meal-timer--stopped-time " (prin1-to-string (d-decode-time meal-timer--stopped-time)) ")\n")
   (insert "  (setq meal-timer--on nil)\n")
   (insert "  (setq meal-timer--paused " (format "%s" meal-timer--paused) "))\n")
   ))
(defun pause-meal-timer ()
  (interactive)
  (cond
   ((and (not meal-timer--last-command-pause) meal-timer--last-command-on)
    (setq meal-timer--last-command-pause t))
   ((not meal-timer--last-command-on)
    (d-error "Tried to pause while timer is off"))
   (t
    (d-error "Tried to pause while last pause is false")))
  (when meal-timer--timer
    (d-assert (timerp meal-timer--timer))
    (cancel-timer meal-timer--timer))
    (setq meal-timer--secs
        (d-seconds-of-time-difference (current-time) meal-timer--stopped-time))
  (setq meal-timer--on nil)
  (setq meal-timer--foo (concat " Paused:" meal-timer--foo))
  )
(defun unpause-meal-timer (&optional not-do-run-timer)
  (interactive)
  (cond
   ((and meal-timer--last-command-pause meal-timer--last-command-on)
    (setq meal-timer--last-command-pause t))
   ((not meal-timer--last-command-on)
    (d-error "Tried to unpause while timer is off"))
   (t
    (d-error "Tried to unpause while last pause is true")))
  (when (not not-do-run-timer)
    (setq meal-timer (run-with-timer meal-timer--secs nil 'meal-timer-function)))
  (setq meal-timer--stopped-time (d-add-seconds meal-timer--secs (current-time)))
  (setq meal-timer--on t)
    (when (file-exists-p meal-timer--filename)
    (delete-file meal-timer--filename))
  )
(defun meal-timer-get-string-inner ()
  (let* ((count (d-seconds-of-time-difference (current-time) meal-timer--stopped-time))
         (count (floor count))
         (str (d-seconds-to-readable-string count nil t)))
    (format " Timer=(%s/%s)" str meal-timer--duration)))
(defun meal-timer-get-string ()
  (if meal-timer--on
      (setq meal-timer--foo (meal-timer-get-string-inner))
    meal-timer--foo)
    )
(run-with-timer 1 1 'force-mode-line-update)
(defun meal-timer-init ()
  (when (file-exists-p meal-timer--filename)
    (message "**** ran meal-timer-init")
    (setq meal-timer--stopped-time nil)
    (setq meal-timer--secs nil)
    (setq meal-timer--on nil)
    (setq meal-timer--paused nil)
    (setq ready-to-start nil)
    (load-file meal-timer--filename)
                    (when (and meal-timer--stopped-time (stringp meal-timer--stopped-time))
      (setq meal-timer--stopped-time
            (d-encode-time meal-timer--stopped-time))
      (setq secs (d-seconds-of-time-difference (current-time) meal-timer--stopped-time))
      (setq meal-timer--secs secs)
      (setq ready-to-start t))
    (when meal-timer--secs
      (setq secs meal-timer--secs)
      (setq meal-timer--stopped-time (d-add-seconds secs (current-time)))
      (setq ready-to-start t))
    (setq meal-timer--duration (d-seconds-to-readable-string secs nil t))
    (if (and ready-to-start
             (> secs 0)
             (time-newer-than-time meal-timer--stopped-time (current-time)))
        (start-meal-timer secs)
      (setq meal-timer--on nil))
    (if meal-timer--paused
        (pause-meal-timer)
      (unpause-meal-timer t))
    )
  )
(meal-timer-init)
(defadvice kill-emacs (before meal-timer activate)
  (let (t1)
    (when (and (boundp 'meal-timer--secs)
               meal-timer--secs)
      (d-with-buffer
       meal-timer--filename
       (progn
         (setq t1 (current-time))
         (d-assert (boundp 'meal-timer--secs))
         (setq t1 (d-add-seconds meal-timer--secs t1))
         (erase-buffer)
         (insert "(progn\n"
                 "  (setq meal-timer--stopped-time " (prin1-to-string
                                                      (d-decode-time t1)) ")\n"
                 "  (setq meal-timer--on t))\n")))
      )))
(provide 'meal-timer)
(d-quote
 (progn
   (setq mtr (run-with-timer 10 10 'd-foo))
   (cancel-timer mtr)
   (timerp mtr))
 )