I'd like to get notified when headphones are plugged in or out in the headphone jack.
I've searched around for this on stackoverflow but I can't seem to find what I'm looking for for the Mac, I can only find for iOS.
So, do you have any ideas on how to perform this? What I want to do with this is: when headphones are plugged out I want to programmatically pause iTunes (iOS-like feature).
Thank you!

- 11,894
- 2
- 48
- 47

- 3,330
- 3
- 41
- 76
-
2I saw that question too. It's for iOS not for OSX – Pedro Vieira Jan 23 '13 at 15:30
-
My bad... I didn't catch their reference to iOS when I was first reading through. – Jason M. Batchelor Jan 23 '13 at 15:47
-
Are u looking for a real headphone (plugged in) or do you just wanna know when "something" is plugged in (internal speakers = off). – Jan 23 '13 at 16:08
-
@DigiMonk that question is what mori57 said (he already deleted the comment). If you look closely that's for iOS not OSX. But, what I want to perform with this is: when the headphones are plugged out I stop iTunes programmatically. – Pedro Vieira Jan 23 '13 at 20:12
-
@PedroVieira Where's the iOS question? I have this question but for iOS. – adib Jun 01 '13 at 04:10
-
1@adib http://stackoverflow.com/questions/5893244/how-to-detect-something-in-headphone-jack-on-a-mac?lq=1 it looks like it's for mac, but the answer is for iOS – Pedro Vieira Jun 01 '13 at 16:51
2 Answers
You can observe changes using the CoreAudio
framework.
Both headphones and the speakers are data sources on the same audio output device (of type built-in). One of both will be on the audio device based on headphones being plugged in or not.
To get notifications you listen to changes of the active datasource on the built-in output device.
1. Get the built-in output device
To keep this short we'll use the default output device. In most cases this is the built-in output device. In real-life applications you'll want to loop all available devices to find it, because the default device could be set to a different audio device (soundflower or airplay for example).
AudioDeviceID defaultDevice = 0;
UInt32 defaultSize = sizeof(AudioDeviceID);
const AudioObjectPropertyAddress defaultAddr = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultAddr, 0, NULL, &defaultSize, &defaultDevice);
2. Read its current data source
The current datasource on a device is identified by an ID of type UInt32
.
AudioObjectPropertyAddress sourceAddr;
sourceAddr.mSelector = kAudioDevicePropertyDataSource;
sourceAddr.mScope = kAudioDevicePropertyScopeOutput;
sourceAddr.mElement = kAudioObjectPropertyElementMaster;
UInt32 dataSourceId = 0;
UInt32 dataSourceIdSize = sizeof(UInt32);
AudioObjectGetPropertyData(defaultDevice, &sourceAddr, 0, NULL, &dataSourceIdSize, &dataSourceId);
3. Observe for changes to the data source
AudioObjectAddPropertyListenerBlock(_defaultDevice, &sourceAddr, dispatch_get_current_queue(), ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses) {
// move to step 2. to read the updated value
});
Determine the data source type
When you have the data source id as UInt32
you can query the audio object for properties using a value transformer. For example to get the source name as string use kAudioDevicePropertyDataSourceNameForIDCFString
. This will result in the string "Internal Speaker" or "Headphones". However this might differ based on user locale.
An easier way is to compare the data source id directly:
if (dataSourceId == 'ispk') {
// Recognized as internal speakers
} else if (dataSourceId == 'hdpn') {
// Recognized as headphones
}
However I couldn't find any constants defined for these values, so this is kind of undocumented.

- 1,030
- 1
- 9
- 15

- 11,894
- 2
- 48
- 47
-
1omg, you're a lifesaver! It works very well! Thank you very much! I just have 2 questions: 1. I'm testing it on 10.8 and it works great. Will it work without any problems on 10.7? 2. Is it app store friendly? – Pedro Vieira Jan 23 '13 at 23:05
-
i'm looking for a web-based solution. can browsers connect to the CoreAudio framework? – RZKY Jun 09 '14 at 05:48
-
1This feels very low-level compared to the iOS APIs. If there is a "more Swifty" solution it'd be most welcome. – Henrik Jul 03 '16 at 10:05
-
@RZKY - Nope. `CoreAudio` is a low-level iOS system framework and is not accessible to JavaScript running in Safari. I am not aware of any web API that can detect the type of the system audio output. (Mozila had this functionality in the FireFox `AudioChannels` API for a while, but it never caught on; see https://developer.mozilla.org/en-US/docs/Archive/B2G_OS/API/AudioChannelManager/headphones) – Master of Ducks Apr 12 '18 at 23:49
I was looking for a similar solution and found AutoMute in the app store. It works well.
I'm also working on some scripts of my own, and wrote this script to test if headphones are plugged in:
#!/bin/bash
if system_profiler SPAudioDataType | grep --quiet Headphones; then
echo plugged in
else
echo not plugged in
fi