Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Built-in Output From Core Audio

Is it possible to reliably get the AudioDeviceID of a Mac's built-in output? I've tried using kAudioHardwarePropertyDefaultOutputDevice to get the currently selected output device, but this can be any old device depending on what the user has selected in system preferences — I only want the ID of the built in speakers.

AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyDefaultInputDevice,
                                          kAudioObjectPropertyScopeGlobal,
                                          kAudioObjectPropertyElementMaster };

verify_noerr (AudioObjectGetPropertyData(kAudioObjectSystemObject,
                                         &theAddress,
                                         0,
                                         NULL,
                                         &propsize,
                                         &inputDevice));

At the moment I'm getting a list of all the devices and checking the name string of the devices by doing name == "Built-in Output". This works on my machine but doesn't seem like a very robust solution! Is there anything like a kAudioHardwarePropertyBuiltInOutputDevice?

like image 617
Dan Halliday Avatar asked Dec 26 '22 22:12

Dan Halliday


2 Answers

The answer of @Equinox2000 is working, but there's a way to avoid heavy string comparing. Just get another AudioObject's property with selector of kAudioDevicePropertyTransportType.

aopa.mSelector = kAudioDevicePropertyTransportType;
aopa.mScope = kAudioObjectPropertyScopeGlobal;
UInt32 size = sizeof(UInt32);
UInt32 transportType = 0;
OSStatus status = AudioObjectGetPropertyData(device.deviceId, &address, 0, NULL, &size, & transportType);
if (transportType == kAudioDeviceTransportTypeBuiltIn) // that's all the checks
    // do something
like image 76
Daniyar Avatar answered Jan 14 '23 19:01

Daniyar


After several days of research the best answer I can can come up with is to look for Built-in output as you mention, but have added a manufacturer check also as below...

- (NSString *)getBuiltInOutputDeviceUID
{
    NSString *deviceUID = @"";

    AudioObjectPropertyAddress aopa;
    aopa.mSelector = kAudioHardwarePropertyDevices;
    aopa.mScope = kAudioObjectPropertyScopeGlobal;
    aopa.mElement = kAudioObjectPropertyElementMaster;

    UInt32 propSize;
    OSStatus error = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &aopa, 0, NULL, &propSize);
    if (error == noErr) {
        int deviceCount = propSize / sizeof(AudioDeviceID);
        AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(propSize);
        error = AudioObjectGetPropertyData(kAudioObjectSystemObject, &aopa, 0, NULL, &propSize, audioDevices);
        if (error == noErr) {
            UInt32 propSize = sizeof(CFStringRef);
            for(int i = 1; i <= deviceCount; i++) {
                NSString *result;
                aopa.mSelector = kAudioDevicePropertyDeviceManufacturerCFString;
                error = AudioObjectGetPropertyData(audioDevices[i], &aopa, 0, NULL, &propSize, &result);
                if (error != noErr || ![result isEqualToString:@"Apple Inc."]) {
                    continue;
                }
                aopa.mSelector = kAudioDevicePropertyDeviceNameCFString;
                error = AudioObjectGetPropertyData(audioDevices[i], &aopa, 0, NULL, &propSize, &result);
                if (error != noErr || ![result isEqualToString:@"Built-in Output"]) {
                    continue;
                }
                aopa.mSelector = kAudioDevicePropertyDeviceUID;
                error = AudioObjectGetPropertyData(audioDevices[i], &aopa, 0, NULL, &propSize, &result);
                if (error == noErr) {
                    deviceUID = result;
                    break;
                }
            }
        }
        free(audioDevices);
    }
    return deviceUID;
}
like image 39
Equinox2000 Avatar answered Jan 14 '23 19:01

Equinox2000