Chromium Code Reviews| Index: media/audio/mac/audio_manager_mac.cc |
| diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc |
| index a4a621725a1371da8f75753e74d876cef8025c39..c116c28a109815bf52c317ca5bd7f7b119bd9e0a 100644 |
| --- a/media/audio/mac/audio_manager_mac.cc |
| +++ b/media/audio/mac/audio_manager_mac.cc |
| @@ -5,6 +5,7 @@ |
| #include <CoreAudio/AudioHardware.h> |
| #include "base/mac/mac_util.h" |
| +#include "base/sys_string_conversions.h" |
| #include "media/audio/fake_audio_input_stream.h" |
| #include "media/audio/fake_audio_output_stream.h" |
| #include "media/audio/mac/audio_input_mac.h" |
| @@ -65,6 +66,120 @@ static bool HasAudioHardware(AudioObjectPropertySelector selector) { |
| output_device_id != kAudioObjectUnknown; |
| } |
| +static void GetAudioDeviceInfo(bool is_input, |
| + media::AudioDeviceNames* device_names) { |
| + DCHECK(device_names); |
| + device_names->clear(); |
| + |
| + // Query the number of total devices. |
| + AudioObjectPropertyAddress property_address = { |
| + kAudioHardwarePropertyDevices, |
| + kAudioObjectPropertyScopeGlobal, |
| + kAudioObjectPropertyElementMaster |
| + }; |
| + UInt32 size = 0; |
| + OSStatus result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, |
| + &property_address, |
| + 0, |
| + NULL, |
| + &size); |
| + if (result || !size) |
| + return; |
| + |
| + int device_count = size / sizeof(AudioDeviceID); |
| + |
| + // Get the array of device ids for all the devices, which includes both |
| + // input devices and output devices. |
| + scoped_ptr_malloc<AudioDeviceID> |
| + devices(reinterpret_cast<AudioDeviceID*>(malloc(size))); |
| + AudioDeviceID* device_ids = devices.get(); |
| + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, |
| + &property_address, |
| + 0, |
| + NULL, |
| + &size, |
| + device_ids); |
| + if (result) |
| + return; |
| + |
| + // Iterate over all available devices to gather information. |
| + for (int i = 0; i < device_count; ++i) { |
| + int channels = 0; |
| + // Get the number of input or output channels of the device. |
| + property_address.mScope = is_input ? |
| + kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; |
| + property_address.mSelector = kAudioDevicePropertyStreamConfiguration; |
| + result = AudioObjectGetPropertyDataSize(device_ids[i], |
| + &property_address, |
| + 0, |
| + NULL, |
| + &size); |
| + if (result) |
| + continue; |
| + |
| + scoped_ptr_malloc<AudioBufferList> |
| + buffer(reinterpret_cast<AudioBufferList*>(malloc(size))); |
| + AudioBufferList* buffer_list = buffer.get(); |
| + result = AudioObjectGetPropertyData(device_ids[i], |
| + &property_address, |
| + 0, |
| + NULL, |
| + &size, |
| + buffer_list); |
| + if (result) |
| + continue; |
| + |
| + for (uint32 j = 0; j < buffer_list->mNumberBuffers; ++j) |
| + channels += buffer_list->mBuffers[j].mNumberChannels; |
| + |
| + // Exclude those devices without the type of channel we are interested in. |
| + if (!channels) |
| + continue; |
| + |
| + // Get device UID. |
| + CFStringRef uid = NULL; |
| + size = sizeof(uid); |
| + property_address.mSelector = kAudioDevicePropertyDeviceUID; |
| + property_address.mScope = kAudioObjectPropertyScopeGlobal; |
| + result = AudioObjectGetPropertyData(device_ids[i], |
| + &property_address, |
| + 0, |
| + NULL, |
| + &size, |
| + &uid); |
| + if (result) |
| + continue; |
| + |
| + // Get device name. |
| + CFStringRef name = NULL; |
| + property_address.mSelector = kAudioObjectPropertyName; |
| + property_address.mScope = kAudioObjectPropertyScopeGlobal; |
| + result = AudioObjectGetPropertyData(device_ids[i], |
| + &property_address, |
| + 0, |
| + NULL, |
| + &size, |
| + &name); |
| + if (result) { |
| + if (uid) |
| + CFRelease(uid); |
| + continue; |
| + } |
| + |
| + // Store the device name and UID. |
| + media::AudioDeviceName device_name; |
| + device_name.device_name = base::SysCFStringRefToUTF8(name); |
| + device_name.unique_id = base::SysCFStringRefToUTF8(uid); |
| + device_names->push_back(device_name); |
| + |
| + // We are responsible for releasing the returned CFObject. |
|
Avi (use Gerrit)
2011/10/27 05:07:14
Be a little more clear here. "Despite being obtain
no longer working on chromium
2011/10/28 16:32:37
Done.
|
| + if (uid) |
| + CFRelease(uid); |
| + if(name) |
|
Avi (use Gerrit)
2011/10/27 05:07:14
space before (
no longer working on chromium
2011/10/28 16:32:37
Done.
|
| + CFRelease(name); |
| + } |
| +} |
| + |
| AudioManagerMac::AudioManagerMac() |
| : num_output_streams_(0) { |
| } |
| @@ -82,15 +197,15 @@ bool AudioManagerMac::HasAudioInputDevices() { |
| void AudioManagerMac::GetAudioInputDeviceNames( |
| media::AudioDeviceNames* device_names) { |
| - // TODO(xians): query a full list of valid devices. |
| - if (HasAudioInputDevices()) { |
| - // Add the default device to the list. |
| - // We use index 0 to make up the unique_id to identify the |
| - // default devices. |
| + GetAudioDeviceInfo(true, device_names); |
| + if (!device_names->empty()) { |
| + // Prepend the default device to the list since we always want it to be |
| + // on the top of the list for all platforms. There is no duplicate |
| + // counting here since the default device has been abstracted out before. |
| media::AudioDeviceName name; |
| name.device_name = AudioManagerBase::kDefaultDeviceName; |
| name.unique_id = "0"; |
| - device_names->push_back(name); |
| + device_names->push_front(name); |
| } |
| } |