Vincent Gable’s Blog

September 11, 2008

Detecting if Headphones are Plugged In

Filed under: MacOSX,Programming,Sample Code | , ,
― Vincent Gable on September 11, 2008

I found many posts on mailing lists asking the question of how to detect if something is plugged into the headphones jack, but no complete answer. So here’s how I do it.

Docs & Tools

Use the CoreAudio.framework, specifically CoreAudio/CoreAudio.h Unfortunately it’s a bit confusing sometimes, but the documentation is still very complete (if complex).

HALLab (/Developer/Examples/CoreAudio/HAL/HALLab/ if you have the developer tools installed) is the most complex bit of relevant CoreAudio sample code, and when built it’s a useful utility for poking-around with to boot.

How To Do It

Whenever something is plugged into the headphones jack, CoreAudio changes the data source for the output device, from internal speakers to headphones. Use AudioDeviceGetProperty(outputDeviceID, 0, 0, kAudioDevicePropertyDataSource, &size, &dataSource); to examine the 32-bit ID of the data source, which is best thought of as a 4 character code. If dataSource is 'ispk', sound is played through internal speakers, if it is 'hdpn', sound is playing through the headphones jack. I’m not sure what happens if you have speakers plugged in that use a different output source, like USB, FireWire, or optical out.

A word of caution, do not use the promising-looking AudioDevice Property kAudioDevicePropertyJackIsConnected it does not work on all systems (specifically it didn’t work in 10.4, and I have not tested it under Leopard).

Change Notifications

If you want to be notified when something is plugged/unplugged in the headphones jack, listen for a kAudioDevicePropertyDataSource change to the output audio device. Here is the code I use to test if a computer is using it’s internal speakers:

Sample Code:


//Returns YES if the default sound output device
//is using external speakers to play sound.
- (BOOL) usingInternalSpeakers
{
   AudioDeviceID deviceID;
   UInt32 size = sizeof(deviceID);
   OSStatus err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultSystemOutputDevice, &size, &deviceID);
   NSCAssert((err == noErr), @"AudioHardwareGetProperty failed to get the kAudioHardwarePropertyDefaultSystemOutputDevice property");
   //To be notified when something is plugged/unplugged into the headphones jack
   //listen for a kAudioDevicePropertyDataSource or kAudioDevicePropertyDataSources notification on deviceID
   
   //Check if headphones are plugged in right now:
   UInt32 dataSource;
   size = sizeof(dataSource);
   err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDataSource, &size, &dataSource);
   NSCAssert((err == noErr), @"AudioDeviceGetProperty failed to get the kAudioDevicePropertyDataSource property");
   
   //'ispk' => internal speakers
   //'hdpn' => headphones
   return dataSource == 'ispk';
}

September 6, 2008

Complexity Is the Enemy

Filed under: Design,Quotes,Security |
― Vincent Gable on September 6, 2008

Complexity is the worst enemy of security; as systems become more complex, they get less secure.

Bruce Schneier

The Term “Sprint” is Very Wrong for Software Projects

Filed under: Programming | , , , ,
― Vincent Gable on September 6, 2008

My employer is big on Scrum-flavored Agile Software Development. This is not a critique of “Agile” practices (if you want one Steve Yegge won’t let you down). I just don’t have enough experience organizing software projects to judge if this whole “Agile” thing is working well or not. But I do think the choice of the word “Sprint” to denote a unit of work is harmful.

A sprint is unsustainable. Fully recovering from a true-sprint takes a long time. To be ready to sprint again, you must rest for far longer then the sprint lasted. And you’re pretty useless (at least running-wise) while you rest. These are simple things that we learned as kids on the playground. This is what “sprint” means to people.

Calling repeated multi-week units of sustainable and quality work a “sprint” makes no sense whatsoever. Worse, it subtly encourages over-exertion and behaviors that are detrimental to a project.

It might be argued that in the context of Scrummy-Agileness, “Sprint” is a technical term, divorced from the common parlance. Whatever. Words don’t change meaning overnight, and they are almost never their own antonyms. Word-choice is known to influence people.

