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';
}

2 Comments »

  1. AudioHardwareGetProperty and AudioDeviceGetProperty works not in snow leopard, since I have some probs understanding coreaudio framework; are there any workarounds ?

    Comment by Joerg Lange — February 7, 2010 @ 2:36 pm

  2. Is there a way to control a specific output source regardless of what the current output device is? Specifically, I wanted to edit the internal speaker’s volume while the user has his or her headphones plugged in. Once they plug in headphones, any edits I make to the volume affect the headphones and not the internal speaker’s volume, which is what I wish to edit.

    Comment by Jaime — October 21, 2012 @ 1:35 am

RSS feed for comments on this post.

Leave a comment

Powered by WordPress