summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-29 00:59:31 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-29 00:59:31 +0000
commit059a0f41373e2c79141ed9c783565048de67fa6a (patch)
tree523290d68070eb4d452d0f9e18709a4ec33d59dd /media
parenta9bf3a5fe62bead51846f9165dcebe3529bac134 (diff)
downloadchromium_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.cc18
-rw-r--r--media/audio/audio_device_name.h9
-rw-r--r--media/audio/linux/audio_manager_linux.cc187
-rw-r--r--media/audio/linux/audio_manager_linux.h18
-rw-r--r--media/media.gyp1
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',