Archive for April 2007

Detecting if Headphones are Plugged in

April 25, 2007

This article has been updated, and moved here.

Facebook Integration Delayed.

April 24, 2007

I have been working on integrating IMLocation with facebook. Unfortunately, the current facebook API utterly lacks a way to set the status of a user. Most everything is read-only.

There are two options:
1) Wait for facebook to fix the API. Who knows how long this will take.
2) Somehow simulate a user in a webrowser manually updating their status message. This is a lot of work.

Unfortunately, at this point in time, nether option looks like it will result in a quick fix.


April 23, 2007

I am writing an FAQ for IMLocation. As you can see it is quite small right now, but it continues to grow.

Any questions are greatly appreciated.

Thanks for your help!

(UPDATED 10/1/2007, the FAQ is now 705 words about 11 topics.)

tell application “YourGreatApp” NSAppleScript is here to save the day

April 21, 2007

Cocoa includes the wonderful NSAppleScript class, which lets you embed a high-level AppleScript code snippets in your Objective-C program. AppleScript is the bee’s knees for interfacing with other applications, particularly Apple programs and OS X itself. EDITED TO ADD: Unless you use threads in your program. Here is a more sobering perspective, written several months after this article.

For example, say you want to get the user’s current status message from iChat. You can mess around with the InstantMessaging.framework — only to discover that it can’t do this — or you can wrap the following AppleScript:

tell application “iChat” to get status message

in an NSAppleScript object, like so:
NSAppleScript *iChatGetStatusScript; //this would be in the header.
/*Apple recommends only compiling NSAppleScript objects once, for performance reasons. Be sure to call [iChatGetStatusScript release] in your dealloc method.*/
  iChatGetStatusScript = [[NSAppleScript alloc] initWithSource:
    @”tell application \”iChat\” to get status message”
NSString *statusString =
[[iChatGetStatusScript executeAndReturnError:&errorDict] stringValue];

Skeptical readers have probably noticed that I cheated by picking functionality that wasn’t in a framework for the last example. Unfortunately this situation is more of a rule then an exception. AppleEvents have been on the Apple software development scene longer then Cocoa. Lots of programs only expose functionality through AppleScript/AppleEvents. Using NSAppleScript is the best way to interact with these programs from Cocoa.

AppleScript is a big part of how FrontRow integrates with iTunes, even though they are both modern programs.
grok the ouptut of:
strings /System/Library/CoreServices/Front\\ Row
(hint: look for “tell”), and you’ll see a lot of gems like:
tell application “iTunes” to get (data of artwork 1 of current track) as picture
tell application “Finder”
    set myCD to first disk whose format is audio format

Now I am the first to admit that a well-written Objective-C library trumps duck-taping one language on-top of another. But we don’t have the luxury of always being given well-written Objective-C interfaces.

As of version 0.24 IMLocation uses AppleScript to: interface with iChat and Adium; install/uninstall itself; mute/unmute sound; perform inter-process communication between the helper and GUI; and to get the MAC address of the first router connected to the ethernet port. NSAppleScript has also been heavily used during development for prototyping.

EDITED TO ADD: NSAppleScript is pathologically un-thread-safe. That is to say, you can only use it on from the main thread. No amount of @synchronized blocks will keep you from crashing if you use NSAppleScript in any other way. There is a workaround, but the cure is worse then the disease. You can use an NSTask to have the osascript program interpret the script for you. This won’t block your thread, but it will be take a long time, and is resource un-friendly.

NSTasks are the way to call the command line, or embed snippets of a different language in cocoa. I was originally using the do shell command AppleScript construct. If you are using it, please switch to NSTasks. They are much more powerful, still easy to use, and prevent all sorts of bugs caused by quote-marks in AppleScript.

Bug Endian

April 20, 2007

I’m ashamed to admit that I got bitten by an endianess bug yesterday. It was just a small bug, in a test program, and didn’t affect IMLocation, but boy was my face ‘!der’

It made me realize I don’t test enough on PowerPC (PPC) systems, since I don’t own one anymore. (One of the joys of being a student developer is only having one computer).

So to simulate a PPC system on my intel box, I’ve started occasionally building for PowerPC only, and making sure everything still runs under Rosetta, OSX’s PPC emulator. You can get the same effect without rebuilding your application, if it is Universal, by selecting it in the Finder, choosing Get Info (⌘-I) -> “General” triangle -> checking “Open Using Rosetta”.

This isn’t a full substitute for testing on a real PPC Mac, of course. But it’s quick to do, catches some endian bugs, and gives you a bit more test coverage.

Selective Muting: Get Out of My Headphones!

April 20, 2007

A feature I thought I would love, but began to hate is automatic muting in “quite” places, like lecture halls. Whenever I take my laptop to a place I have designated as quiet, IMLocation will mute it. This works great at preventing embarrassing beeps during class. But I like to listen to headphones while I work, and they were getting muted whenever I would work in a library or study hall.

What I needed was selective muting — if I was in a quiet place, sound would be turned off, unless I was using headphones.

At first I suspected that this feature would only work on newer Macs. My MacBookPro remembers the volume of my headphones when I plug them in. (By the way, if you don’t know about this handy feature of your new Mac, check it out — it’s an ear saver). But older Macs don’t do this, so I figured there was just no way for them to figure out if headphones were plugged in or not.

Well, it turns out this is not the case. Apparently on older Macs, OS X chooses not to change the volume, even though it can. I have confirmed that this is the case on an iBook G4, iMac G4, 12″ Powerbook, and 15″ TiBook. They can detect if they have headphones plugged in or not, even though OS X ignores this bit of information.

Selective muting is currently available as of IMLocation version 0.24.