1. The Objective-C interface

Recently I was planning a presentation on RubyCocoa. I had prepared a demo application to show during my talk and decided that it would be fun to show my presentation slides from my demo app. I quickly found that Keynote could export my slides as .png files, and it didn’t take long to get them loaded into a custom image viewer that used an NSImageView to display the slides. But one thing was missing: with Keynote, I could control my presentation with my new Apple Remote. I wanted to be able to do the same thing from Ruby.

Thanks to Google, Martin Kahr, Objective-C, and RubyCocoa, less than 30 minutes later I had exactly what I wanted. A search for ‘Apple Remote Objective-C’ took me directly to Martin’s source code page, where I found the source for his small demo application.

Let’s switch from past to present and do the rest together.

Download the source from Martin’s web site. As I write this, here is the current version of his demo application. Inside the archive, you’ll find an Xcode project. Build and run it. The result will be an application window like the one below.

Pressing buttons on your remote will cause red circles to appear on the corresponding parts of the image. In the window shown, I’m holding the right “forward” button down.

There are three significant Objective-C classes in the demo application, each with its own pair of header and source files. RemoteFeedbackView provides the contents of the application window, AppleRemote handles communication with the remote control, and MainController brings the two together. If you look at its source in MainController.m, you’ll see that Martin has designed a very easy to use interface that uses a common Objective-C pattern: delegation. In its awakeFromNib method, the MainController gets a singleton object representing the Apple Remote (using another common Objective-C pattern, the shared object). Then the controller sets itself as the delegate of the [AppleRemote sharedRemote]. It then waits for button presses, which cause the Apple Remote handler to send an appleRemoteButton:pressedDown: message to the delegate, which displays a status message and forwards the button press information to the view.

Feel free to read through the code in AppleRemote.m; it contains some mysterious calls to Apple’s HID (human interface device) manager that could easily take hours to fully understand. But by now we already know enough to use Martin’s Apple Remote interface from Ruby.

Let’s begin by creating a framework containing Martin’s AppleRemote controller. First, in the Groups & Files pane, expand the Targets item, click on the AppleRemote target to select it, and press the delete key to delete it. We’re going to replace it with a new build target with the same name. To add the new target, first select the Project->New Target… menu item. You’ll then see a dialog box with a list of different project types. Choose the Cocoa->Framework type and press the Next button. Name the target “AppleRemote” (don’t type the quotes) and click the Finish button.

Now you’ll need to add some files to the new target. Back in the Groups & Files pane, expand the AppleRemote target to reveal the build steps. Then expand the Base Classes and Devices folder near the top of the pane and drag RemoteControl.h, HIDRemoteControlDevice.h and AppleRemote.h to the Copy Headers step and RemoteControl.m, HIDRemoteControlDevice.m and AppleRemote.m to the Compile Sources step. Then expand the Frameworks folder and drag the IOKit.framework and Carbon.framework to the Link Binary With Libraries step.

Under the Project menu, set the Active Build Configuration to Release.

Next, build the framework. Here is a picture of my Xcode project window just after my build completed.

Finally, move the result (AppleRemote.framework) from the build/Release directory to /Library/Frameworks.

Did you find an error? Is something missing? Post your comment or suggestion below!

Comments (2) post
  1. Nick Wed Mar 28 00:44:50 +0000 2007

    Thanks for the step-by-step. Can you explicitly say what the ‘result’ is from the build/release directory? This is my first time building anything in XCode. Is it AppleRemote.framework? Thanks

  2. Tim Wed Mar 28 11:38:59 +0000 2007

    Yes, that’s it.