我有一个混合的C ++ / Objective-C项目,它使用AudioObjectGetPropertyDataSize来获取插入的音频设备(如USB耳机)的数量。这个API在某些条件下似乎不起作用。例如,在10.5上它可以工作,但在10.6上,它将无法检测到何时插入新的USB耳机。
我已经将问题减少到一小部分代码来重现问题(它在循环中调用AudioObjectGetPropertyDataSize)。当代码仅与CoreAudio链接时,代码将在10.6上工作(即,它将检测何时插入/拔出设备),但是一旦链接到Foundation ,它将停止工作。
我不明白如何链接到框架可以破坏其他方式有效的代码。
这是代码(coreaudio-test.cpp):
#include <stdio.h>
#include <CoreAudio/AudioHardware.h>
int main(int argc, char **argv) {
printf("Press <enter> to refresh device list> \n");
while (1) {
getchar();
// get device count
UInt32 dataSize = 0;
AudioObjectPropertyAddress propertyAddress;
propertyAddress.mSelector = kAudioHardwarePropertyDevices;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
OSStatus result =
AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
int count = -1;
if (result == noErr) {
count = dataSize / sizeof(AudioDeviceID);
}
printf("num devices= %d \n", count);
}
return 0;
}
这是Makefile:
LFLAGS= -framework CoreAudio
all: coreaudio-test coreaudio-test.broken
# create a test that works
coreaudio-test: coreaudio-test.cpp
g++ -o $@ $^ $(LFLAGS)
# linking to foundation will break the test
coreaudio-test.broken: coreaudio-test.cpp
g++ -o $@ $^ $(LFLAGS) -framework Foundation
对这种离奇行为的任何想法? (顺便说一句,我也在CoreAudio list上发布了这个问题。)
答案 0 :(得分:2)
CoreAudio列表answered my question。我们需要告诉CoreAudio分配自己的事件派发线程:
CFRunLoopRef theRunLoop = NULL;
AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
AudioObjectSetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
我怀疑正在发生的事情是当程序链接到Foundation时,CoreAudio假定主线程充当事件调度程序循环(非常常见,因为Objective-C通常用于GUI程序)。当没有链接到Foundation时,我想它认为它需要分配自己的事件线程。
答案 1 :(得分:0)
相关行为,就像9年前有人报道的那样: http://lists.apple.com/archives/coreaudio-api/2001/May/msg00021.html