Sure, word-choice alone isn’t enough to derail a project, or sink a methodology. That’s why this isn’t a criticism of “Scrum”, which will ultimately stand or fall for other reasons. But there are plenty of much better terms to describe a chunk of work, that will help long-term productivity. Wouldn’t you rather work for a company that evaluated how effective a “Play” was?

September 5, 2008

The ‘Apple Stands on 3rd Party Shoulders’ Theory

Filed under: Uncategorized | , , ,
― Vincent Gable on September 5, 2008

Do you know what the real difference is between a Mac and a PC?

It’s not just the OS. A platform always stands or falls on third-party development. The difference is that Mac software tends to be well designed, and Windows software tends to suck.

Mike Lee, being “an elitist Mac-fan wanker”. Some interesting comments so far.

Condescending Rich Guys

Filed under: Design,Quotes | ,
― Vincent Gable on September 5, 2008

Maria Russo, in the LA Times, totally nails what’s wrong with Microsoft’s first Seinfeld-fueled commercial

Let’s start with the premise of these two famous rich people out discount shoe shopping. Ha, ha! They don’t really have to shop at Payless like the half a million people who lost their jobs this year.

Gates and Seinfeld may both be schlumpy dressers, but their regular-guy qualities stop there. Neither is the Warren Buffett kind of rich, the frugal sort who knows the value of a dollar and doesn’t put himself above the working man (or so we believe about Buffett). Instead the ad seems to be somehow making light of bargain-shopping, as if it’s just a lark for these guys, or some kind of joke that we’re not quite in on.

ASCII is Dangerous

Never use NSASCIIStringEncoding

“Foreign” characters, like the ï in “naïve”, will break your code, if you use NSASCIIStringEncoding. Such characters are more common then you might expect, even if you do not have an internationalized application. “Smart quotes”, and most well-rendered punctuation marks, are not 7-bit ASCII. For example, that last sentence can’t be encoded into ASCII, because my blog uses smart-quotes. (Seriously, [thatSentence cStringUsingEncoding:NSASCIIStringEncoding] will return nil!)

Here are some simple alternatives:

C-String Paths
Use - (const char *)fileSystemRepresentation; to get a C-string that you can pass to POSIX functions. The C-string will be freed when the NSString it came from is freed.

An Alternate Encoding
NSUTF8StringEncoding is the closest safe alternative to NSASCIIStringEncoding. ASCII characters have the same representation in UTF-8 as in ASCII. UTF-8 strings will printf correctly, but will look wrong (‘fancy’ characters will be garbage) if you use NSLog(%s).

Native Foundation (NSLog) Encoding
Generally, Foundation uses UTF-16. It is my understanding that this is what NSStrings are by default under the hood. UTF-16 strings will look right if you print them with NSLog(%s), but will not print correctly using printf. In my experience printf truncates UTF-16 strings in an unpredictable way. Do not mix UTF-16 and printf.

Convenience C-Ctrings
[someNSString UTF8String] will give you a const char * to a NULL-terminated UTF8-string. ASCII characters have the same representation in UTF-8 as in ASCII.

Take a minute to search all your projects for NSASCIIStringEncoding, and replace it with a more robust option.

It never hurts to brush up on unicode.

September 2, 2008

You Can Fool Some of the People

Filed under: Security,Usability | , ,
― Vincent Gable on September 2, 2008

Preconceptions are a powerful thing.

In one recent test, psychologists asked 32 volunteers to sample strawberry yogurt. To make sure the testers made their judgments purely on the basis of taste, the researchers said, they needed to turn out the lights. Then they gave their subjects chocolate yogurt. Nineteen of the 32 praised the strawberry flavor. One said that strawberry was her favorite flavor and she planned to switch to this new brand.

According to this New York Times article.

Waiting for Safety “Kills”

Filed under: Design,Quotes,Security | ,
― Vincent Gable on September 2, 2008

