CoreAudio:在 10.6 上链接到 Foundation 时设备计数中断

发布于 2024-09-17 06:27:53 字数 1756 浏览 2 评论 0原文

我有一个混合 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 列表上发布了这个问题。)

I have a mixed C++/Objective-C project that uses AudioObjectGetPropertyDataSize to get the number of audio devices (such as USB headsets) plugged in. This API doesn't seem to work under certain conditions. For example, on 10.5 it will work but on 10.6 it won't detect when a new USB headset is plugged in.

I've pared down the problem to a small bit of code that reproduces the problem (it calls AudioObjectGetPropertyDataSize in a loop). The code will work on 10.6 (ie, it will detect when devices are plugged/unplugged) when its only linked against CoreAudio, but once you link against Foundation it will stop working.

I don't understand how linking to a framework can break code that otherwise works.

Here is the code (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;
}

And here is the 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

Any thoughts on this bizarre behavior? (btw, I've also posted this question on the CoreAudio list.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

长伴 2024-09-24 06:27:53

CoreAudio 列表回答了我的问题。我们需要告诉 CoreAudio 分配它自己的事件调度线程:

CFRunLoopRef theRunLoop =  NULL;
AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
AudioObjectSetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);

我怀疑发生的情况是,当程序链接到 Foundation 时,CoreAudio 假设主线程充当事件调度程序循环(很常见,因为通常使用 Objective-C)对于 GUI 程序)。当不链接到 Foundation 时,我猜它需要分配自己的事件线程。

The CoreAudio List answered my question. We need to tell CoreAudio to allocate its own event-dispatching thread:

CFRunLoopRef theRunLoop =  NULL;
AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
AudioObjectSetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);

I suspect what's happening is that when the program is linked to Foundation, CoreAudio assumes the main thread is acting as an event dispatcher loop (very common since Objective-C is usually used for GUI programs). When not linking against Foundation, I guess it figures that it needs to allocate its own event thread.

笑着哭最痛 2024-09-24 06:27:53

相关行为,就像9年前有人报道的那样:
http://lists.apple.com/archives/coreaudio- api/2001/May/msg00021.html

Related behavior, which is like 9 years ago someone reported:
http://lists.apple.com/archives/coreaudio-api/2001/May/msg00021.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文