How do I register for a notification for then the sound volume changes?

后端 未结 1 1019
感情败类
感情败类 2021-02-06 12:57

I need my app to be notified when the OS X sound volume has changed. This is for a Desktop app, not for iOS. How can I register for this notification?

1条回答
  •  暗喜
    暗喜 (楼主)
    2021-02-06 14:00

    This can be a tiny bit tricky because some audio devices support a master channel, but most don't so the volume will be a per-channel property. Depending on what you need to do you could observe only one channel and assume that all other channels the device supports have the same volume. Regardless of how many channels you want to watch, you observe the volume by registering a property listener for the AudioObject in question:

    // 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
    }
    

    Your listener proc should be something like:

    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, ¤tAddress, 0, NULL, &dataSize, &volume);
    
                    if(kAudioHardwareNoError != result) {
                        // Handle the error
                        continue;
                    }
    
                    // Process the volume change
    
                    break;
                }
            }
        }
    }
    

    0 讨论(0)
提交回复
热议问题