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 21b931809a5333e89595deae95be058455791d6f..bef019a735821e0c4c046d80f4f95e38b64668d7 100644 |
| --- a/media/audio/mac/audio_manager_mac.cc |
| +++ b/media/audio/mac/audio_manager_mac.cc |
| @@ -186,7 +186,7 @@ static AudioDeviceID GetAudioDeviceIdByUId(bool is_input, |
| UInt32 device_size = sizeof(audio_device_id); |
| OSStatus result = -1; |
| - if (device_id == AudioManagerBase::kDefaultDeviceId) { |
| + if (device_id == AudioManagerBase::kDefaultDeviceId || device_id.empty()) { |
| // Default Device. |
| property_address.mSelector = is_input ? |
| kAudioHardwarePropertyDefaultInputDevice : |
| @@ -441,6 +441,64 @@ AudioParameters AudioManagerMac::GetInputStreamParameters( |
| sample_rate, 16, buffer_size); |
| } |
| +std::string AudioManagerMac::GetAssociatedOutputDeviceID( |
| + const std::string& input_device_id) { |
| + AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); |
| + if (device == kAudioObjectUnknown) |
| + return std::string(); |
| + |
| + UInt32 size = 0; |
| + AudioObjectPropertyAddress pa = { |
| + kAudioDevicePropertyRelatedDevices, |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
Guess thus guy is the key here. Nice.
|
| + kAudioObjectPropertyScopeOutput, |
| + kAudioObjectPropertyElementMaster |
| + }; |
| + OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size); |
| + if (result || !size) |
| + return std::string(); |
| + |
| + int device_count = size / sizeof(AudioDeviceID); |
| + scoped_ptr_malloc<AudioDeviceID> |
| + devices(reinterpret_cast<AudioDeviceID*>(malloc(size))); |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
I always hesitate to use reinterpret; you don't ;-
tommi (sloooow) - chröme
2013/09/08 19:11:19
Not when it's the right thing to do ;)
|
| + result = AudioObjectGetPropertyData( |
| + device, &pa, 0, NULL, &size, devices.get()); |
| + if (result) |
| + return std::string(); |
| + |
| + for (int i = 0; i < device_count; ++i) { |
| + // Get the number of output channels of the device. |
| + pa.mSelector = kAudioDevicePropertyStreams; |
| + size = 0; |
| + result = AudioObjectGetPropertyDataSize(devices.get()[i], |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
Nit, I did clang-format on my latest CL and I thin
tommi (sloooow) - chröme
2013/09/08 19:11:19
This is fine style-wize and consistent with all ot
|
| + &pa, |
| + 0, |
| + NULL, |
| + &size); |
| + if (result || !size) |
| + continue; // Skip if there aren't any output channels. |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
Don't we have methods to detect number of output d
tommi (sloooow) - chröme
2013/09/08 19:11:19
See line 453 where the "scope" is set to output.
W
|
| + |
| + // Get device UID. |
| + CFStringRef uid = NULL; |
| + size = sizeof(uid); |
| + pa.mSelector = kAudioDevicePropertyDeviceUID; |
| + result = AudioObjectGetPropertyData(devices.get()[i], |
| + &pa, |
| + 0, |
| + NULL, |
| + &size, |
| + &uid); |
| + if (result || !uid) |
| + continue; |
| + |
| + std::string ret(base::SysCFStringRefToUTF8(uid)); |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
What does these IDs look like?
tommi (sloooow) - chröme
2013/09/08 19:11:19
Here's an example of a USB device I tested with:
i
|
| + CFRelease(uid); |
| + return ret; |
| + } |
| + |
| + // No matching device found. |
| + return std::string(); |
| +} |
| + |
| AudioOutputStream* AudioManagerMac::MakeLinearOutputStream( |
| const AudioParameters& params) { |
| return MakeLowLatencyOutputStream(params, std::string(), std::string()); |
| @@ -507,6 +565,29 @@ AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( |
| kAudioDeviceUnknown); |
| } |
| +std::string AudioManagerMac::GetDefaultOutputDeviceID() { |
| + AudioDeviceID device_id = kAudioObjectUnknown; |
| + if (!GetDefaultOutputDevice(&device_id)) |
| + return std::string(); |
| + |
| + const AudioObjectPropertyAddress property_address = { |
| + kAudioDevicePropertyDeviceUID, |
| + kAudioObjectPropertyScopeGlobal, |
| + kAudioObjectPropertyElementMaster |
| + }; |
| + CFStringRef device_uid = NULL; |
| + UInt32 size = sizeof(device_uid); |
| + OSStatus status = AudioObjectGetPropertyData(device_id, &property_address, 0, |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
Different style than above ;-)
tommi (sloooow) - chröme
2013/09/08 19:11:19
Fixed.
|
| + NULL, &size, &device_uid); |
| + if (status != kAudioHardwareNoError || !device_uid) |
| + return std::string(); |
| + |
| + std::string ret(base::SysCFStringRefToUTF8(device_uid)); |
| + CFRelease(device_uid); |
| + |
| + return ret; |
| +} |
| + |
| AudioInputStream* AudioManagerMac::MakeLinearInputStream( |
| const AudioParameters& params, const std::string& device_id) { |
| DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); |
| @@ -529,17 +610,22 @@ AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream( |
| AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters( |
| const std::string& output_device_id, |
| const AudioParameters& input_params) { |
| - // TODO(tommi): Support |output_device_id|. |
| - DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; |
| + AudioDeviceID device = GetAudioDeviceIdByUId(true, output_device_id); |
| + if (device == kAudioObjectUnknown) { |
| + DLOG(ERROR) << "Invalid device " << output_device_id; |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
I would say Invalid output device just in case
tommi (sloooow) - chröme
2013/09/08 19:11:19
Done.
|
| + return AudioParameters(); |
| + } |
| + |
| int hardware_channels = 2; |
|
henrika (OOO until Aug 14)
2013/09/07 08:04:25
Don't understand this "fallback" scheme. Do you?
tommi (sloooow) - chröme
2013/09/08 19:11:19
Not really. I guess there must be a case where we
|
| - if (!GetDefaultOutputChannels(&hardware_channels)) { |
| + if (!GetDeviceChannels(device, kAudioDevicePropertyScopeOutput, |
| + &hardware_channels)) { |
| // Fallback to stereo. |
| hardware_channels = 2; |
| } |
| ChannelLayout channel_layout = GuessChannelLayout(hardware_channels); |
| - const int hardware_sample_rate = AUAudioOutputStream::HardwareSampleRate(); |
| + const int hardware_sample_rate = HardwareSampleRateForDevice(device); |
| const int buffer_size = ChooseBufferSize(hardware_sample_rate); |
| int input_channels = 0; |