这很简单(我想)。我只是想在我的应用程序中得到一个通知,每当用户在“系统偏好设置 - 声音”中更改默认的声音输入或声音输出设备。但是,我真的找不到苹果文档中的相关信息。
另外说一下,这是针对OSX而不是IOS的。
谢谢!
另外说一下,这是针对OSX而不是IOS的。
谢谢!
为默认输出设备设置AudioObjectPropertyAddress
:
AudioObjectPropertyAddress outputDeviceAddress = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
接下来使用AudioObjectAddPropertyListener
为默认设备注册监听器:
AudioObjectAddPropertyListener(kAudioObjectSystemObject,
&outputDeviceAddress,
&callbackFunction, nil);
OSStatus callbackFunction(AudioObjectID inObjectID,
UInt32 inNumberAddresses,
const AudioObjectPropertyAddress inAddresses[],
void *inClientData)
AudioObjectPropertyAddress
来告诉HAL管理自己的线程以进行通知。通过将运行循环选择器设置为NULL来实现此操作。实际上,在设置输出设备侦听器之前,我会执行这个步骤。AudioObjectPropertyAddress runLoopAddress = {
kAudioHardwarePropertyRunLoop,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
CFRunLoopRef runLoop = NULL;
UInt32 size = sizeof(CFRunLoopRef);
AudioObjectSetPropertyData(kAudioObjectSystemObject,
&runLoopAddress, 0, NULL, size, &runLoop);
Register for notifications by adding a listener block, for example when a View Controller loads its view. The addListenerBlock
function simplifies adding property listener blocks. Swift allows parameters to be variables, which is very convenient for the forPropertyAddress
parameter. When calling addListenerBlock
, the property address parameters are just plugged in.
import Cocoa
import CoreAudio
class ViewController: NSViewController {
// Utility function to simplify adding listener blocks:
func addListenerBlock( listenerBlock: AudioObjectPropertyListenerBlock, onAudioObjectID: AudioObjectID, var forPropertyAddress: AudioObjectPropertyAddress) {
if (kAudioHardwareNoError != AudioObjectAddPropertyListenerBlock(onAudioObjectID, &forPropertyAddress, nil, listenerBlock)) {
print("Error calling: AudioObjectAddPropertyListenerBlock") }
}
override func viewDidLoad() { super.viewDidLoad()
addListenerBlock(audioObjectPropertyListenerBlock,
onAudioObjectID: AudioObjectID(bitPattern: kAudioObjectSystemObject),
forPropertyAddress: AudioObjectPropertyAddress(
mSelector: kAudioHardwarePropertyDefaultOutputDevice,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster))
}
...
Provide a listener block function to receive the notifications. You're given an array that could potentially have more than one property address, so loop through and look for the one you want:
func audioObjectPropertyListenerBlock (numberAddresses: UInt32, addresses: UnsafePointer<AudioObjectPropertyAddress>) {
var index: UInt32 = 0
while index < numberAddresses {
let address: AudioObjectPropertyAddress = addresses[0]
switch address.mSelector {
case kAudioHardwarePropertyDefaultOutputDevice:
let deviceID = getDefaultAudioOutputDevice()
print("kAudioHardwarePropertyDefaultOutputDevice: \(deviceID)")
default:
print("We didn't expect this!")
}
index += 1
}
// Utility function to get default audio output device:
func getDefaultAudioOutputDevice () -> AudioObjectID {
var devicePropertyAddress = AudioObjectPropertyAddress(mSelector: kAudioHardwarePropertyDefaultOutputDevice, mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster)
var deviceID: AudioObjectID = 0
var dataSize = UInt32(truncatingBitPattern: sizeof(AudioDeviceID))
let systemObjectID = AudioObjectID(bitPattern: kAudioObjectSystemObject)
if (kAudioHardwareNoError != AudioObjectGetPropertyData(systemObjectID, &devicePropertyAddress, 0, nil, &dataSize, &deviceID)) { return 0 }
return deviceID
}
}
let address: AudioObjectPropertyAddress = addresses[0]
你是不是想用 index
而不是 0
? - GW.Rodriguez