AudioObjectGetPropertyData to get a list of input devices

后端 未结 4 1833
旧时难觅i
旧时难觅i 2020-11-30 04:15

How do I utilize AudioObjectGetPropertyData in OS X to retrieve a list of the system\'s input devices? I currently have the following dummy code for retrieving

4条回答
  •  抹茶落季
    2020-11-30 05:06

    I have slightly modified the code submitted by "sbooth" to print all the input devices along with the no. of buffers for each device and no. of channels for each buffer.

    CFArrayRef CreateInputDeviceArray()
    {
        AudioObjectPropertyAddress propertyAddress = {
            kAudioHardwarePropertyDevices,
            kAudioObjectPropertyScopeGlobal,
            kAudioObjectPropertyElementMaster
        };
    
        UInt32 dataSize = 0;
        OSStatus status = AudioHardwareServiceGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
        if(kAudioHardwareNoError != status) {
            fprintf(stderr, "AudioObjectGetPropertyDataSize (kAudioHardwarePropertyDevices) failed: %i\n", status);
            return NULL;
        }
    
        UInt32 deviceCount = (UInt32)(dataSize / sizeof(AudioDeviceID));
    
        AudioDeviceID *audioDevices = (AudioDeviceID *)(malloc(dataSize));
        if(NULL == audioDevices) {
            fputs("Unable to allocate memory", stderr);
            return NULL;
        }
    
        status = AudioHardwareServiceGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, audioDevices);
        if(kAudioHardwareNoError != status) {
            fprintf(stderr, "AudioObjectGetPropertyData (kAudioHardwarePropertyDevices) failed: %i\n", status);
            free(audioDevices), audioDevices = NULL;
            return NULL;
        }
    
        CFMutableArrayRef inputDeviceArray = CFArrayCreateMutable(kCFAllocatorDefault, deviceCount, &kCFTypeArrayCallBacks);
        if(NULL == inputDeviceArray) {
            fputs("CFArrayCreateMutable failed", stderr);
            free(audioDevices), audioDevices = NULL;
            return NULL;
        }
    
        // Iterate through all the devices and determine which are input-capable
        propertyAddress.mScope = kAudioDevicePropertyScopeInput;
        for(UInt32 i = 0; i < deviceCount; ++i) {
            // Query device UID
            CFStringRef deviceUID = NULL;
            dataSize = sizeof(deviceUID);
            propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
            status = AudioHardwareServiceGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceUID);
            if(kAudioHardwareNoError != status) {
                fprintf(stderr, "AudioObjectGetPropertyData (kAudioDevicePropertyDeviceUID) failed: %i\n", status);
                continue;
            }
    
            // Query device name
            CFStringRef deviceName = NULL;
            dataSize = sizeof(deviceName);
            propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
            status = AudioHardwareServiceGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceName);
            if(kAudioHardwareNoError != status) {
                fprintf(stderr, "AudioObjectGetPropertyData (kAudioDevicePropertyDeviceNameCFString) failed: %i\n", status);
                continue;
            }
    
            // Query device manufacturer
            CFStringRef deviceManufacturer = NULL;
            dataSize = sizeof(deviceManufacturer);
            propertyAddress.mSelector = kAudioDevicePropertyDeviceManufacturerCFString;
            status = AudioHardwareServiceGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceManufacturer);
            if(kAudioHardwareNoError != status) {
                fprintf(stderr, "AudioObjectGetPropertyData (kAudioDevicePropertyDeviceManufacturerCFString) failed: %i\n", status);
                continue;
            }
    
            // Determine if the device is an input device (it is an input device if it has input channels)
            dataSize = 0;
            propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
            status = AudioHardwareServiceGetPropertyDataSize(audioDevices[i], &propertyAddress, 0, NULL, &dataSize);
            if(kAudioHardwareNoError != status) {
                fprintf(stderr, "AudioObjectGetPropertyDataSize (kAudioDevicePropertyStreamConfiguration) failed: %i\n", status);
                continue;
            }
    
            AudioBufferList *bufferList = (AudioBufferList *)(malloc(dataSize));
            if(NULL == bufferList) {
                fputs("Unable to allocate memory", stderr);
                break;
            }
    
            status = AudioHardwareServiceGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, bufferList);
            if(kAudioHardwareNoError != status || 0 == bufferList->mNumberBuffers) {
                if(kAudioHardwareNoError != status)
                    fprintf(stderr, "AudioObjectGetPropertyData (kAudioDevicePropertyStreamConfiguration) failed: %i\n", status);
                free(bufferList), bufferList = NULL;
                continue;
            }
            UInt32 numBuffers = bufferList->mNumberBuffers;
    
            printf("\n\ndeviceUID:%s \tdeviceName: %s\ndeviceManufacturer: %s\t#Buffers:%d", \
                   CFStringGetCStringPtr(deviceUID, kCFStringEncodingMacRoman),\
                   CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman), \
                   CFStringGetCStringPtr(deviceManufacturer, kCFStringEncodingMacRoman), \
                   numBuffers
                   );
            for (UInt8 j = 0; j < numBuffers; j++) {
                AudioBuffer ab = bufferList->mBuffers[j];
                printf("\n#Channels: %d DataByteSize: %d", ab.mNumberChannels, ab.mDataByteSize);
            }
    
            free(bufferList), bufferList = NULL;
    
            // Add a dictionary for this device to the array of input devices
            CFStringRef keys    []  = { CFSTR("deviceUID"),     CFSTR("deviceName"),    CFSTR("deviceManufacturer") };
            CFStringRef values  []  = { deviceUID,              deviceName,             deviceManufacturer };
    
    
    
            CFDictionaryRef deviceDictionary = CFDictionaryCreate(kCFAllocatorDefault,
                                                                  (const void **)(keys),
                                                                  (const void **)(values),
                                                                  3,
                                                                  &kCFTypeDictionaryKeyCallBacks,
                                                                  &kCFTypeDictionaryValueCallBacks);
    
    
            CFArrayAppendValue(inputDeviceArray, deviceDictionary);
    
            CFRelease(deviceDictionary), deviceDictionary = NULL;
        }
    
        free(audioDevices), audioDevices = NULL;
    
        // Return a non-mutable copy of the array
        CFArrayRef copy = CFArrayCreateCopy(kCFAllocatorDefault, inputDeviceArray);
        CFRelease(inputDeviceArray), inputDeviceArray = NULL;
    
        return copy;
    }
    

提交回复
热议问题