Как мне зарегистрироваться для получения уведомления о том, что громкость звука изменится? - PullRequest
5 голосов
/ 19 июля 2011

Мне нужно, чтобы мое приложение было уведомлено, когда громкость звука OS X изменилась. Это для настольного приложения, а не для iOS. Как я могу зарегистрироваться для этого уведомления?

1 Ответ

10 голосов
/ 19 июля 2011

Это может быть немного сложнее, потому что некоторые аудиоустройства поддерживают главный канал, но большинство этого не делают, поэтому громкость будет свойством для каждого канала. В зависимости от того, что вам нужно сделать, вы можете наблюдать только один канал и предполагать, что все остальные каналы, поддерживаемые устройством, имеют одинаковую громкость. Независимо от того, сколько каналов вы хотите посмотреть, вы наблюдаете громкость, регистрируя прослушиватель свойства для рассматриваемого аудиообъекта:

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

Ваш прослушиватель должен выглядеть примерно так:

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;
            }
        }
    }
}
...