diff options
Diffstat (limited to 'chromium/media/audio/pulse/audio_manager_pulse.cc')
-rw-r--r-- | chromium/media/audio/pulse/audio_manager_pulse.cc | 92 |
1 files changed, 87 insertions, 5 deletions
diff --git a/chromium/media/audio/pulse/audio_manager_pulse.cc b/chromium/media/audio/pulse/audio_manager_pulse.cc index fc0ec5d6c4d..3cd51959861 100644 --- a/chromium/media/audio/pulse/audio_manager_pulse.cc +++ b/chromium/media/audio/pulse/audio_manager_pulse.cc @@ -4,6 +4,9 @@ #include "media/audio/pulse/audio_manager_pulse.h" +#include <algorithm> +#include <utility> + #include "base/command_line.h" #include "base/environment.h" #include "base/logging.h" @@ -40,7 +43,8 @@ AudioManagerPulse::AudioManagerPulse(std::unique_ptr<AudioThread> audio_thread, input_context_(pa_context), devices_(NULL), native_input_sample_rate_(0), - native_channel_count_(0) { + native_channel_count_(0), + default_source_is_monitor_(false) { DCHECK(input_mainloop_); DCHECK(input_context_); SetMaxOutputStreamsAllowed(kMaxOutputStreams); @@ -107,6 +111,12 @@ AudioParameters AudioManagerPulse::GetInputStreamParameters( // TODO(xians): add support for querying native channel layout for pulse. UpdateNativeAudioHardwareInfo(); + // We don't want to accidentally open a monitor device, so return invalid + // parameters for those. + if (device_id == AudioDeviceDescription::kDefaultDeviceId && + default_source_is_monitor_) { + return AudioParameters(); + } return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, native_input_sample_rate_, buffer_size); @@ -149,6 +159,46 @@ AudioInputStream* AudioManagerPulse::MakeLowLatencyInputStream( return MakeInputStream(params, device_id); } +std::string AudioManagerPulse::GetDefaultInputDeviceID() { +#if defined(OS_CHROMEOS) + return AudioManagerBase::GetDefaultInputDeviceID(); +#else + return pulse::GetRealDefaultDeviceId(input_mainloop_, input_context_, + pulse::RequestType::INPUT); +#endif +} + +std::string AudioManagerPulse::GetDefaultOutputDeviceID() { +#if defined(OS_CHROMEOS) + return AudioManagerBase::GetDefaultOutputDeviceID(); +#else + return pulse::GetRealDefaultDeviceId(input_mainloop_, input_context_, + pulse::RequestType::OUTPUT); +#endif +} + +std::string AudioManagerPulse::GetAssociatedOutputDeviceID( + const std::string& input_device_id) { +#if defined(OS_CHROMEOS) + return AudioManagerBase::GetAssociatedOutputDeviceID(input_device_id); +#else + DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); + DCHECK(input_mainloop_); + DCHECK(input_context_); + std::string input = + (input_device_id == AudioDeviceDescription::kDefaultDeviceId) + ? pulse::GetRealDefaultDeviceId(input_mainloop_, input_context_, + pulse::RequestType::INPUT) + : input_device_id; + + std::string input_bus = + pulse::GetBusOfInput(input_mainloop_, input_context_, input); + return input_bus.empty() ? "" + : pulse::GetOutputCorrespondingTo( + input_mainloop_, input_context_, input_bus); +#endif +} + AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters( const std::string& output_device_id, const AudioParameters& input_params) { @@ -203,6 +253,10 @@ void AudioManagerPulse::UpdateNativeAudioHardwareInfo() { pa_operation* operation = pa_context_get_server_info( input_context_, AudioHardwareInfoCallback, this); WaitForOperationCompletion(input_mainloop_, operation); + operation = pa_context_get_source_info_by_name( + input_context_, default_source_name_.c_str(), DefaultSourceInfoCallback, + this); + WaitForOperationCompletion(input_mainloop_, operation); } void AudioManagerPulse::InputDevicesInfoCallback(pa_context* context, @@ -216,11 +270,22 @@ void AudioManagerPulse::InputDevicesInfoCallback(pa_context* context, return; } - // Exclude the output devices. - if (info->monitor_of_sink == PA_INVALID_INDEX) { - manager->devices_->push_back(AudioDeviceName(info->description, - info->name)); + // Exclude output monitor (i.e. loopback) devices. + if (info->monitor_of_sink != PA_INVALID_INDEX) + return; + + // If the device has ports, but none of them are available, skip it. + if (info->n_ports > 0) { + uint32_t port = 0; + for (; port != info->n_ports; ++port) { + if (info->ports[port]->available != PA_PORT_AVAILABLE_NO) + break; + } + if (port == info->n_ports) + return; } + + manager->devices_->push_back(AudioDeviceName(info->description, info->name)); } void AudioManagerPulse::OutputDevicesInfoCallback(pa_context* context, @@ -245,7 +310,24 @@ void AudioManagerPulse::AudioHardwareInfoCallback(pa_context* context, manager->native_input_sample_rate_ = info->sample_spec.rate; manager->native_channel_count_ = info->sample_spec.channels; + manager->default_source_name_ = info->default_source_name; pa_threaded_mainloop_signal(manager->input_mainloop_, 0); } +void AudioManagerPulse::DefaultSourceInfoCallback(pa_context* context, + const pa_source_info* info, + int eol, + void* user_data) { + AudioManagerPulse* manager = reinterpret_cast<AudioManagerPulse*>(user_data); + if (eol) { + // Signal the pulse object that it is done. + pa_threaded_mainloop_signal(manager->input_mainloop_, 0); + return; + } + + DCHECK(info); + manager->default_source_is_monitor_ = + info->monitor_of_sink != PA_INVALID_INDEX; +} + } // namespace media |