49

I would like to have alarms set off based on org-mode events associated with specific times (or start times). Ideally these would be audio and visual, and able to be customised to some extent. I used to use Sauron, but I can't get it to work with org-mode events (or email notificiations) anymore. What are other good methods?

(I'm particularly interested in having the notification be displayed not only on screen via the notification daemon, but also spoken (text-to-speech). I'm on Linux.)

emacsomancer
  • 1,011
  • 1
  • 9
  • 16
  • 2
    Possibly related to [any tools for making UI-based or email-based DEADLINE notifications in org-mode?](http://emacs.stackexchange.com/q/3749/2355). – Constantine Nov 24 '14 at 02:34
  • @Constantine - this seems rather different to me. I'm not asking for tools for making this, but rather ready-made solutions that already exist. Further, I'm actually interested not in alarms for DEADLINEs, but rather for events associated with (start) times. – emacsomancer Nov 24 '14 at 02:37
  • OK; I edited my comment. (I think we both agree that your question is related to the one I linked to.) – Constantine Nov 24 '14 at 02:41
  • 1
    Related: http://emacs-fu.blogspot.nl/2009/11/showing-pop-ups.html – abo-abo Nov 24 '14 at 18:00
  • Also possibly related: http://web.archiveorange.com/archive/v/Fv8aAIDRK3ey3dBnAi9k – emacsomancer Nov 25 '14 at 05:14
  • 2
    If you have use the builtin appt system to import appointments from your org-agenda files using the function `org-agenda-to-appt`. Then you can customize `appt-disp-window-function` to notify you the way you want (which can include calling external programs). – Iqbal Ansari Nov 30 '14 at 12:30
  • @emacsomancer: for the benefit of future readers, if the answer below addresses your question, shouldn't you accept it? – scaramouche Jan 07 '15 at 18:01

3 Answers3

20

I am quite happy with the system I use, which does (I think) exactly what you want. It has two parts: an Emacs part that uses appt.el to schedule the reminders and a small shell program (I'm using Linux) that creates the popup + sound notification. Here I share the code for both parts.

A) Code in ~/.emacs.d/init.el

(require 'appt)
(appt-activate t)

(setq appt-message-warning-time 5) ; Show notification 5 minutes before event
(setq appt-display-interval appt-message-warning-time) ; Disable multiple reminders
(setq appt-display-mode-line nil)

; Use appointment data from org-mode
(defun my-org-agenda-to-appt ()
  (interactive)
  (setq appt-time-msg-list nil)
  (org-agenda-to-appt))

; Update alarms when...
; (1) ... Starting Emacs
(my-org-agenda-to-appt)

; (2) ... Everyday at 12:05am (useful in case you keep Emacs always on)
(run-at-time "12:05am" (* 24 3600) 'my-org-agenda-to-appt)

; (3) ... When TODO.txt is saved
(add-hook 'after-save-hook
          '(lambda ()
             (if (string= (buffer-file-name) (concat (getenv "HOME") "/ideas/TODO.txt"))
                 (my-org-agenda-to-appt))))

; Display appointments as a window manager notification
(setq appt-disp-window-function 'my-appt-display)
(setq appt-delete-window-function (lambda () t))

(setq my-appt-notification-app (concat (getenv "HOME") "/bin/appt-notification"))

(defun my-appt-display (min-to-app new-time msg)
  (if (atom min-to-app)
    (start-process "my-appt-notification-app" nil my-appt-notification-app min-to-app msg)
  (dolist (i (number-sequence 0 (1- (length min-to-app))))
    (start-process "my-appt-notification-app" nil my-appt-notification-app (nth i min-to-app) (nth i msg)))))

B) Code in ~/bin/appt-notification

#!/bin/sh

TIME="$1"
MSG="$2"

notify-send -t 0 "<br>Appointment in $TIME minutes:<br>$MSG<br>"
play "~/bin/alarm.wav"

To get voice notifications you could replace the last line (play) with the following:

espeak "Appointment in $TIME minutes: $MSG"
holocronweaver
  • 1,319
  • 10
  • 22
scaramouche
  • 1,772
  • 10
  • 24
  • I added a case for auto-updating appts when quitting org-agenda: `; (4) ... Quitting org-agenda. (advice-add 'org-agenda-quit :after #'hw-org-agenda-to-appt)` – holocronweaver Oct 11 '16 at 16:03
  • Note: updating around midnight is important for night owls since `org-agenda-to-appt` only creates appts for current day. – holocronweaver Oct 11 '16 at 16:12
  • +1 This is great. Thank you for sharing. I have modified this a little to use [alert.el](https://github.com/jwiegley/alert) instead. One question, though: have you ever had any luck getting it to work with the org "APPT_WARNTIME" property to set a custom warning time for each event? I can't seem to get it to work. – Joseph R. Apr 26 '19 at 05:33
12

You can use notifications in Emacs > 24:

(require 'notifications)

(notifications-notify :title "Achtung!"
                      :body (format "You have an appointment in %d minutes" 10)
                      :app-name "Emacs: Org"
                      :sound-name "alarm-clock-elapsed")
Scott Weldon
  • 2,695
  • 1
  • 17
  • 31
ungawa
  • 129
  • 1
  • 2
4

This is what I ended up coming up with:

;;; org-to-appt

;; based on http://emacs-fu.blogspot.nl/2009/11/showing-pop-ups.html
(defun talky-popup (title msg &optional icon sound)  
  "Show a popup if we're on X, or echo it otherwise; TITLE is the title
of the message, MSG is the context. Optionally, you can provide an ICON and
a sound to be played"

  (interactive)
  ;;verbal warning



  (shell-command
   ;;  (concat "espeak -v mb-en1 -k5 -s125 " "'" title " " msg "'" " --stdout | paplay") ;; use local espeak
   (concat "echo " "'" title "'" " " "'" msg "'" " |text-to-speech en-gb")  ;; use remote Google voices
    ;; text-to-speech is from https://github.com/taylorchu/speech-to-text-text-to-speech
   )
  (if (eq window-system 'x)
    (shell-command (concat "notify-send -u critical -t 1800000  " 

                     (if icon (concat "-i " icon) "")
                     " '" title "' '" msg "'"))
    ;; text only version

    (message (concat title ": " msg))))

;; the appointment notification facility
(setq
  appt-message-warning-time 15 ;; warn 15 min in advance

  appt-display-mode-line t     ;; show in the modeline
  appt-display-format 'window) ;; use our func
(appt-activate 1)              ;; active appt (appointment notification)
(display-time)                 ;; time display is required for this...

 ;; update appt each time agenda opened

(add-hook 'org-finalize-agenda-hook 'org-agenda-to-appt)

;; our little façade-function for talky-popup
 (defun talky-appt-display (min-to-app new-time msg)
    (talky-popup (format "In %s minute(s):" min-to-app) msg 
  ;;    "/usr/share/icons/gnome/32x32/status/appointment-soon.png"   ;; optional icon

  ;;    "/usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg"    ;; optional sound

        ))
  (setq appt-disp-window-function (function talky-appt-display))

It's not dissimilar to scaramouche's setup.

Scott Weldon
  • 2,695
  • 1
  • 17
  • 31
emacsomancer
  • 1,011
  • 1
  • 9
  • 16