Change OS X system volume programmatically

core-audio, objective-c, osx-mountain-lion

Solution

You need to get the default audio device first:

#import <CoreAudio/CoreAudio.h>

AudioObjectPropertyAddress getDefaultOutputDevicePropertyAddress = {
  kAudioHardwarePropertyDefaultOutputDevice,
  kAudioObjectPropertyScopeGlobal,
  kAudioObjectPropertyElementMaster
};

AudioDeviceID defaultOutputDeviceID;
UInt32 volumedataSize = sizeof(defaultOutputDeviceID);
OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
                                             &getDefaultOutputDevicePropertyAddress,
                                             0, NULL,
                                             &volumedataSize, &defaultOutputDeviceID);

if(kAudioHardwareNoError != result)
{
  // ... handle error ...
}

You can then set your volume on channel 1 (left) and channel 2 (right). Note that channel 0 (master) does not seem to be supported (the set command returns 'who?')

AudioObjectPropertyAddress volumePropertyAddress = {
  kAudioDevicePropertyVolumeScalar,
  kAudioDevicePropertyScopeOutput,
  1 /*LEFT_CHANNEL*/
};

Float32 volume;
volumedataSize = sizeof(volume);

result = AudioObjectSetPropertyData(defaultOutputDeviceID,
                                    &volumePropertyAddress,
                                    0, NULL,
                                    sizeof(volume), &volume);
if (result != kAudioHardwareNoError) {
  // ... handle error ...
}

Hope this answers your question!

Problem

How can I change the volume programmatically from Objective-C? I found this question, Controlling OS X volume in Snow Leopard which suggests to do: ``` Float32 volume = 0.5; UInt32 size = sizeof(Float32); AudioObjectPropertyAddress address = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, 1 // Use values 1 and 2 here, 0 (master) does not seem to work }; OSStatus err; err = AudioObjectSetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, size, &volume); NSLog(@"status is %i", err); ``` This does nothing for me, and prints out `status is 2003332927`. I also tried using values `2` and `0` in the `address` structure, same result for both. How can I fix this and make it actually decrease the volume to 50%?

Original source