gpt4 book ai didi

macos - AudioObjectGetPropertyData 获取输入设备列表

转载 作者:行者123 更新时间:2023-12-03 21:03:52 31 4
gpt4 key购买 nike

如何使用 AudioObjectGetPropertyData在 OS X 中检索系统输入设备的列表?我目前有以下用于检索全局设备列表的虚拟代码:

AudioDeviceID devices[12];
UInt32 arraySize = sizeof(devices);

AudioObjectPropertyAddress thePropertyAddress = { kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster };

AudioObjectGetPropertyData(kAudioObjectSystemObject,
&thePropertyAddress,
0,
NULL,
&arraySize,
&devices);

最佳答案

要确定设备是否为输入设备,您需要检查它是否有任何输入 channel 。

这是从 Objective-C 类 here 修改的代码:

static BOOL DeviceHasBuffersInScope(AudioObjectID deviceID, AudioObjectPropertyScope scope)
{
NSCParameterAssert(deviceID != kAudioObjectUnknown);

AudioObjectPropertyAddress propertyAddress = {
.mSelector = kAudioDevicePropertyStreamConfiguration,
.mScope = scope,
.mElement = kAudioObjectPropertyElementWildcard
};

UInt32 dataSize = 0;
OSStatus result = AudioObjectGetPropertyDataSize(deviceID, &propertyAddress, 0, NULL, &dataSize);
if(result != kAudioHardwareNoError) {
return NO;
}

AudioBufferList *bufferList = malloc(dataSize);
if(!bufferList) {
return NO;
}

result = AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, NULL, &dataSize, bufferList);
if(result != kAudioHardwareNoError) {
free(bufferList);
return NO;
}

BOOL supportsScope = bufferList->mNumberBuffers > 0;
free(bufferList);

return supportsScope;
}

static BOOL DeviceSupportsInput(AudioObjectID deviceID)
{
return DeviceHasBuffersInScope(deviceID, kAudioObjectPropertyScopeInput);
}

static BOOL DeviceSupportsOutput(AudioObjectID deviceID)
{
return DeviceHasBuffersInScope(deviceID, kAudioObjectPropertyScopeOutput);
}

NSArray<NSNumber *> * AllAudioDevices()
{
AudioObjectPropertyAddress propertyAddress = {
.mSelector = kAudioHardwarePropertyDevices,
.mScope = kAudioObjectPropertyScopeGlobal,
.mElement = kAudioObjectPropertyElementWildcard
};

UInt32 dataSize = 0;
OSStatus result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
if(result != kAudioHardwareNoError) {
return nil;
}

AudioObjectID *deviceIDs = (AudioObjectID *)malloc(dataSize);
if(!deviceIDs) {
return nil;
}

result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, deviceIDs);
if(kAudioHardwareNoError != result) {
free(deviceIDs);
return nil;
}

NSMutableArray *allDevices = [NSMutableArray array];
for(NSInteger i = 0; i < (NSInteger)(dataSize / sizeof(AudioObjectID)); ++i) {
[allDevices addObject:[NSNumber numberWithUnsignedInt:deviceIDs[i]]];
}

free(deviceIDs);

return allDevices;
}

NSArray<NSNumber *> * AudioOutputDevices()
{
NSMutableArray *outputDevices = [NSMutableArray array];

NSArray *allDevices = AllAudioDevices();
for(NSNumber *device in allDevices) {
if(DeviceSupportsOutput(device.unsignedIntValue)) {
[outputDevices addObject:device];
}
}

return outputDevices;
}

NSArray<NSNumber *> * AudioInputDevices()
{
NSMutableArray *inputDevices = [NSMutableArray array];

NSArray *allDevices = AllAudioDevices();
for(NSNumber *device in allDevices) {
if(DeviceSupportsInput(device.unsignedIntValue)) {
[inputDevices addObject:device];
}
}

return inputDevices;
}


原始代码片段是:

这是我转换的一些应该可以工作的代码(尽管未经测试):
CFArrayRef CreateInputDeviceArray()
{
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};

UInt32 dataSize = 0;
OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
if(kAudioHardwareNoError != status) {
fprintf(stderr, "AudioObjectGetPropertyDataSize (kAudioHardwarePropertyDevices) failed: %i\n", status);
return NULL;
}

UInt32 deviceCount = static_cast<UInt32>(dataSize / sizeof(AudioDeviceID));

AudioDeviceID *audioDevices = static_cast<AudioDeviceID *>(malloc(dataSize));
if(NULL == audioDevices) {
fputs("Unable to allocate memory", stderr);
return NULL;
}

status = AudioObjectGetPropertyData(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 = AudioObjectGetPropertyData(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 = AudioObjectGetPropertyData(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 = AudioObjectGetPropertyData(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 = AudioObjectGetPropertyDataSize(audioDevices[i], &propertyAddress, 0, NULL, &dataSize);
if(kAudioHardwareNoError != status) {
fprintf(stderr, "AudioObjectGetPropertyDataSize (kAudioDevicePropertyStreamConfiguration) failed: %i\n", status);
continue;
}

AudioBufferList *bufferList = static_cast<AudioBufferList *>(malloc(dataSize));
if(NULL == bufferList) {
fputs("Unable to allocate memory", stderr);
break;
}

status = AudioObjectGetPropertyData(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;
}

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,
reinterpret_cast<const void **>(keys),
reinterpret_cast<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;
}

关于macos - AudioObjectGetPropertyData 获取输入设备列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4575408/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com