I am looking to incorporate a NSSlider in a Cocoa application that controls the master volume of a Mac. I do not want to do this through AppleScript though, even though I know it is probably easier.
I found this code that should be able to do the trick but does not because since 10.5 AudioDeviceGetProperty and its ilk have been deprecated. What needs to be changed to make this work?
- (float) getVolume
{
float b_vol;
OSStatus err;
AudioDeviceID device;
UInt32 size;
UInt32 channels[2];
float volume[2];
// get device
size = sizeof device;
err = AudioObjectGetPropertyData(kAudioHardwarePropertyDefaultOutputDevice, &device, <#UInt32 inQualifierDataSize#>, <#const void *inQualifierData#>, &size, <#void *outData#>);
if(err!=noErr)
{
NSLog(@"audio-volume error get device");
return 0.0;
}
// try set master volume (channel 0)
size = sizeof b_vol;
err = AudioDeviceGetProperty(device, 0, 0, kAudioDevicePropertyVolumeScalar, &size, &b_vol); //kAudioDevicePropertyVolumeScalarToDecibels
if(noErr==err) return b_vol;
// otherwise, try seperate channels
// get channel numbers
size = sizeof(channels);
err = AudioDeviceGetProperty(device, 0, 0,kAudioDevicePropertyPreferredChannelsForStereo, &size,&channels);
if(err!=noErr) NSLog(@"error getting channel-numbers");
size = sizeof(float);
err = AudioDeviceGetProperty(device, channels[0], 0, kAudioDevicePropertyVolumeScalar, &size, &volume[0]);
if(noErr!=err) NSLog(@"error getting volume of channel %d",channels[0]);
err = AudioDeviceGetProperty(device, channels[1], 0, kAudioDevicePropertyVolumeScalar, &size, &volume[1]);
if(noErr!=err) NSLog(@"error getting volume of channel %d",channels[1]);
b_vol = (volume[0]+volume[1])/2.00;
return b_vol;
}
- (void)setVolume:(float)involume {
OSStatus err;
AudioDeviceID device;
UInt32 size;
Boolean canset = false;
UInt32 channels[2];
//float volume[2];
// get default device
size = sizeof device;
printf("setVolume:: value of the volume set =%lf", involume);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &device);
if(err!=noErr) {
NSLog(@"audio-volume error get device");
return;
}
// try set master-channel (0) volume
size = sizeof canset;
err = AudioDeviceGetPropertyInfo(device, 0, false, kAudioDevicePropertyVolumeScalar, &size, &canset);
if(err==noErr && canset==true) {
size = sizeof involume;
err = AudioDeviceSetProperty(device, NULL, 0, false, kAudioDevicePropertyVolumeScalar, size, &involume);
return;
}
// else, try seperate channes
// get channels
size = sizeof(channels);
err = AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyPreferredChannelsForStereo, &size,&channels);
if(err!=noErr) {
NSLog(@"error getting channel-numbers");
return;
}
// set volume
size = sizeof(float);
err = AudioDeviceSetProperty(device, 0, channels[0], false, kAudioDevicePropertyVolumeScalar, size, &involume);
if(noErr!=err) NSLog(@"error setting volume of channel %d",channels[0]);
err = AudioDeviceSetProperty(device, 0, channels[1], false, kAudioDevicePropertyVolumeScalar, size, &involume);
if(noErr!=err) NSLog(@"error setting volume of channel %d",channels[1]);
}
Thanks in advance!
This will do the trick - I just copied and pasted it out of one of my projects, so there are a few extraneous variables and functions but you should be able to get the gist of it:
BOOL gotMaster = NO;
BOOL gotLeft = NO;
BOOL gotRight = NO;
float volume = 1, lvolume = 1, rvolume = 1;
float inVolume = 1, inLvolume = 1, inRvolume = 1;
OSStatus result = noErr;
AudioObjectPropertyAddress thePropertyAddress;
UInt32 thePropSize = sizeof(Float32);
thePropertyAddress.mSelector = kAudioDevicePropertyVolumeScalar;
thePropertyAddress.mScope = kAudioDevicePropertyScopeOutput;
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster;
// see if the device supports volume control, if so, then get it
if (AudioObjectHasProperty(_targetDevice, &thePropertyAddress)) {
result = AudioObjectGetPropertyData(_targetDevice, &thePropertyAddress, 0, NULL, &thePropSize, &volume);
if (result) { cwlog("AudioDeviceManager: Error in AudioObjectGetPropertyData: %d", result); return -1; }
gotMaster = YES;
} else {
cwlog("AudioDeviceManager: The target device does not support getting the master volume");
}
// see if the device supports left channel volume control, if so, then get it
thePropertyAddress.mElement = 1;
if (AudioObjectHasProperty(_targetDevice, &thePropertyAddress)) {
result = AudioObjectGetPropertyData(_targetDevice, &thePropertyAddress, 0, NULL, &thePropSize, &lvolume);
if (result) { cwlog("AudioDeviceManager: Error in AudioObjectGetPropertyData: %d", result); return -1; }
gotLeft = YES;
} else {
cwlog("AudioDeviceManager: The target device does not support getting the left channel volume");
}
thePropertyAddress.mElement = 2;
// see if the device supports right channel volume control, if so, then get it
if (AudioObjectHasProperty(_targetDevice, &thePropertyAddress)) {
result = AudioObjectGetPropertyData(_targetDevice, &thePropertyAddress, 0, NULL, &thePropSize, &rvolume);
if (result) { cwlog("AudioDeviceManager: Error in AudioObjectGetPropertyData: %d", result); return -1; }
gotRight = YES;
} else {
// if the device does not support master volume control, do nothing
cwlog("AudioDeviceManager: The target device does not support getting the right channel volume");
}
if(!gotMaster && !gotLeft && !gotRight) {
cwlog("AudioDeviceManager: Could not get any volume settings for %s (%u)", [[self nameOfDevice:_targetDevice] UTF8String], _targetDevice);
return -1;
}