Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the computer's current volume level?

How do I access the current volume level of a Mac from the Cocoa API?

For example: when I'm using Spotify.app on OS X 10.7 and a sound advertisement comes up, and I turn down my Mac's volume, the app will pause the ad until I turn it back up to an average level. I find this incredibly obnoxious and a violation of user privacy, but somehow Spotify has found a way to do this.

Is there any way I can do this with Cocoa? I'm making an app where it might come in useful to warn the user if the volume is low.

like image 515
element119 Avatar asked Jan 21 '12 04:01

element119


1 Answers

There are two options available. The first step is to determine what device you'd like and get its ID. Assuming the default output device, the code will look something like:

AudioObjectPropertyAddress propertyAddress = { 
    kAudioHardwarePropertyDefaultOutputDevice, 
    kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster 
};

AudioDeviceID deviceID;
UInt32 dataSize = sizeof(deviceID);
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, &deviceID);

if(kAudioHardwareNoError != result)
    // Handle the error

Next, you can use the kAudioHardwareServiceDeviceProperty_VirtualMasterVolume property to get the device's virtual master volume:

AudioObjectPropertyAddress propertyAddress = { 
    kAudioHardwareServiceDeviceProperty_VirtualMasterVolume, 
    kAudioDevicePropertyScopeOutput,
    kAudioObjectPropertyElementMaster 
};

if(!AudioHardwareServiceHasProperty(deviceID, &propertyAddress))
    // An error occurred

Float32 volume;
UInt32 dataSize = sizeof(volume);
OSStatus result = AudioHardwareServiceGetPropertyData(deviceID, &propertyAddress, 0, NULL, &dataSize, &volume);

if(kAudioHardwareNoError != result)
    // An error occurred

Alternatively, you can use kAudioDevicePropertyVolumeScalar to get the volume for a specific channel:

UInt32 channel = 1; // Channel 0  is master, if available
AudioObjectPropertyAddress propertyAddress = { 
    kAudioDevicePropertyVolumeScalar, 
    kAudioDevicePropertyScopeOutput,
    channel 
};

if(!AudioObjectHasProperty(deviceID, &propertyAddress))
    // An error occurred

Float32 volume;
UInt32 dataSize = sizeof(volume);
OSStatus result = AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, NULL, &dataSize, &volume);

if(kAudioHardwareNoError != result)
    // An error occurred

The difference between the two is explained in Apple's docs:

kAudioHardwareServiceDeviceProperty_VirtualMasterVolume

A Float32 value that represents the value of the volume control. The range for this property’s value is 0.0 (silence) through 1.0 (full level). The effect of this property depends on the hardware device associated with the HAL audio object. If the device has a master volume control, this property controls it. If the device has individual channel volume controls, this property applies to those identified by the device's preferred multichannel layout, or the preferred stereo pair if the device is stereo only. This control maintains relative balance between the channels it affects.

So it can be tricky to define exactly what a device's volume is, especially for multichannel devices with non-standard channel maps.

like image 50
sbooth Avatar answered Oct 02 '22 11:10

sbooth