2012-01-21 56 views
5

如何從Cocoa API訪問Mac的當前音量級別?如何獲取電腦的當前音量?

例如:當我在OS X 10.7上使用Spotify.app並出現聲音廣告時,我拒絕了我的Mac音量,該應用會暫停廣告直到我將其恢復到平均水平。我發現這種令人難以置信的討厭和侵犯用戶隱私,但不知何故Spotify找到了一種方法來做到這一點。

有什麼辦法,我可以用可可做到這一點?我正在製作一個應用程序,它可能會有用於在音量不足時提醒用戶。

+1

沒有一個單一的「當前音量」。有一個用於每個設備,常常每通道*一個*在設備上,並有兩個元的設備(至少對於輸出):「默認輸出裝置」(對於大多數聲音輸出)和「警報輸出裝置」 (用於提醒聲音,界面聲音等)。 –

回答

8

有兩種方法可供選擇。第一步是確定你想要什麼設備並獲得它的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音頻對象關聯的硬件設備 。如果該設備具有主控制器,則該屬性將控制該設備。如果設備具有 個別信道的音量控制,該屬性適用於由該設備的優選的多通道佈局確定的那些 ,或 優選立體對,如果設備僅是立體聲。該控件 保持其影響的頻道之間的相對平衡。

因此,精確定義設備的音量是非常棘手的,特別是對於具有非標準通道映射的多聲道設備。

+0

'kAudioHardwareServiceDeviceProperty_VirtualMasterVolume'在那個代碼中出現在哪裏? –

+0

我原本沒有發佈代碼,因爲艾薩克似乎在他的回答中涵蓋了這一點。不過,我會將其添加到我的答案中,以使其更加完整。 – sbooth

+0

我使用kAudioHardwareServiceDeviceProperty_VirtualMasterVolume和kAudioDevicePropertyVolumeScalar來獲取AudioObjectGetPropertyData的kAudioHardwareUnknownPropertyError。 Xcode 7.3.1 OS X 10.10 – rocky

2

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

什麼是'KNVolumeControl'? – sbooth

+0

@sbooth:我的部分複製/粘貼失敗。現在應該修復。 (和你的答案+1,這似乎是沿着相同的路線,但實際上解釋它。) – Isaac

+0

鏈接到CocoaDev已經死了。這需要'-framework可可-framework AudioToolbox' –