diff options
Diffstat (limited to 'media/audio/linux/audio_manager_linux.cc')
-rw-r--r-- | media/audio/linux/audio_manager_linux.cc | 89 |
1 files changed, 63 insertions, 26 deletions
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc index 38253e2e65..7596c2fe25 100644 --- a/media/audio/linux/audio_manager_linux.cc +++ b/media/audio/linux/audio_manager_linux.cc @@ -42,9 +42,9 @@ static const int kDefaultSampleRate = 48000; // hence surround devices are not stored in the list. static const char* kInvalidAudioInputDevices[] = { "default", + "dmix", "null", "pulse", - "dmix", "surround", }; @@ -105,7 +105,13 @@ void AudioManagerLinux::ShowAudioInputSettings() { void AudioManagerLinux::GetAudioInputDeviceNames( media::AudioDeviceNames* device_names) { DCHECK(device_names->empty()); - GetAlsaAudioInputDevices(device_names); + GetAlsaAudioDevices(kStreamCapture, device_names); +} + +void AudioManagerLinux::GetAudioOutputDeviceNames( + media::AudioDeviceNames* device_names) { + DCHECK(device_names->empty()); + GetAlsaAudioDevices(kStreamPlayback, device_names); } AudioParameters AudioManagerLinux::GetInputStreamParameters( @@ -117,7 +123,8 @@ AudioParameters AudioManagerLinux::GetInputStreamParameters( kDefaultSampleRate, 16, kDefaultInputBufferSize); } -void AudioManagerLinux::GetAlsaAudioInputDevices( +void AudioManagerLinux::GetAlsaAudioDevices( + StreamType type, media::AudioDeviceNames* device_names) { // Constants specified by the ALSA API for device hints. static const char kPcmInterfaceName[] = "pcm"; @@ -128,37 +135,40 @@ void AudioManagerLinux::GetAlsaAudioInputDevices( void** hints = NULL; int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints); if (!error) { - GetAlsaDevicesInfo(hints, device_names); + GetAlsaDevicesInfo(type, hints, device_names); // Destroy the hints now that we're done with it. wrapper_->DeviceNameFreeHint(hints); } else { - DLOG(WARNING) << "GetAudioInputDevices: unable to get device hints: " + DLOG(WARNING) << "GetAlsaAudioDevices: unable to get device hints: " << wrapper_->StrError(error); } } } void AudioManagerLinux::GetAlsaDevicesInfo( - void** hints, media::AudioDeviceNames* device_names) { + AudioManagerLinux::StreamType type, + void** hints, + media::AudioDeviceNames* device_names) { static const char kIoHintName[] = "IOID"; static const char kNameHintName[] = "NAME"; static const char kDescriptionHintName[] = "DESC"; - static const char kOutputDevice[] = "Output"; + + const char* unwanted_device_type = UnwantedDeviceTypeWhenEnumerating(type); for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { - // Only examine devices that are input capable. Valid values are + // Only examine devices of the right type. Valid values are // "Input", "Output", and NULL which means both input and output. scoped_ptr_malloc<char> io(wrapper_->DeviceNameGetHint(*hint_iter, kIoHintName)); - if (io != NULL && strcmp(kOutputDevice, io.get()) == 0) + if (io != NULL && strcmp(unwanted_device_type, io.get()) == 0) continue; - // Found an input device, prepend the default device since we always want - // it to be on the top of the list for all platforms. And there is no - // duplicate counting here since it is only done if the list is still empty. - // Note, pulse has exclusively opened the default device, so we must open - // the device via the "default" moniker. + // Found a device, prepend the default device since we always want + // it to be on the top of the list for all platforms. And there is + // no duplicate counting here since it is only done if the list is + // still empty. Note, pulse has exclusively opened the default + // device, so we must open the device via the "default" moniker. if (device_names->empty()) { device_names->push_front(media::AudioDeviceName( AudioManagerBase::kDefaultDeviceName, @@ -170,7 +180,7 @@ void AudioManagerLinux::GetAlsaDevicesInfo( wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName)); // Find out if the device is available. - if (IsAlsaDeviceAvailable(unique_device_name.get())) { + if (IsAlsaDeviceAvailable(type, unique_device_name.get())) { // Get the description for the device. scoped_ptr_malloc<char> desc(wrapper_->DeviceNameGetHint( *hint_iter, kDescriptionHintName)); @@ -196,25 +206,46 @@ void AudioManagerLinux::GetAlsaDevicesInfo( } } -bool AudioManagerLinux::IsAlsaDeviceAvailable(const char* device_name) { +// static +bool AudioManagerLinux::IsAlsaDeviceAvailable( + AudioManagerLinux::StreamType type, + const char* device_name) { if (!device_name) return false; - // Check if the device is in the list of invalid devices. - for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) { - if (strncmp(kInvalidAudioInputDevices[i], device_name, - strlen(kInvalidAudioInputDevices[i])) == 0) - return false; + // We do prefix matches on the device name to see whether to include + // it or not. + if (type == kStreamCapture) { + // Check if the device is in the list of invalid devices. + for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) { + if (strncmp(kInvalidAudioInputDevices[i], device_name, + strlen(kInvalidAudioInputDevices[i])) == 0) + return false; + } + return true; + } else { + DCHECK_EQ(kStreamPlayback, type); + // We prefer the device type that maps straight to hardware but + // goes through software conversion if needed (e.g. incompatible + // sample rate). + // TODO(joi): Should we prefer "hw" instead? + static const char kDeviceTypeDesired[] = "plughw"; + return strncmp(kDeviceTypeDesired, + device_name, + arraysize(kDeviceTypeDesired) - 1) == 0; } +} - return true; +// static +const char* AudioManagerLinux::UnwantedDeviceTypeWhenEnumerating( + AudioManagerLinux::StreamType wanted_type) { + return wanted_type == kStreamPlayback ? "Input" : "Output"; } -bool AudioManagerLinux::HasAnyAlsaAudioDevice(StreamType stream) { +bool AudioManagerLinux::HasAnyAlsaAudioDevice( + AudioManagerLinux::StreamType stream) { static const char kPcmInterfaceName[] = "pcm"; static const char kIoHintName[] = "IOID"; - const char* kNotWantedDevice = - (stream == kStreamPlayback ? "Input" : "Output"); void** hints = NULL; bool has_device = false; int card = -1; @@ -230,7 +261,8 @@ bool AudioManagerLinux::HasAnyAlsaAudioDevice(StreamType stream) { // "Input", "Output", and NULL which means both input and output. scoped_ptr_malloc<char> io(wrapper_->DeviceNameGetHint(*hint_iter, kIoHintName)); - if (io != NULL && strcmp(kNotWantedDevice, io.get()) == 0) + const char* unwanted_type = UnwantedDeviceTypeWhenEnumerating(stream); + if (io != NULL && strcmp(unwanted_type, io.get()) == 0) continue; // Wrong type, skip the device. // Found an input device. @@ -258,7 +290,9 @@ AudioOutputStream* AudioManagerLinux::MakeLinearOutputStream( AudioOutputStream* AudioManagerLinux::MakeLowLatencyOutputStream( const AudioParameters& params, + const std::string& device_id, const std::string& input_device_id) { + DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); // TODO(xians): Use input_device_id for unified IO. return MakeOutputStream(params); @@ -277,7 +311,10 @@ AudioInputStream* AudioManagerLinux::MakeLowLatencyInputStream( } AudioParameters AudioManagerLinux::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!"; static const int kDefaultOutputBufferSize = 2048; ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; int sample_rate = kDefaultSampleRate; |