Scripting the display appliance – launchd tasks

Last time, we started to look at automating (or at least scripting) the configuration of the Mac mini display appliance. We set the Energy Saver prefs and set autologin for a certain user.

The central task of this display appliance is to play QuickTime movies full screen at all times. That’s why we configured the machine to auto restart after a power failure, and to autologin a user at boot – all so that the machine can get to a point where it can play movies even if it is ungracefully restarted.

So the meat of the task is a script that actually plays the movies. I chose to implement a launchd task. Originally I just used a cron job that ran once a minute, and that worked okay for the most part. But I have a web interface that allows the operator to select which movie to play. Web CGIs run as the web server user, or www. The autologged in user is not the www user, so there is no way for the Web CGI to _directly_ control QuickTime Player, or any GUI app running as the autologged in user.

So the launchd task, which runs as root, becomes the glue between the Web CGI and QuickTime Player. The web CGI changes which file is to be played. The launchd task sees the change and tells QuickTime Player to play the new file. When the root task was a cron job, it took up to a minute for the change to take effect. In practice, this is probably OK, but makes a terrible demo when showing it to management. So I wanted the task to be able to switch the display faster.

Enter launchd. One of the things launchd can do for you is watch a certain filesystem path for you, and when it changes, run your task. So I wrote the following plist file and saved it in /Library/LaunchDaemons/:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>com.disney.fa.dwupdate</string>
   <key>ProgramArguments</key>
   <array>
      <string>/Library/FA/Scripts/digitalwalkwayupdate.pl</string>
   </array>
   <key>RunAtLoad</key>
   <true/>
   <key>WatchPaths</key>
   <array>
      <string>/Users/Shared/DigitalWalkway/display/</string>
   </array>
   <key>StartInterval</key>
   <integer>60</integer>
</dict>
</plist>

This plist contains several key-value pairs which tell launchd what to do.
The first is Label, which is simply a name for the job.
ProgramArguments is the path to the executable to run, in this case a Perl script.
RunAtLoad tells it to run the job immediately when this definition is loaded.
WatchPaths contains the path to the directory I want launchd to watch for changes. When anything inside this directory changes, the Perl script is run.
StartInterval tells launchd to also run this task every 60 seconds. This makes sure that the movie is played fullscreen even if someone quits QuickTime Player, exits fullscreen, or does something else to interrupt the display.

The result of converting this from a cron job to a launchd job is that when someone uses the Web CGI to change which movie is displayed, the new movie gets displayed within seconds instead of taking up to a minute. This makes for a much better demonstration. This also gives you the option to make the periodic check less frequent (for example, every five minutes) while retaining quick reponse to changes.

Next time: controlling QuickTime from Perl.

Scripting the display appliance – launchd tasks