How to get notifications when the headphones are plugged in/out? Mac

做~自己de王妃 提交于 2019-12-04 07:54:29

问题


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!


回答1:


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.




回答2:


I was looking for a similar solution and found AutoMute in the app store. It works well. https://itunes.apple.com/us/app/automute-preventing-awkward/id1118136179?mt=12 I'm also working on some scripts of my own, and wrote this script to test if headphones are plugged in: https://gist.github.com/jordan314/bffa2e6cdbf248f8c558ba6496dcc7ea



来源:https://stackoverflow.com/questions/14483083/how-to-get-notifications-when-the-headphones-are-plugged-in-out-mac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!