Assume that all the new airport security measures increase the waiting time at airports by — and I’m making this up — 30 minutes per passenger. There were 760 million passenger boardings in the United States in 2007. This means that the extra waiting time at airports has cost us a collective 43,000 years of extra waiting time. Assume a 70-year life expectancy, and the increased waiting time has “killed” 620 people per year — 930 if you calculate the numbers based on 16 hours of awake time per day. So the question is: If we did away with increased airport security, would the result be more people dead from terrorism or fewer?

Bruce Schneier

Relatedly, Tog claims that designing roads for speed first, and safety second, could save lives.

August 31, 2008

Better List Termination

Filed under: MacOSX,Objective-C,Programming,Usability | , ,
― Vincent Gable on August 31, 2008

As I’ve written before, using nil to terminate a variable-length list (eg [NSArray arrayWithObject:foo,bar,nil]) is a bad choice because of how easy it is to get a nil value in Objective-C without knowing it. (Unlike, say C++, doing stuff with nil won’t cause an exception, leading to some subtle bugs). Well, here is a solution.

A Better Sentinel

#define END_OF_LIST ((id) -1)
is my current choice of a good sentinel-value. It is an invalid pointer, so unlike nil, you should never get it back from some library. Sending it any message will fail fast, and recognizably (you will see 0xFF...FF as an illegal address somewhere in the back-trace).

Example:


id aNilObject = nil;
NSArray *standard = [NSArray arrayWithObjects:@"1", @"2", aNilObject, @"4", nil];
LOG_ID(standard);
NSArray *better = [NSArray arrayWithSentinelTerminatedObjects:@"1", @"2", aNilObject, @"4", END_OF_LIST];
LOG_ID(better);


standard = (
   1,
   2
)
better = (
   1,
   2,
   <null>,
   4
)

The Code:


#define END_OF_LIST ((id) -1)

@implementation NSArray (SentinelTerminatedConstructors)

+ (NSArray*) arrayWithSentinelTerminatedObjects:(id) firstObject, ...
{
   NSMutableArray *array = [NSMutableArray array];
   
   if (firstObject != END_OF_LIST)
   {
      if(!firstObject)
         firstObject = [NSNull null];

      [array addObject:firstObject];
      
      id eachObject;
      va_list argumentList;
      va_start(argumentList, firstObject);
      while (END_OF_LIST != (eachObject = va_arg(argumentList, id)))
      {
         if(!eachObject)
            eachObject = [NSNull null];

         [array addObject:eachObject];
      }
      va_end(argumentList);
   }
   
   return array;
}

@end

Some Downsides

arrayWithSentinelTerminatedObjects” is too long of a name. If you’ve got a better one, please share!

You won’t get a compiler-warning if you leave out END_OF_LIST, but if you compile with -Wformat, you will get a warning if you leave out nil. The full story

There are six collection creation methods in Foundation which require nil termination to function properly. They are:

+[NSArray arrayWithObjects:]
-[NSArray initWithObject:]
+[NSDictionary dictionaryWithObjectsAndKeys:]
-[NSDictionary initWithObjectsAndKeys:]
+[NSSet setWithObjects:]
-[NSSet initWithObjects:]

These methods have been decorated with the NS_REQUIRES_NIL_TERMINATION macro, which adds an additional check to invocations of those methods to make sure the nil has been included at the end of the argument list. This warning is only available when compiling with -Wformat.

What do you think?

Frankly, I haven’t used END_OF_LIST-terminated collection creation enough yet to have a final verdict. So please let me know what you think! Was this code useful? Did it cause problems, or preempt them? As always, if you have a better solution, please share!

August 28, 2008

Lying With Pictures

Filed under: Design,Security | , , ,
― Vincent Gable on August 28, 2008

A fantastic discussion of lying with photography. One of the take-aways for me were that captioning a picture can be more effective then photoshopping it, especially since the text and image are processed separately in the brain (at least as far as we know).

For historical reference, here’s an article on staged photographs in early 1930’s advertising.

« Newer PostsOlder Posts »

Powered by WordPress