2012-01-21 48 views
5

Làm cách nào để truy cập mức âm lượng hiện tại của máy Mac từ API Cocoa?Làm thế nào để có được mức âm lượng hiện tại của máy tính?

Ví dụ: khi tôi đang sử dụng Spotify.app trên OS X 10.7 và quảng cáo âm thanh xuất hiện và tôi giảm âm lượng của máy Mac, ứng dụng sẽ tạm dừng quảng cáo cho đến khi tôi chuyển nó trở lại mức trung bình . Tôi thấy điều này vô cùng đáng ghét và sự vi phạm quyền riêng tư của người dùng, nhưng bằng cách nào đó Spotify đã tìm ra cách để làm điều này.

Có cách nào tôi có thể làm điều này với Cocoa không? Tôi đang tạo một ứng dụng có thể hữu ích khi cảnh báo người dùng nếu âm lượng thấp.

+1

Không có một "mức âm lượng hiện tại". Có một thiết bị cho mỗi thiết bị, thường là một * mỗi kênh * trên thiết bị và có hai thiết bị meta (ít nhất là cho đầu ra): “thiết bị đầu ra mặc định” (đối với hầu hết đầu ra âm thanh) và “thiết bị đầu ra cảnh báo” (đối với âm thanh cảnh báo, âm thanh giao diện, v.v.). –

Trả lời

8

Có hai tùy chọn có sẵn. Bước đầu tiên là xác định thiết bị nào bạn muốn và nhận ID của thiết bị đó. Giả sử các thiết bị đầu ra mặc định, mã sẽ giống như thế:

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 

Tiếp theo, bạn có thể sử dụng kAudioHardwareServiceDeviceProperty_VirtualMasterVolume bất động sản để có được âm lượng tổng thể ảo của thiết bị:

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 

Ngoài ra, bạn có thể sử dụng kAudioDevicePropertyVolumeScalar để tải âm lượng cho một kênh cụ thể:

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 

Sự khác biệt giữa hai kênh được giải thích trong tài liệu của Apple:

kAudioHardwareServiceDeviceProperty_VirtualMasterVolume

Một giá trị float32 đại diện cho giá trị của điều khiển âm lượng. Phạm vi cho giá trị của thuộc tính này là 0.0 (im lặng) đến 1.0 (đầy đủ cấp). Ảnh hưởng của thuộc tính này phụ thuộc vào thiết bị phần cứng được kết hợp với đối tượng âm thanh HAL. Nếu thiết bị có điều khiển âm lượng chính , thuộc tính này sẽ kiểm soát nó. Nếu thiết bị có các điều khiển âm lượng kênh riêng lẻ , thì thuộc tính này áp dụng cho được xác định bởi bố cục đa kênh ưa thích của thiết bị hoặc cặp stereo ưa thích nếu thiết bị chỉ có âm thanh nổi. Điều khiển này duy trì sự cân bằng tương đối giữa các kênh mà nó ảnh hưởng.

Vì vậy, có thể khó xác định chính xác khối lượng thiết bị là gì, đặc biệt đối với các thiết bị đa kênh có bản đồ kênh không chuẩn.

+0

'kAudioHardwareServiceDeviceProperty_VirtualMasterVolume' ở đâu trong mã đó? –

+0

Tôi đã không đăng mã cho điều này ban đầu bởi vì Isaac dường như bao gồm điều đó trong câu trả lời của mình.Tôi sẽ thêm nó vào câu trả lời của tôi để làm cho nó hoàn chỉnh hơn, tuy nhiên. – sbooth

+0

Tôi nhận được kAudioHardwareUnknownPropertyError cho AudioObjectGetPropertyData sử dụng cả kAudioHardwareServiceDeviceProperty_VirtualMasterVolume và kAudioDevicePropertyVolumeScalar. Xcode 7.3.1 OS X 10.10 – rocky

2

Từ CocoaDev, những phương pháp lớp trông giống như họ nên làm việc, mặc dù nó không phải là đặc biệt ca cao giống như:

#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' là gì? – sbooth

+0

@sbooth: sao chép/dán không thành công. Nên được cố định ngay bây giờ. (Và +1 trên câu trả lời của bạn, mà dường như là cùng một dòng, nhưng thực sự giải thích nó.) – Isaac

+0

Liên kết đến CocoaDev đã chết. Điều này đòi hỏi '-framework Cocoa -framework AudioToolbox' –

Các vấn đề liên quan