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%?
I ran the HALLab utility that comes with the developer tools (i.e. Audio Tools for Xcode). That allows you to open an info window for individual devices and that window has a tab showing notifications. When I change my system volume, I do indeed see that the
kAudioDevicePropertyVolumeScalar
property changes for each channel of the output device as Thomas O'Dell's answer suggests. However, I also see the propertykAudioHardwareServiceDeviceProperty_VirtualMasterVolume
change on the master channel. That seems much more promising since you don't have to manually set it for all channels and maintain the balance across them.You would use the function
AudioHardwareServiceSetPropertyData()
from Audio Hardware Services to set that on the default output device. To be safe, you might first check that it's settable usingAudioHardwareServiceIsPropertySettable()
.The documentation for that property says:
You need to get the default audio device first:
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?')
Hope this answers your question!
You could run a bash script that will change the master volume. This prevents setting the audio first to one side:
Muted:
Change volume (scale 0-10):