如何更新CoreAudio程序代码以消除编译时的“函数已废弃”警告
嘿,我正好碰到过一模一样的问题!这些警告都是因为苹果在Mac OS X 10.6(Snow Leopard)之后就把旧的CoreAudio硬件直接操作API标记为废弃了,转而推荐用更统一、更灵活的AudioObject API——这套API把所有音频相关对象(设备、系统硬件、插件等)都抽象成AudioObject,用标准化的方式处理属性读写和事件监听。我来给你逐个对应替换方案,都是实际测试过可用的:
1. 替换 AudioDeviceSetProperty
旧函数用来设置音频设备的属性(比如你代码里的kAudioDevicePropertyHogMode),替换成AudioObjectSetPropertyData,核心是用AudioObjectPropertyAddress结构体明确属性的作用域和元素:
旧代码
const OSStatus err = AudioDeviceSetProperty(cadi()->GetAudioDeviceID(), 0, 0, FALSE, kAudioDevicePropertyHogMode, sizeof(myPID), &myPID);
新代码
// 构造属性地址,明确要操作的属性、作用域和元素 AudioObjectPropertyAddress propertyAddr = { kAudioDevicePropertyHogMode, kAudioObjectPropertyScopeGlobal, // 对应旧API的第一个0参数(全局作用域) kAudioObjectPropertyElementMaster // 对应旧API的第二个0参数(主元素) }; const OSStatus err = AudioObjectSetPropertyData( cadi()->GetAudioDeviceID(), &propertyAddr, 0, // 无选择器参数 NULL, // 无选择器数据 sizeof(myPID), &myPID );
2. 替换 AudioDeviceAddPropertyListener
旧函数用来监听设备属性变化(比如你代码里的kAudioDeviceProcessorOverload),替换成AudioObjectAddPropertyListener:
旧代码
const OSStatus err = AudioDeviceAddPropertyListener(deviceID, 0, false, kAudioDeviceProcessorOverload, PlaybackDevicePropertyChanged, NULL);
新代码
AudioObjectPropertyAddress propertyAddr = { kAudioDevicePropertyProcessorOverload, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; const OSStatus err = AudioObjectAddPropertyListener( deviceID, &propertyAddr, PlaybackDevicePropertyChanged, // 回调函数签名和旧API完全兼容,不用改 NULL // 传递给回调的上下文,和旧API最后一个参数一致 );
3. 替换 AudioDeviceRemovePropertyListener
旧函数用来移除设备属性监听,替换成AudioObjectRemovePropertyListener:
旧代码
const OSStatus err = AudioDeviceRemovePropertyListener(deviceID, 0, false, kAudioDeviceProcessorOverload, PlaybackDevicePropertyChanged);
新代码
AudioObjectPropertyAddress propertyAddr = { kAudioDevicePropertyProcessorOverload, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; const OSStatus err = AudioObjectRemovePropertyListener( deviceID, &propertyAddr, PlaybackDevicePropertyChanged, NULL // 注意:要和添加监听时传递的上下文参数完全一致 );
4. 替换 AudioHardwareGetPropertyInfo 和 AudioHardwareGetProperty
旧函数用来获取系统音频硬件的属性(比如你代码里的kAudioHardwarePropertyPlugInForBundleID),替换成AudioObjectGetPropertyDataSize(替代属性信息查询)和AudioObjectGetPropertyData(替代属性数据获取),系统音频对应的AudioObjectID是kAudioObjectSystemObject:
旧代码
OSStatus osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable); // ... osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
新代码
AudioObjectPropertyAddress propertyAddr = { kAudioHardwarePropertyPlugInForBundleID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; // 替代AudioHardwareGetPropertyInfo:先获取属性数据的大小 UInt32 outSize = 0; OSStatus osErr = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddr, 0, NULL, &outSize ); // 替代AudioHardwareGetPropertyInfo的可写性检查(如果需要的话) Boolean outWritable; osErr = AudioObjectIsPropertyWritable( kAudioObjectSystemObject, &propertyAddr, &outWritable ); // 替代AudioHardwareGetProperty:获取属性实际数据 osErr = AudioObjectGetPropertyData( kAudioObjectSystemObject, &propertyAddr, 0, NULL, &outSize, &pluginAVT );
几个额外注意事项:
- 确保你的编译目标至少是Mac OS X 10.6或更高,这些新API正好是10.6引入的,和旧API废弃的版本一致,不需要额外做版本兼容(如果你的程序还要支持更早的系统,可能需要加
#ifdef判断,但现在几乎没人用10.6之前的系统了) - 所有原有的属性ID(比如
kAudioDevicePropertyHogMode)都是完全兼容的,不需要更换 - 调试时记得检查
OSStatus返回值,新API的错误码和旧API大部分是一致的,比如kAudioHardwareNoError表示操作成功
备注:内容来源于stack exchange,提问作者Jeremy Friesner

