如何從Cocoa API訪問Mac的當前音量級別?如何獲取電腦的當前音量?
例如:當我在OS X 10.7上使用Spotify.app並出現聲音廣告時,我拒絕了我的Mac音量,該應用會暫停廣告直到我將其恢復到平均水平。我發現這種令人難以置信的討厭和侵犯用戶隱私,但不知何故Spotify找到了一種方法來做到這一點。
有什麼辦法,我可以用可可做到這一點?我正在製作一個應用程序,它可能會有用於在音量不足時提醒用戶。
如何從Cocoa API訪問Mac的當前音量級別?如何獲取電腦的當前音量?
例如:當我在OS X 10.7上使用Spotify.app並出現聲音廣告時,我拒絕了我的Mac音量,該應用會暫停廣告直到我將其恢復到平均水平。我發現這種令人難以置信的討厭和侵犯用戶隱私,但不知何故Spotify找到了一種方法來做到這一點。
有什麼辦法,我可以用可可做到這一點?我正在製作一個應用程序,它可能會有用於在音量不足時提醒用戶。
有兩種方法可供選擇。第一步是確定你想要什麼設備並獲得它的ID。假設默認的輸出設備,代碼看起來類似:
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
接下來,你可以使用kAudioHardwareServiceDeviceProperty_VirtualMasterVolume
屬性來獲取設備的虛擬主音量:
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
或者,你可以使用kAudioDevicePropertyVolumeScalar
來拿貨量特定通道:
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
兩者之間的差額,蘋果的文檔解釋:
kAudioHardwareServiceDeviceProperty_VirtualMasterVolume
甲浮點32值,該值表示音量控制的值。該 此屬性的範圍的值是0.0(沉默)通過1.0(全 電平)。此屬性的效果取決於與HAL音頻對象關聯的硬件設備 。如果該設備具有主控制器,則該屬性將控制該設備。如果設備具有 個別信道的音量控制,該屬性適用於由該設備的優選的多通道佈局確定的那些 ,或 優選立體對,如果設備僅是立體聲。該控件 保持其影響的頻道之間的相對平衡。
因此,精確定義設備的音量是非常棘手的,特別是對於具有非標準通道映射的多聲道設備。
'kAudioHardwareServiceDeviceProperty_VirtualMasterVolume'在那個代碼中出現在哪裏? –
我原本沒有發佈代碼,因爲艾薩克似乎在他的回答中涵蓋了這一點。不過,我會將其添加到我的答案中,以使其更加完整。 – sbooth
我使用kAudioHardwareServiceDeviceProperty_VirtualMasterVolume和kAudioDevicePropertyVolumeScalar來獲取AudioObjectGetPropertyData的kAudioHardwareUnknownPropertyError。 Xcode 7.3.1 OS X 10.10 – rocky
從CocoaDev,這些類方法看起來像他們應該工作,但它並不特別可可類:
#import <AudioToolbox/AudioServices.h>
+(AudioDeviceID)defaultOutputDeviceID
{
AudioDeviceID outputDeviceID = kAudioObjectUnknown;
// get output device device
UInt32 propertySize = 0;
OSStatus status = noErr;
AudioObjectPropertyAddress propertyAOPA;
propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
propertyAOPA.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
if (!AudioHardwareServiceHasProperty(kAudioObjectSystemObject, &propertyAOPA))
{
NSLog(@"Cannot find default output device!");
return outputDeviceID;
}
propertySize = sizeof(AudioDeviceID);
status = AudioHardwareServiceGetPropertyData(kAudioObjectSystemObject, &propertyAOPA, 0, NULL, &propertySize, &outputDeviceID);
if(status)
{
NSLog(@"Cannot find default output device!");
}
return outputDeviceID;
}
// getting system volume
+(float)volume
{
Float32 outputVolume;
UInt32 propertySize = 0;
OSStatus status = noErr;
AudioObjectPropertyAddress propertyAOPA;
propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
propertyAOPA.mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume;
propertyAOPA.mScope = kAudioDevicePropertyScopeOutput;
AudioDeviceID outputDeviceID = [[self class] defaultOutputDeviceID];
if (outputDeviceID == kAudioObjectUnknown)
{
NSLog(@"Unknown device");
return 0.0;
}
if (!AudioHardwareServiceHasProperty(outputDeviceID, &propertyAOPA))
{
NSLog(@"No volume returned for device 0x%0x", outputDeviceID);
return 0.0;
}
propertySize = sizeof(Float32);
status = AudioHardwareServiceGetPropertyData(outputDeviceID, &propertyAOPA, 0, NULL, &propertySize, &outputVolume);
if (status)
{
NSLog(@"No volume returned for device 0x%0x", outputDeviceID);
return 0.0;
}
if (outputVolume < 0.0 || outputVolume > 1.0) return 0.0;
return outputVolume;
}
沒有一個單一的「當前音量」。有一個用於每個設備,常常每通道*一個*在設備上,並有兩個元的設備(至少對於輸出):「默認輸出裝置」(對於大多數聲音輸出)和「警報輸出裝置」 (用於提醒聲音,界面聲音等)。 –