diff options
author | xians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-29 00:59:31 +0000 |
---|---|---|
committer | xians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-29 00:59:31 +0000 |
commit | 059a0f41373e2c79141ed9c783565048de67fa6a (patch) | |
tree | 523290d68070eb4d452d0f9e18709a4ec33d59dd /media | |
parent | a9bf3a5fe62bead51846f9165dcebe3529bac134 (diff) | |
download | chromium_src-059a0f41373e2c79141ed9c783565048de67fa6a.zip chromium_src-059a0f41373e2c79141ed9c783565048de67fa6a.tar.gz chromium_src-059a0f41373e2c79141ed9c783565048de67fa6a.tar.bz2 |
Reland the CL 8162015.
CL 8162015 failed the trybot and was reverted.
But I could not reproduce the issue in my local machine, so I just make a new CL and test it on trybot again.
BUG=
TEST=
Review URL: http://codereview.chromium.org/8361031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107842 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/audio_device_name.cc | 18 | ||||
-rw-r--r-- | media/audio/audio_device_name.h | 9 | ||||
-rw-r--r-- | media/audio/linux/audio_manager_linux.cc | 187 | ||||
-rw-r--r-- | media/audio/linux/audio_manager_linux.h | 18 | ||||
-rw-r--r-- | media/media.gyp | 1 |
5 files changed, 172 insertions, 61 deletions
diff --git a/media/audio/audio_device_name.cc b/media/audio/audio_device_name.cc new file mode 100644 index 0000000..02bb03f --- /dev/null +++ b/media/audio/audio_device_name.cc @@ -0,0 +1,18 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/audio/audio_device_name.h" + +namespace media { + +AudioDeviceName::AudioDeviceName() {} + +AudioDeviceName::AudioDeviceName(const std::string& device_name, + const std::string& unique_id) + : device_name(device_name), + unique_id(unique_id) { +} + +} // namespace media + diff --git a/media/audio/audio_device_name.h b/media/audio/audio_device_name.h index ef3cd77..aa3cca0 100644 --- a/media/audio/audio_device_name.h +++ b/media/audio/audio_device_name.h @@ -7,11 +7,16 @@ #include <list> #include <string> +#include "media/base/media_export.h" namespace media { -struct AudioDeviceName { - std::string device_name; // Name and also display name of the device. +struct MEDIA_EXPORT AudioDeviceName { + AudioDeviceName(); + AudioDeviceName(const std::string& device_name, + const std::string& unique_id); + + std::string device_name; // Friendly name of the device. std::string unique_id; // Unique identifier for the device. }; diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc index 930c6b2..d6704fe 100644 --- a/media/audio/linux/audio_manager_linux.cc +++ b/media/audio/linux/audio_manager_linux.cc @@ -39,54 +39,13 @@ static const char* kInvalidAudioInputDevices[] = { "surround", }; -static bool IsValidAudioInputDevice(const char* device_name) { - if (!device_name) - return false; - - for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) { - if (strcmp(kInvalidAudioInputDevices[i], device_name) == 0) - return false; - } - - return true; -} - // Implementation of AudioManager. bool AudioManagerLinux::HasAudioOutputDevices() { - // TODO(ajwong): Make this actually query audio devices. - return true; + return HasAnyAlsaAudioDevice(kStreamPlayback); } bool AudioManagerLinux::HasAudioInputDevices() { - if (!initialized()) { - return false; - } - - // Constants specified by the ALSA API for device hints. - static const char kPcmInterfaceName[] = "pcm"; - bool has_device = false; - void** hints = NULL; - int card = -1; - - // Loop through the sound cards to get Alsa device hints. - // Don't use snd_device_name_hint(-1,..) since there is a access violation - // inside this ALSA API with libasound.so.2.0.0. - while (!wrapper_->CardNext(&card) && (card >= 0) && !has_device) { - int error = wrapper_->DeviceNameHint(card, - kPcmInterfaceName, - &hints); - if (error == 0) { - has_device = HasAnyValidAudioInputDevice(hints); - - // Destroy the hints now that we're done with it. - wrapper_->DeviceNameFreeHint(hints); - hints = NULL; - } else { - LOG(ERROR) << "Unable to get device hints: " << wrapper_->StrError(error); - } - } - - return has_device; + return HasAnyAlsaAudioDevice(kStreamCapture); } AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream( @@ -141,6 +100,7 @@ AudioInputStream* AudioManagerLinux::MakeAudioInputStream( if (!initialized()) return NULL; + // TODO(xians): Pass the device name From AudioInputController instead. std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice; if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) { device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( @@ -213,21 +173,47 @@ void AudioManagerLinux::ShowAudioInputSettings() { void AudioManagerLinux::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. - media::AudioDeviceName name; - name.device_name = AudioManagerBase::kDefaultDeviceName; - name.unique_id = "0"; - device_names->push_back(name); + DCHECK(device_names->empty()); + + GetAlsaAudioInputDevices(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. + // We use index 0 to make up the unique_id to identify the default device. + device_names->push_front(media::AudioDeviceName( + AudioManagerBase::kDefaultDeviceName, "0")); + } +} + +void AudioManagerLinux::GetAlsaAudioInputDevices( + media::AudioDeviceNames* device_names) { + // Constants specified by the ALSA API for device hints. + static const char kPcmInterfaceName[] = "pcm"; + int card = -1; + + // Loop through the sound cards to get ALSA device hints. + while (!wrapper_->CardNext(&card) && card >= 0) { + void** hints = NULL; + int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints); + if (!error) { + GetAlsaDevicesInfo(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: " + << wrapper_->StrError(error); + } } } -bool AudioManagerLinux::HasAnyValidAudioInputDevice(void** hints) { +void AudioManagerLinux::GetAlsaDevicesInfo( + 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"; for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { @@ -238,13 +224,100 @@ bool AudioManagerLinux::HasAnyValidAudioInputDevice(void** hints) { if (io != NULL && strcmp(kOutputDevice, io.get()) == 0) continue; - scoped_ptr_malloc<char> hint_device_name( + // Get the unique device name for the device. + scoped_ptr_malloc<char> unique_device_name( wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName)); - if (IsValidAudioInputDevice(hint_device_name.get())) - return true; + + // Find out if the device is available. + if (IsAlsaDeviceAvailable(unique_device_name.get())) { + // Get the description for the device. + scoped_ptr_malloc<char> desc(wrapper_->DeviceNameGetHint( + *hint_iter, kDescriptionHintName)); + + media::AudioDeviceName name; + name.unique_id = unique_device_name.get(); + if (desc.get()) { + // Use the more user friendly description as name. + // Replace '\n' with '-'. + char* pret = strchr(desc.get(), '\n'); + if (pret) + *pret = '-'; + name.device_name = desc.get(); + } else { + // Virtual devices don't necessarily have descriptions. + // Use their names instead. + name.device_name = unique_device_name.get(); + } + + // Store the device information. + device_names->push_back(name); + } } +} - return false; +bool AudioManagerLinux::IsAlsaDeviceAvailable(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]))) + return false; + } + + // The only way to check if the device is available is to open/close the + // device. Return false if it fails either of operations. + snd_pcm_t* device_handle = NULL; + if (wrapper_->PcmOpen(&device_handle, + device_name, + SND_PCM_STREAM_CAPTURE, + SND_PCM_NONBLOCK)) + return false; + if (wrapper_->PcmClose(device_handle)) + return false; + + return true; +} + +bool AudioManagerLinux::HasAnyAlsaAudioDevice(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; + + // Loop through the sound cards. + // Don't use snd_device_name_hint(-1,..) since there is a access violation + // inside this ALSA API with libasound.so.2.0.0. + while (!wrapper_->CardNext(&card) && (card >= 0) && !has_device) { + int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints); + if (!error) { + for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) { + // Only examine devices that are |stream| capable. 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(kNotWantedDevice, io.get()) == 0) + continue; // Wrong type, skip the device. + + // Found an input device. + has_device = true; + break; + } + + // Destroy the hints now that we're done with it. + wrapper_->DeviceNameFreeHint(hints); + hints = NULL; + } else { + DLOG(WARNING) << "HasAnyAudioDevice: unable to get device hints: " + << wrapper_->StrError(error); + } + } + + return has_device; } // static diff --git a/media/audio/linux/audio_manager_linux.h b/media/audio/linux/audio_manager_linux.h index 77ea481..ed08a1a2 100644 --- a/media/audio/linux/audio_manager_linux.h +++ b/media/audio/linux/audio_manager_linux.h @@ -42,8 +42,22 @@ class MEDIA_EXPORT AudioManagerLinux : public AudioManagerBase { virtual ~AudioManagerLinux(); private: - // Helper method to query if there is any valid input device - bool HasAnyValidAudioInputDevice(void** hint); + enum StreamType { + kStreamPlayback = 0, + kStreamCapture, + }; + + // Gets a list of available ALSA input devices. + void GetAlsaAudioInputDevices(media::AudioDeviceNames* device_names); + + // Gets the ALSA devices' names and ids. + void GetAlsaDevicesInfo(void** hint, media::AudioDeviceNames* device_names); + + // Checks if the specific ALSA device is available. + bool IsAlsaDeviceAvailable(const char* device_name); + + // Returns true if a device is present for the given stream type. + bool HasAnyAlsaAudioDevice(StreamType stream); scoped_ptr<AlsaWrapper> wrapper_; diff --git a/media/media.gyp b/media/media.gyp index a9baf28..8226238 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -33,6 +33,7 @@ 'audio/audio_io.h', 'audio/audio_input_controller.cc', 'audio/audio_input_controller.h', + 'audio/audio_device_name.cc', 'audio/audio_device_name.h', 'audio/audio_manager.cc', 'audio/audio_manager.h', |