如何注册声音音量变化的通知?

dan*_*dan 5 cocoa objective-c core-audio

当OS X音量发生变化时,我需要通知我的应用程序.这适用于桌面应用,不适用于iOS.我如何注册此通知?

sbo*_*oth 10

这可能有点棘手,因为有些音频设备支持主通道,但大多数音频设备不支持主通道属性.根据您的需要,您只能观察一个通道,并假设设备支持的所有其他通道具有相同的音量.无论您想要观看多少个频道,都可以通过为相关AudioObject注册属性侦听器来观察音量:

// Some devices (but not many) support a master channel
AudioObjectPropertyAddress propertyAddress = { 
    kAudioDevicePropertyVolumeScalar, 
    kAudioDevicePropertyScopeOutput,
    kAudioObjectPropertyElementMaster 
};

if(AudioObjectHasProperty(deviceID, &propertyAddress)) {
    OSStatus result = AudioObjectAddPropertyListener(deviceID, &propertyAddress, myAudioObjectPropertyListenerProc, self);
    // Error handling omitted
}
else {
    // Typically the L and R channels are 1 and 2 respectively, but could be different
    propertyAddress.mElement = 1;
    OSStatus result = AudioObjectAddPropertyListener(deviceID, &propertyAddress, myAudioObjectPropertyListenerProc, self);
    // Error handling omitted

    propertyAddress.mElement = 2;
    result = AudioObjectAddPropertyListener(deviceID, &propertyAddress, myAudioObjectPropertyListenerProc, self);
    // Error handling omitted
}
Run Code Online (Sandbox Code Playgroud)

你的听众proc应该是这样的:

static OSStatus
myAudioObjectPropertyListenerProc(AudioObjectID                         inObjectID,
                                  UInt32                                inNumberAddresses,
                                  const AudioObjectPropertyAddress      inAddresses[],
                                  void                                  *inClientData)
{
    for(UInt32 addressIndex = 0; addressIndex < inNumberAddresses; ++addressIndex) {
        AudioObjectPropertyAddress currentAddress = inAddresses[addressIndex];

        switch(currentAddress.mSelector) {
            case kAudioDevicePropertyVolumeScalar:
            {
                Float32 volume = 0;
                UInt32 dataSize = sizeof(volume);
                OSStatus result = AudioObjectGetPropertyData(inObjectID, &currentAddress, 0, NULL, &dataSize, &volume);

                if(kAudioHardwareNoError != result) {
                    // Handle the error
                    continue;
                }

                // Process the volume change

                break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)