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; |