Controlling the Mac with Java (and a little AppleScript)

A couple of weeks ago, a friend forwarded me this presentation about Scripting in the Java Platform. I didn't get the chance to read through and try out some ideas from the presentation until this weekend. 

My main takeaway from the presentation is developing applications on the Java platform with the right language for the problem. For example, my core business logic (representing the "hard" parts of my architecture) might be built with Java / Scala to provide the additional guarantee of type safety and then utilizing a dynamic language like JRuby, Jython, Groovy et al for scripting, writing unit tests. 

From the presentation I was introduced to a new CLI tool available in Java 6: jrunscript

The -q option shows all the scripting engines available. When I run it on my Mac, 

dc@feynman:jrunscript$ jrunscript -q

Language ECMAScript 1.6 implemention "Mozilla Rhino" 1.6 release 2

Language AppleScript 2.0.1 implemention "AppleScriptEngine" 1.0

ECMAScript was not surprising. I had known that a Javascript interpreter had been embedded in Java 6 for awhile but I found the AppleScript engine interesting. I've always thought that AppleScript was a weird language. Weird but useful on the Mac. If I could use AppleScript to extract data out of applications running on my Mac, I could process the data with Java (or another JVM based language like clojure).

For a first pass, I wanted to make a Java + AppleScript program put up a Growl message. After a quick crash course with AppleScript and Script Editor, I had this:

and on the Java side:

There were a couple of gotchas which I'll summarize.

1) You can't appear to set arbitrary variables with the various Binding/ScriptContext methods. 

2) To pass values, you have to define a "main" function for the script. That's what this line was doing

applescript.put("javax_script_function", "growlNotification");

It set growlNotification as the "main" function for the script.

3) growlNotification has 2 parameters. To pass arguments, I needed to define a List interface and add my two arguments there. This sort of made sense since the key we use to set the binding says "ARGV". When I initially passed my 2 arguments via an array, I received an error message. After a little bit of trial and error, I found that using a List interface worked. The documentation around this is spotty but the use of a List is somewhat intuitive. 

What's next? Possibly doing this with Clojure and learning more about the various application APIs (aka dictionaries in AppleScript parlance). 


Hell Fire for Lunch

Sent from my iPhone

Posted via email from Daniel's posterous


MacPherson Market

An open air market located in the Beacon Hill neighborhood of Seattle.

Sent from my iPhone

Posted via email from Daniel's posterous


Anyone know a good cactus recipe?

Sent from my iPhone

Posted via email from Daniel's posterous


Seen at Whole Foods


How a Clojure pet project turned into a full-blown cloud-computing web-app

Very cool presentation!

Posted via web from Daniel's posterous


First, care. | 43 Folders

So, first, care. Then, as you’ll happily and unavoidably discover, all that “focus” business has a peculiar way of taking care of itself.


Posted via email from Daniel's posterous




Moving to Clojure 1.1

I'm not using the 1.1 features yet but I was planning on it. During the upgrade to clojure 1.1, I broke my emacs, slime and clojure setup. That's a good thing since the process has simplified since the last time I did it.

Here's what I did on my Mac (running Leopard). Git is a requirement. I installed mine through MacPorts.

First, I got myself an emacs starter kit. Since I'm using aquamacs, I went with an aquamacs variant of the starter kit. Aquamacs Emacs Starter Kit vs Emacs Starter Kit . Follow the instructions for installing the appropriate emacs starter kit. It should look something like this:


In this process I learnt a little about Aquamacs. The dot emacs file aka ~/.emacs  are read after the preferences that are under  ~/Library/Preferences/Aquamacs Emacs. Since I mostly used Aquamacs for hacking clojure, I didn't care and nuked all my emacs preferences. Your mileage may vary. Afterward your Preferences.el file should look like this:

Restart Aquamacs to ensure the new preferences get taken.

One of the important things the Emacs Starter Kit installs is the package manager for emacs (aka elpa). I used elpa to install the swank-clojure package. The starter kit also defaults Aquamacs to green text on a black background (changing that is left as an exercise to the reader).

You don't need to but I wanted to check out the packages available to be installed. The M key below is the meta key which on my Mac is bound to the Option and Esc key. Your key bindings might be set up differently but I would try the Option or Esc key to start with.


This is what the package list looks like.
To install a package, I used the package-install command.


You'll be prompted for the package to install.

You'll see some text scrolling by in a buffer. It looks like various emacs lisp files are being compiled. I got some errors. I ignored them. It seemed alright.

Once swank-clojure is installed, it's time to install clojure. To do this, I started up slime.


You'll get prompted about clojure not being installed. You want to say yes here.


You'll see some status messages about clojure getting installed. For reference purposes, this process installs clojure, contrib and swank clojure jars in ~/.swank-clojure Voila_Capture27  

Once that's completed, restart Aquamacs and type   'M-x slime' . You should now be ready to hack clojure code.

If you need a custom classpath, you'll need to set the  swank-clojure-classpath variable. I created a directory containing all my jar files (in ~/.emacs.d/clojure ) and have all the jar files there available in my slime session. To do this, my ~/.emacs file contains the following lines:

(setq swank-clojure-classpath 


       (directory-files "~/.swank-clojure" t ".jar$")

       (directory-files "~/.emacs.d/clojure" t ".jar$")))

This approach of globbing jar files together is simple and pretty effective. Alternatively,  leiningren appears to be the new hotness in terms of managing clojure dependancies. It's something I'll look at in the future.


Homemade CCTV System

A couple of months ago, I started researching putting a homemade CCTV system on the cheap. I picked up a D-Link DCS920 Wireless-G Internet Camera to use as the initial prototype camera since it was the cheapest wireless camera I found. 

The first approach I took was to setup an Ubuntu 9.10 box and install ZoneMinder. Ubuntu 9.10 has the ZoneMinder packages in the repository so installing it was not hard. There were some additional steps that I found here to get it up and running. On a scale of 1-10, getting ZoneMinder to run was a 6.5.

The trouble I faced was configuring cameras once ZoneMinder was running. ZoneMinder is a full featured application and multitude of configuration options was intimidating. I got it to run in a motion detection mode (where it will capture moving objects in the video stream) but was not satisfied with how fast it was capturing video. This was probably no fault of the software. The Ubuntu box was older box and may not have been able to keep up. 

At this point, I was going to put this project on the backburner until I read a post on lifehacker. The Mac Mini that we use as our media server sits idle for parts of the day when we want a CCTV system in place. Thus there was no additional hardware costs. The resultant performance of the video capture with the Mac Mini was also leads me to believe that the Ubuntu box was too slow. The AMD CPU on the Ubuntu box is a couple of generations old where the Mac Mini has a more modern Core 2 Duo.

One nice feature of Vitamin D was the streamlined camera configuration process. It was able to auto detect the DCS920 wireless camera on our network and after clicking the "Continue" button a couple of times, we were ready to go.

By default, it records everything to the hard disk. It was straightforward to configure sending images of people to my email account.

The starter edition is free and so it fits perfectly into our budget. In the future, we might add additional cameras to our system (they have a compatibility list!) and upgrade to one of their more full featured editions

Newer Entries Older Entries