CL-Growl Client Library April 12th, 2010
Patrick Stein

Growl is a notification system for Mac OS X. Growl supports a small network protocol over UDP called Growl Talk. This is a Common Lisp client library for communicating with Growl.

Obtaining the code

Usage

Before your application can start sending messages to Growl, it needs to register the notification types it intends to send. On the receiving end, the message display can be customized based on the notification type. Here is a simple example showing all of the available options for an application called My Lisp Application with three types of message (Info, Warn, and Error) where Info messages are not displayed unless you tweak your Growl preferences to display them.

(growl:register :app "My Lisp Application"
                :enabled (list "Warn" "Error")
                :disabled (list "Info")
                :host "localhost"
                :port 9887
                :checksum-mode :sha256
                :password "my-growl-password")

After the application has been registered once (from anywhere, in any process), you can send a message Cannot connect to database! with title Critical Error of type Error with priority 2 that will stay showing on the receiving desktop with:

(growl:notify "Cannot connect to database!"
              :app "My Lisp Application"
              :title "Critical Error"
              :notification "Error"
              :priority 2
              :sticky t
              :host "localhost"  
              :port 9887
              :checksum-mode :sha256
              :password "my-growl-password")

Almost all of those parameters derive their defaults from special variables that you can rebind for your application. For example, you could do both of the above like this (initial values shown in comments after each binding):

(let ((growl:*growl-default-host* "localhost")
                              ;; "localhost"                                    
      (growl:*growl-default-port* 9887)
                              ;; 9887                                          
      (growl:*growl-default-app* "My Lisp Application")
                              ;; "Common Lisp program"                          
      (growl:*growl-default-enabled-notifications* (list "Warn" "Error"))
                              ;; (list "Common Lisp notification")              
      (growl:*growl-default-disabled-notifications (list "Info"))
                              ;; (list)                                        
      (growl:*growl-default-title* "Critical Error")
                              ;; ""                                            
      (growl:*growl-default-password* "my-growl-password")
                              ;; ""                                            
      (growl:*growl-default-notification* "Error"))
                              ;; "Common Lisp notification"
  (growl:register)
  (growl:notify "Cannot connect to database!" :priority 2 :sticky t))

For most applications, you will only be calling (REGISTER …) one time but may be calling (NOTIFY …) many times. So, it probably doesn’t make sense to rebind the special variables for the *growl-default-enabled-notifications* and *growl-default-disabled-notifications*.

Note: one specifies the password under the Network panel of the Growl preferences. Check the Allow remote application registration and specify a Server Password.

Dependencies

This package weakly depends on MD5 and Ironclad. If neither are present, this client will not be able to take advantage of the password features of Growl. Consequently, you will not be able to send messages to the Growl host unless its Server Password is blank. If Ironclad is available, then the :sha256 checksum mode will be the default (and :md5 and :noauth are other possible choices). If Ironclad is not available but MD5 is, then the :md5 checksum mode will be the default (and :noauth is the only other choice). If neither is present, the checksum mode can only be :noauth. With :noauth, the password is ignored.

This package depends explicitly on trivial-utf-8, usocket-udp, and flexi-streams.