通过 Cocoa 应用程序控制 Mac 上的主音量

发布于 2025-01-04 13:48:06 字数 3218 浏览 0 评论 0原文

我希望将 NSSlider 合并到 Cocoa 应用程序中来控制 Mac 的主音量。不过,我不想通过 AppleScript 来完成此操作,尽管我知道这可能更容易。

我发现这段代码应该能够做到这一点,但事实并非如此,因为自 10.5 AudioDeviceGetProperty 及其同类以来已被弃用。为了使这项工作有效,需要改变什么?

- (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]);

}

提前致谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风吹雨成花 2025-01-11 13:48:06

这可以解决问题 - 我刚刚将其复制并粘贴到我的一个项目中,因此存在一些无关的变量和函数,但您应该能够了解其要点:

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

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文