summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/renderer_host/media/media_stream_manager_unittest.cc14
-rw-r--r--media/audio/alsa/alsa_input.cc (renamed from media/audio/linux/alsa_input.cc)14
-rw-r--r--media/audio/alsa/alsa_input.h (renamed from media/audio/linux/alsa_input.h)14
-rw-r--r--media/audio/alsa/alsa_output.cc (renamed from media/audio/linux/alsa_output.cc)12
-rw-r--r--media/audio/alsa/alsa_output.h (renamed from media/audio/linux/alsa_output.h)14
-rw-r--r--media/audio/alsa/alsa_output_unittest.cc (renamed from media/audio/linux/alsa_output_unittest.cc)14
-rw-r--r--media/audio/alsa/alsa_util.cc (renamed from media/audio/linux/alsa_util.cc)6
-rw-r--r--media/audio/alsa/alsa_util.h (renamed from media/audio/linux/alsa_util.h)8
-rw-r--r--media/audio/alsa/alsa_wrapper.cc (renamed from media/audio/linux/alsa_wrapper.cc)4
-rw-r--r--media/audio/alsa/alsa_wrapper.h (renamed from media/audio/linux/alsa_wrapper.h)7
-rw-r--r--media/audio/alsa/audio_manager_alsa.cc361
-rw-r--r--media/audio/alsa/audio_manager_alsa.h (renamed from media/audio/linux/audio_manager_linux.h)16
-rw-r--r--media/audio/audio_low_latency_input_output_unittest.cc12
-rw-r--r--media/audio/audio_manager_unittest.cc14
-rw-r--r--media/audio/cras/cras_input.cc2
-rw-r--r--media/audio/cras/cras_unified.cc2
-rw-r--r--media/audio/fake_audio_manager.cc68
-rw-r--r--media/audio/fake_audio_manager.h51
-rw-r--r--media/audio/linux/audio_manager_linux.cc355
-rw-r--r--media/audio/pulse/audio_manager_pulse.cc4
-rw-r--r--media/media.gyp32
-rw-r--r--tools/valgrind/tsan/suppressions.txt2
22 files changed, 595 insertions, 431 deletions
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index a67237a..03e95e0 100644
--- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -13,14 +13,16 @@
#include "content/common/media/media_stream_options.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager_base.h"
-#if defined(OS_ANDROID)
+#if defined(USE_ALSA)
+#include "media/audio/alsa/audio_manager_alsa.h"
+#elif defined(OS_ANDROID)
#include "media/audio/android/audio_manager_android.h"
-#elif defined(OS_LINUX) || defined(OS_OPENBSD)
-#include "media/audio/linux/audio_manager_linux.h"
#elif defined(OS_MACOSX)
#include "media/audio/mac/audio_manager_mac.h"
#elif defined(OS_WIN)
#include "media/audio/win/audio_manager_win.h"
+#else
+#include "media/audio/fake_audio_manager.h"
#endif
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,14 +31,16 @@ using testing::_;
namespace content {
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
-typedef media::AudioManagerLinux AudioManagerPlatform;
+#if defined(USE_ALSA)
+typedef media::AudioManagerAlsa AudioManagerPlatform;
#elif defined(OS_MACOSX)
typedef media::AudioManagerMac AudioManagerPlatform;
#elif defined(OS_WIN)
typedef media::AudioManagerWin AudioManagerPlatform;
#elif defined(OS_ANDROID)
typedef media::AudioManagerAndroid AudioManagerPlatform;
+#else
+typedef media::FakeAudioManager AudioManagerPlatform;
#endif
diff --git a/media/audio/linux/alsa_input.cc b/media/audio/alsa/alsa_input.cc
index 929cbe7..9dcbf2b 100644
--- a/media/audio/linux/alsa_input.cc
+++ b/media/audio/alsa/alsa_input.cc
@@ -1,19 +1,19 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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/linux/alsa_input.h"
+#include "media/audio/alsa/alsa_input.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
+#include "media/audio/alsa/alsa_output.h"
+#include "media/audio/alsa/alsa_util.h"
+#include "media/audio/alsa/alsa_wrapper.h"
+#include "media/audio/alsa/audio_manager_alsa.h"
#include "media/audio/audio_manager.h"
-#include "media/audio/linux/alsa_output.h"
-#include "media/audio/linux/alsa_util.h"
-#include "media/audio/linux/alsa_wrapper.h"
-#include "media/audio/linux/audio_manager_linux.h"
namespace media {
@@ -24,7 +24,7 @@ static const char kDefaultDevice2[] = "plug:default";
const char AlsaPcmInputStream::kAutoSelectDevice[] = "";
-AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerLinux* audio_manager,
+AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerBase* audio_manager,
const std::string& device_name,
const AudioParameters& params,
AlsaWrapper* wrapper)
diff --git a/media/audio/linux/alsa_input.h b/media/audio/alsa/alsa_input.h
index 888e478..6e9aad90 100644
--- a/media/audio/linux/alsa_input.h
+++ b/media/audio/alsa/alsa_input.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
-#ifndef MEDIA_AUDIO_LINUX_ALSA_INPUT_H_
-#define MEDIA_AUDIO_LINUX_ALSA_INPUT_H_
+#ifndef MEDIA_AUDIO_ALSA_ALSA_INPUT_H_
+#define MEDIA_AUDIO_ALSA_ALSA_INPUT_H_
#include <alsa/asoundlib.h>
@@ -20,7 +20,7 @@
namespace media {
class AlsaWrapper;
-class AudioManagerLinux;
+class AudioManagerBase;
// Provides an input stream for audio capture based on the ALSA PCM interface.
// This object is not thread safe and all methods should be invoked in the
@@ -34,7 +34,7 @@ class AlsaPcmInputStream : public AgcAudioStream<AudioInputStream> {
// Create a PCM Output stream for the ALSA device identified by
// |device_name|. If unsure of what to use for |device_name|, use
// |kAutoSelectDevice|.
- AlsaPcmInputStream(AudioManagerLinux* audio_manager,
+ AlsaPcmInputStream(AudioManagerBase* audio_manager,
const std::string& device_name,
const AudioParameters& params,
AlsaWrapper* wrapper);
@@ -69,7 +69,7 @@ class AlsaPcmInputStream : public AgcAudioStream<AudioInputStream> {
// want circular references. Additionally, stream objects live on the audio
// thread, which is owned by the audio manager and we don't want to addref
// the manager from that thread.
- AudioManagerLinux* audio_manager_;
+ AudioManagerBase* audio_manager_;
std::string device_name_;
AudioParameters params_;
int bytes_per_buffer_;
@@ -89,4 +89,4 @@ class AlsaPcmInputStream : public AgcAudioStream<AudioInputStream> {
} // namespace media
-#endif // MEDIA_AUDIO_LINUX_ALSA_INPUT_H_
+#endif // MEDIA_AUDIO_ALSA_ALSA_INPUT_H_
diff --git a/media/audio/linux/alsa_output.cc b/media/audio/alsa/alsa_output.cc
index fa83835..eccf8ee 100644
--- a/media/audio/linux/alsa_output.cc
+++ b/media/audio/alsa/alsa_output.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
//
@@ -32,7 +32,7 @@
// view, it will seem that the device has just clogged and stopped requesting
// data.
-#include "media/audio/linux/alsa_output.h"
+#include "media/audio/alsa/alsa_output.h"
#include <algorithm>
@@ -42,9 +42,9 @@
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/time/time.h"
-#include "media/audio/linux/alsa_util.h"
-#include "media/audio/linux/alsa_wrapper.h"
-#include "media/audio/linux/audio_manager_linux.h"
+#include "media/audio/alsa/alsa_util.h"
+#include "media/audio/alsa/alsa_wrapper.h"
+#include "media/audio/alsa/audio_manager_alsa.h"
#include "media/base/channel_mixer.h"
#include "media/base/data_buffer.h"
#include "media/base/seekable_buffer.h"
@@ -134,7 +134,7 @@ const uint32 AlsaPcmOutputStream::kMinLatencyMicros = 40 * 1000;
AlsaPcmOutputStream::AlsaPcmOutputStream(const std::string& device_name,
const AudioParameters& params,
AlsaWrapper* wrapper,
- AudioManagerLinux* manager)
+ AudioManagerBase* manager)
: requested_device_name_(device_name),
pcm_format_(alsa_util::BitsToFormat(params.bits_per_sample())),
channels_(params.channels()),
diff --git a/media/audio/linux/alsa_output.h b/media/audio/alsa/alsa_output.h
index 841615d..65a23f7 100644
--- a/media/audio/linux/alsa_output.h
+++ b/media/audio/alsa/alsa_output.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
//
@@ -18,8 +18,8 @@
// the audio thread. When modifying the code in this class, please read the
// threading assumptions at the top of the implementation.
-#ifndef MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
-#define MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
+#ifndef MEDIA_AUDIO_ALSA_ALSA_OUTPUT_H_
+#define MEDIA_AUDIO_ALSA_ALSA_OUTPUT_H_
#include <alsa/asoundlib.h>
@@ -40,7 +40,7 @@ class MessageLoop;
namespace media {
class AlsaWrapper;
-class AudioManagerLinux;
+class AudioManagerBase;
class ChannelMixer;
class SeekableBuffer;
@@ -70,7 +70,7 @@ class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream {
AlsaPcmOutputStream(const std::string& device_name,
const AudioParameters& params,
AlsaWrapper* wrapper,
- AudioManagerLinux* manager);
+ AudioManagerBase* manager);
virtual ~AlsaPcmOutputStream();
@@ -187,7 +187,7 @@ class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream {
AlsaWrapper* wrapper_;
// Audio manager that created us. Used to report that we've been closed.
- AudioManagerLinux* manager_;
+ AudioManagerBase* manager_;
// Message loop to use for polling. The object is owned by the AudioManager.
// We hold a reference to the audio thread message loop since
@@ -225,4 +225,4 @@ MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
}; // namespace media
-#endif // MEDIA_AUDIO_LINUX_ALSA_OUTPUT_H_
+#endif // MEDIA_AUDIO_ALSA_ALSA_OUTPUT_H_
diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/alsa/alsa_output_unittest.cc
index 82fbab9..9d83b56 100644
--- a/media/audio/linux/alsa_output_unittest.cc
+++ b/media/audio/alsa/alsa_output_unittest.cc
@@ -1,12 +1,12 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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 "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
-#include "media/audio/linux/alsa_output.h"
-#include "media/audio/linux/alsa_wrapper.h"
-#include "media/audio/linux/audio_manager_linux.h"
+#include "media/audio/alsa/alsa_output.h"
+#include "media/audio/alsa/alsa_wrapper.h"
+#include "media/audio/alsa/audio_manager_alsa.h"
#include "media/base/data_buffer.h"
#include "media/base/seekable_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -76,7 +76,7 @@ class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
MOCK_METHOD1(OnError, void(AudioOutputStream* stream));
};
-class MockAudioManagerLinux : public AudioManagerLinux {
+class MockAudioManagerAlsa : public AudioManagerAlsa {
public:
MOCK_METHOD0(Init, void());
MOCK_METHOD0(HasAudioOutputDevices, bool());
@@ -109,7 +109,7 @@ class MockAudioManagerLinux : public AudioManagerLinux {
class AlsaPcmOutputStreamTest : public testing::Test {
protected:
AlsaPcmOutputStreamTest() {
- mock_manager_.reset(new StrictMock<MockAudioManagerLinux>());
+ mock_manager_.reset(new StrictMock<MockAudioManagerAlsa>());
}
virtual ~AlsaPcmOutputStreamTest() {
@@ -171,7 +171,7 @@ class AlsaPcmOutputStreamTest : public testing::Test {
static void* kFakeHints[];
StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
- scoped_ptr<StrictMock<MockAudioManagerLinux> > mock_manager_;
+ scoped_ptr<StrictMock<MockAudioManagerAlsa> > mock_manager_;
base::MessageLoop message_loop_;
scoped_refptr<media::DataBuffer> packet_;
diff --git a/media/audio/linux/alsa_util.cc b/media/audio/alsa/alsa_util.cc
index 176ef69..f26cbd3 100644
--- a/media/audio/linux/alsa_util.cc
+++ b/media/audio/alsa/alsa_util.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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/linux/alsa_util.h"
+#include "media/audio/alsa/alsa_util.h"
#include <string>
#include "base/logging.h"
-#include "media/audio/linux/alsa_wrapper.h"
+#include "media/audio/alsa/alsa_wrapper.h"
namespace alsa_util {
diff --git a/media/audio/linux/alsa_util.h b/media/audio/alsa/alsa_util.h
index 53cf80a..a23ab31 100644
--- a/media/audio/linux/alsa_util.h
+++ b/media/audio/alsa/alsa_util.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
-#ifndef MEDIA_AUDIO_LINUX_ALSA_UTIL_H_
-#define MEDIA_AUDIO_LINUX_ALSA_UTIL_H_
+#ifndef MEDIA_AUDIO_ALSA_ALSA_UTIL_H_
+#define MEDIA_AUDIO_ALSA_ALSA_UTIL_H_
#include <alsa/asoundlib.h>
#include <string>
@@ -44,4 +44,4 @@ snd_mixer_elem_t* LoadCaptureMixerElement(media::AlsaWrapper* wrapper,
} // namespace alsa_util
-#endif // MEDIA_AUDIO_LINUX_ALSA_UTIL_H_
+#endif // MEDIA_AUDIO_ALSA_ALSA_UTIL_H_
diff --git a/media/audio/linux/alsa_wrapper.cc b/media/audio/alsa/alsa_wrapper.cc
index c1ce359..969f3c4 100644
--- a/media/audio/linux/alsa_wrapper.cc
+++ b/media/audio/alsa/alsa_wrapper.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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/linux/alsa_wrapper.h"
+#include "media/audio/alsa/alsa_wrapper.h"
#include <alsa/asoundlib.h>
diff --git a/media/audio/linux/alsa_wrapper.h b/media/audio/alsa/alsa_wrapper.h
index 30d9463..4b3c295 100644
--- a/media/audio/linux/alsa_wrapper.h
+++ b/media/audio/alsa/alsa_wrapper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
//
@@ -6,6 +6,9 @@
// we want to use. It's purpose is to allow injection of a mock so that the
// higher level code is testable.
+#ifndef MEDIA_AUDIO_ALSA_ALSA_WRAPPER_H_
+#define MEDIA_AUDIO_ALSA_ALSA_WRAPPER_H_
+
#include <alsa/asoundlib.h>
#include "base/basictypes.h"
@@ -79,3 +82,5 @@ class MEDIA_EXPORT AlsaWrapper {
};
} // namespace media
+
+#endif // MEDIA_AUDIO_ALSA_ALSA_WRAPPER_H_
diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc
new file mode 100644
index 0000000..6c9696a
--- /dev/null
+++ b/media/audio/alsa/audio_manager_alsa.cc
@@ -0,0 +1,361 @@
+// Copyright 2013 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/alsa/audio_manager_alsa.h"
+
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/nix/xdg_util.h"
+#include "base/process/launch.h"
+#include "base/stl_util.h"
+#include "media/audio/audio_output_dispatcher.h"
+#include "media/audio/audio_parameters.h"
+#if defined(USE_CRAS)
+#include "media/audio/cras/audio_manager_cras.h"
+#endif
+#include "media/audio/alsa/alsa_input.h"
+#include "media/audio/alsa/alsa_output.h"
+#include "media/audio/alsa/alsa_wrapper.h"
+#if defined(USE_PULSEAUDIO)
+#include "media/audio/pulse/audio_manager_pulse.h"
+#endif
+#include "media/base/channel_layout.h"
+#include "media/base/limits.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+// Maximum number of output streams that can be open simultaneously.
+static const int kMaxOutputStreams = 50;
+
+// Default sample rate for input and output streams.
+static const int kDefaultSampleRate = 48000;
+
+// Since "default", "pulse" and "dmix" devices are virtual devices mapped to
+// real devices, we remove them from the list to avoiding duplicate counting.
+// In addition, note that we support no more than 2 channels for recording,
+// hence surround devices are not stored in the list.
+static const char* kInvalidAudioInputDevices[] = {
+ "default",
+ "dmix",
+ "null",
+ "pulse",
+ "surround",
+};
+
+// static
+void AudioManagerAlsa::ShowLinuxAudioInputSettings() {
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ CommandLine command_line(CommandLine::NO_PROGRAM);
+ switch (base::nix::GetDesktopEnvironment(env.get())) {
+ case base::nix::DESKTOP_ENVIRONMENT_GNOME:
+ command_line.SetProgram(base::FilePath("gnome-volume-control"));
+ break;
+ case base::nix::DESKTOP_ENVIRONMENT_KDE3:
+ case base::nix::DESKTOP_ENVIRONMENT_KDE4:
+ command_line.SetProgram(base::FilePath("kmix"));
+ break;
+ case base::nix::DESKTOP_ENVIRONMENT_UNITY:
+ command_line.SetProgram(base::FilePath("gnome-control-center"));
+ command_line.AppendArg("sound");
+ command_line.AppendArg("input");
+ break;
+ default:
+ LOG(ERROR) << "Failed to show audio input settings: we don't know "
+ << "what command to use for your desktop environment.";
+ return;
+ }
+ base::LaunchProcess(command_line, base::LaunchOptions(), NULL);
+}
+
+// Implementation of AudioManager.
+bool AudioManagerAlsa::HasAudioOutputDevices() {
+ return HasAnyAlsaAudioDevice(kStreamPlayback);
+}
+
+bool AudioManagerAlsa::HasAudioInputDevices() {
+ return HasAnyAlsaAudioDevice(kStreamCapture);
+}
+
+AudioManagerAlsa::AudioManagerAlsa()
+ : wrapper_(new AlsaWrapper()) {
+ SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+}
+
+AudioManagerAlsa::~AudioManagerAlsa() {
+ Shutdown();
+}
+
+void AudioManagerAlsa::ShowAudioInputSettings() {
+ ShowLinuxAudioInputSettings();
+}
+
+void AudioManagerAlsa::GetAudioInputDeviceNames(
+ AudioDeviceNames* device_names) {
+ DCHECK(device_names->empty());
+ GetAlsaAudioDevices(kStreamCapture, device_names);
+}
+
+void AudioManagerAlsa::GetAudioOutputDeviceNames(
+ AudioDeviceNames* device_names) {
+ DCHECK(device_names->empty());
+ GetAlsaAudioDevices(kStreamPlayback, device_names);
+}
+
+AudioParameters AudioManagerAlsa::GetInputStreamParameters(
+ const std::string& device_id) {
+ static const int kDefaultInputBufferSize = 1024;
+
+ return AudioParameters(
+ AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
+ kDefaultSampleRate, 16, kDefaultInputBufferSize);
+}
+
+void AudioManagerAlsa::GetAlsaAudioDevices(
+ StreamType type,
+ 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(type, hints, device_names);
+
+ // Destroy the hints now that we're done with it.
+ wrapper_->DeviceNameFreeHint(hints);
+ } else {
+ DLOG(WARNING) << "GetAlsaAudioDevices: unable to get device hints: "
+ << wrapper_->StrError(error);
+ }
+ }
+}
+
+void AudioManagerAlsa::GetAlsaDevicesInfo(
+ AudioManagerAlsa::StreamType type,
+ void** hints,
+ media::AudioDeviceNames* device_names) {
+ static const char kIoHintName[] = "IOID";
+ static const char kNameHintName[] = "NAME";
+ static const char kDescriptionHintName[] = "DESC";
+
+ const char* unwanted_device_type = UnwantedDeviceTypeWhenEnumerating(type);
+
+ for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) {
+ // 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(unwanted_device_type, io.get()) == 0)
+ continue;
+
+ // 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,
+ AudioManagerBase::kDefaultDeviceId));
+ }
+
+ // Get the unique device name for the device.
+ scoped_ptr_malloc<char> unique_device_name(
+ wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName));
+
+ // Find out if the device is available.
+ if (IsAlsaDeviceAvailable(type, 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) {
+ // 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);
+ }
+ }
+}
+
+// static
+bool AudioManagerAlsa::IsAlsaDeviceAvailable(
+ AudioManagerAlsa::StreamType type,
+ const char* device_name) {
+ if (!device_name)
+ 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;
+ }
+}
+
+// static
+const char* AudioManagerAlsa::UnwantedDeviceTypeWhenEnumerating(
+ AudioManagerAlsa::StreamType wanted_type) {
+ return wanted_type == kStreamPlayback ? "Input" : "Output";
+}
+
+bool AudioManagerAlsa::HasAnyAlsaAudioDevice(
+ AudioManagerAlsa::StreamType stream) {
+ static const char kPcmInterfaceName[] = "pcm";
+ static const char kIoHintName[] = "IOID";
+ 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));
+ 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.
+ 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;
+}
+
+AudioOutputStream* AudioManagerAlsa::MakeLinearOutputStream(
+ const AudioParameters& params) {
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+ return MakeOutputStream(params);
+}
+
+AudioOutputStream* AudioManagerAlsa::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);
+}
+
+AudioInputStream* AudioManagerAlsa::MakeLinearInputStream(
+ const AudioParameters& params, const std::string& device_id) {
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+ return MakeInputStream(params, device_id);
+}
+
+AudioInputStream* AudioManagerAlsa::MakeLowLatencyInputStream(
+ const AudioParameters& params, const std::string& device_id) {
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ return MakeInputStream(params, device_id);
+}
+
+AudioParameters AudioManagerAlsa::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;
+ int buffer_size = kDefaultOutputBufferSize;
+ int bits_per_sample = 16;
+ int input_channels = 0;
+ if (input_params.IsValid()) {
+ // Some clients, such as WebRTC, have a more limited use case and work
+ // acceptably with a smaller buffer size. The check below allows clients
+ // which want to try a smaller buffer size on Linux to do so.
+ // TODO(dalecurtis): This should include bits per channel and channel layout
+ // eventually.
+ sample_rate = input_params.sample_rate();
+ bits_per_sample = input_params.bits_per_sample();
+ channel_layout = input_params.channel_layout();
+ input_channels = input_params.input_channels();
+ buffer_size = std::min(input_params.frames_per_buffer(), buffer_size);
+ }
+
+ int user_buffer_size = GetUserBufferSize();
+ if (user_buffer_size)
+ buffer_size = user_buffer_size;
+
+ return AudioParameters(
+ AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
+ sample_rate, bits_per_sample, buffer_size);
+}
+
+AudioOutputStream* AudioManagerAlsa::MakeOutputStream(
+ const AudioParameters& params) {
+ std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAlsaOutputDevice)) {
+ device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kAlsaOutputDevice);
+ }
+ return new AlsaPcmOutputStream(device_name, params, wrapper_.get(), this);
+}
+
+AudioInputStream* AudioManagerAlsa::MakeInputStream(
+ const AudioParameters& params, const std::string& device_id) {
+ std::string device_name = (device_id == AudioManagerBase::kDefaultDeviceId) ?
+ AlsaPcmInputStream::kAutoSelectDevice : device_id;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) {
+ device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kAlsaInputDevice);
+ }
+
+ return new AlsaPcmInputStream(this, device_name, params, wrapper_.get());
+}
+
+} // namespace media
diff --git a/media/audio/linux/audio_manager_linux.h b/media/audio/alsa/audio_manager_alsa.h
index ab284df..c8ed7c1 100644
--- a/media/audio/linux/audio_manager_linux.h
+++ b/media/audio/alsa/audio_manager_alsa.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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.
-#ifndef MEDIA_AUDIO_LINUX_AUDIO_MANAGER_LINUX_H_
-#define MEDIA_AUDIO_LINUX_AUDIO_MANAGER_LINUX_H_
+#ifndef MEDIA_AUDIO_ALSA_AUDIO_MANAGER_ALSA_H_
+#define MEDIA_AUDIO_ALSA_AUDIO_MANAGER_ALSA_H_
#include <string>
#include "base/compiler_specific.h"
@@ -15,9 +15,9 @@ namespace media {
class AlsaWrapper;
-class MEDIA_EXPORT AudioManagerLinux : public AudioManagerBase {
+class MEDIA_EXPORT AudioManagerAlsa : public AudioManagerBase {
public:
- AudioManagerLinux();
+ AudioManagerAlsa();
static void ShowLinuxAudioInputSettings();
@@ -45,7 +45,7 @@ class MEDIA_EXPORT AudioManagerLinux : public AudioManagerBase {
const AudioParameters& params, const std::string& device_id) OVERRIDE;
protected:
- virtual ~AudioManagerLinux();
+ virtual ~AudioManagerAlsa();
virtual AudioParameters GetPreferredOutputStreamParameters(
const std::string& output_device_id,
@@ -86,9 +86,9 @@ class MEDIA_EXPORT AudioManagerLinux : public AudioManagerBase {
scoped_ptr<AlsaWrapper> wrapper_;
- DISALLOW_COPY_AND_ASSIGN(AudioManagerLinux);
+ DISALLOW_COPY_AND_ASSIGN(AudioManagerAlsa);
};
} // namespace media
-#endif // MEDIA_AUDIO_LINUX_AUDIO_MANAGER_LINUX_H_
+#endif // MEDIA_AUDIO_ALSA_AUDIO_MANAGER_ALSA_H_
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc
index 994353e..a187e3b 100644
--- a/media/audio/audio_low_latency_input_output_unittest.cc
+++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -18,8 +18,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
-#include "media/audio/linux/audio_manager_linux.h"
+#if defined(USE_ALSA)
+#include "media/audio/alsa/audio_manager_alsa.h"
#elif defined(OS_MACOSX)
#include "media/audio/mac/audio_manager_mac.h"
#elif defined(OS_WIN)
@@ -27,18 +27,22 @@
#include "media/audio/win/core_audio_util_win.h"
#elif defined(OS_ANDROID)
#include "media/audio/android/audio_manager_android.h"
+#else
+#include "media/audio/fake_audio_manager.h"
#endif
namespace media {
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
-typedef AudioManagerLinux AudioManagerAnyPlatform;
+#if defined(USE_ALSA)
+typedef AudioManagerAlsa AudioManagerAnyPlatform;
#elif defined(OS_MACOSX)
typedef AudioManagerMac AudioManagerAnyPlatform;
#elif defined(OS_WIN)
typedef AudioManagerWin AudioManagerAnyPlatform;
#elif defined(OS_ANDROID)
typedef AudioManagerAndroid AudioManagerAnyPlatform;
+#else
+typedef FakeAudioManager AudioManagerAnyPlatform;
#endif
// Limits the number of delay measurements we can store in an array and
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 4747c2e..e96cef1 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -9,9 +9,9 @@
#include "media/audio/audio_manager_base.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_LINUX)
-#include "media/audio/linux/audio_manager_linux.h"
-#endif // defined(OS_LINUX)
+#if defined(USE_ALSA)
+#include "media/audio/alsa/audio_manager_alsa.h"
+#endif // defined(USE_ALSA)
#if defined(OS_WIN)
#include "base/win/scoped_com_initializer.h"
@@ -288,8 +288,8 @@ TEST_F(AudioManagerTest, EnumerateInputDevicesAlsa) {
if (!CanRunInputTest())
return;
- VLOG(2) << "Testing AudioManagerLinux.";
- audio_manager_.reset(new AudioManagerLinux());
+ VLOG(2) << "Testing AudioManagerAlsa.";
+ audio_manager_.reset(new AudioManagerAlsa());
AudioDeviceNames device_names;
audio_manager_->GetAudioInputDeviceNames(&device_names);
CheckDeviceNames(device_names);
@@ -299,8 +299,8 @@ TEST_F(AudioManagerTest, EnumerateOutputDevicesAlsa) {
if (!CanRunOutputTest())
return;
- VLOG(2) << "Testing AudioManagerLinux.";
- audio_manager_.reset(new AudioManagerLinux());
+ VLOG(2) << "Testing AudioManagerAlsa.";
+ audio_manager_.reset(new AudioManagerAlsa());
AudioDeviceNames device_names;
audio_manager_->GetAudioOutputDeviceNames(&device_names);
CheckDeviceNames(device_names);
diff --git a/media/audio/cras/cras_input.cc b/media/audio/cras/cras_input.cc
index fd574dc..c41f364 100644
--- a/media/audio/cras/cras_input.cc
+++ b/media/audio/cras/cras_input.cc
@@ -10,9 +10,9 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/time/time.h"
+#include "media/audio/alsa/alsa_util.h"
#include "media/audio/audio_manager.h"
#include "media/audio/cras/audio_manager_cras.h"
-#include "media/audio/linux/alsa_util.h"
namespace media {
diff --git a/media/audio/cras/cras_unified.cc b/media/audio/cras/cras_unified.cc
index 906f209..c85cf59 100644
--- a/media/audio/cras/cras_unified.cc
+++ b/media/audio/cras/cras_unified.cc
@@ -8,8 +8,8 @@
#include "base/command_line.h"
#include "base/logging.h"
+#include "media/audio/alsa/alsa_util.h"
#include "media/audio/cras/audio_manager_cras.h"
-#include "media/audio/linux/alsa_util.h"
namespace media {
diff --git a/media/audio/fake_audio_manager.cc b/media/audio/fake_audio_manager.cc
new file mode 100644
index 0000000..c346289
--- /dev/null
+++ b/media/audio/fake_audio_manager.cc
@@ -0,0 +1,68 @@
+// Copyright 2013 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/fake_audio_manager.h"
+
+namespace media {
+
+FakeAudioManager::FakeAudioManager() {}
+
+FakeAudioManager::~FakeAudioManager() {
+ Shutdown();
+}
+
+// Implementation of AudioManager.
+bool FakeAudioManager::HasAudioOutputDevices() { return false; }
+
+bool FakeAudioManager::HasAudioInputDevices() { return false; }
+
+// Implementation of AudioManagerBase.
+AudioOutputStream* FakeAudioManager::MakeLinearOutputStream(
+ const AudioParameters& params) {
+ return FakeAudioOutputStream::MakeFakeStream(this, params);
+}
+
+AudioOutputStream* FakeAudioManager::MakeLowLatencyOutputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const std::string& input_device_id) {
+ return FakeAudioOutputStream::MakeFakeStream(this, params);
+}
+
+AudioInputStream* FakeAudioManager::MakeLinearInputStream(
+ const AudioParameters& params,
+ const std::string& device_id) {
+ return FakeAudioInputStream::MakeFakeStream(this, params);
+}
+
+AudioInputStream* FakeAudioManager::MakeLowLatencyInputStream(
+ const AudioParameters& params,
+ const std::string& device_id) {
+ return FakeAudioInputStream::MakeFakeStream(this, params);
+}
+
+AudioParameters FakeAudioManager::GetPreferredOutputStreamParameters(
+ const std::string& output_device_id,
+ const AudioParameters& input_params) {
+ static const int kDefaultOutputBufferSize = 2048;
+ static const int kDefaultSampleRate = 48000;
+ ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+ int sample_rate = kDefaultSampleRate;
+ int buffer_size = kDefaultOutputBufferSize;
+ int bits_per_sample = 16;
+ int input_channels = 0;
+ if (input_params.IsValid()) {
+ sample_rate = input_params.sample_rate();
+ bits_per_sample = input_params.bits_per_sample();
+ channel_layout = input_params.channel_layout();
+ input_channels = input_params.input_channels();
+ buffer_size = std::min(input_params.frames_per_buffer(), buffer_size);
+ }
+
+ return AudioParameters(
+ AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
+ sample_rate, bits_per_sample, buffer_size);
+}
+
+} // namespace media
diff --git a/media/audio/fake_audio_manager.h b/media/audio/fake_audio_manager.h
new file mode 100644
index 0000000..d230739
--- /dev/null
+++ b/media/audio/fake_audio_manager.h
@@ -0,0 +1,51 @@
+// Copyright 2013 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.
+
+#ifndef MEDIA_AUDIO_FAKE_AUDIO_MANAGER_H_
+#define MEDIA_AUDIO_FAKE_AUDIO_MANAGER_H_
+
+#include <string>
+#include "base/compiler_specific.h"
+#include "media/audio/audio_manager_base.h"
+#include "media/audio/fake_audio_input_stream.h"
+#include "media/audio/fake_audio_output_stream.h"
+
+namespace media {
+
+class MEDIA_EXPORT FakeAudioManager : public AudioManagerBase {
+ public:
+ FakeAudioManager();
+
+ // Implementation of AudioManager.
+ virtual bool HasAudioOutputDevices() OVERRIDE;
+ virtual bool HasAudioInputDevices() OVERRIDE;
+
+ // Implementation of AudioManagerBase.
+ virtual AudioOutputStream* MakeLinearOutputStream(
+ const AudioParameters& params) OVERRIDE;
+ virtual AudioOutputStream* MakeLowLatencyOutputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const std::string& input_device_id) OVERRIDE;
+ virtual AudioInputStream* MakeLinearInputStream(const AudioParameters& params,
+ const std::string& device_id)
+ OVERRIDE;
+ virtual AudioInputStream* MakeLowLatencyInputStream(
+ const AudioParameters& params,
+ const std::string& device_id) OVERRIDE;
+
+ protected:
+ virtual ~FakeAudioManager();
+
+ virtual AudioParameters GetPreferredOutputStreamParameters(
+ const std::string& output_device_id,
+ const AudioParameters& input_params) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeAudioManager);
+};
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_FAKE_AUDIO_MANAGER_H_
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index 0d0f104..350cd64 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -2,51 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "media/audio/linux/audio_manager_linux.h"
-
#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "base/nix/xdg_util.h"
-#include "base/process/launch.h"
-#include "base/stl_util.h"
-#include "media/audio/audio_output_dispatcher.h"
-#include "media/audio/audio_parameters.h"
+#if defined(USE_ALSA)
+#include "media/audio/alsa/audio_manager_alsa.h"
+#else
+#include "media/audio/fake_audio_manager.h"
+#endif
#if defined(USE_CRAS)
#include "media/audio/cras/audio_manager_cras.h"
#endif
-#include "media/audio/linux/alsa_input.h"
-#include "media/audio/linux/alsa_output.h"
-#include "media/audio/linux/alsa_wrapper.h"
#if defined(USE_PULSEAUDIO)
#include "media/audio/pulse/audio_manager_pulse.h"
#endif
-#include "media/base/channel_layout.h"
-#include "media/base/limits.h"
#include "media/base/media_switches.h"
namespace media {
-// Maximum number of output streams that can be open simultaneously.
-static const int kMaxOutputStreams = 50;
-
-// Default sample rate for input and output streams.
-static const int kDefaultSampleRate = 48000;
-
-// Since "default", "pulse" and "dmix" devices are virtual devices mapped to
-// real devices, we remove them from the list to avoiding duplicate counting.
-// In addition, note that we support no more than 2 channels for recording,
-// hence surround devices are not stored in the list.
-static const char* kInvalidAudioInputDevices[] = {
- "default",
- "dmix",
- "null",
- "pulse",
- "surround",
-};
-
enum LinuxAudioIO {
kPulse,
kAlsa,
@@ -54,317 +26,6 @@ enum LinuxAudioIO {
kAudioIOMax // Must always be last!
};
-// static
-void AudioManagerLinux::ShowLinuxAudioInputSettings() {
- scoped_ptr<base::Environment> env(base::Environment::Create());
- CommandLine command_line(CommandLine::NO_PROGRAM);
- switch (base::nix::GetDesktopEnvironment(env.get())) {
- case base::nix::DESKTOP_ENVIRONMENT_GNOME:
- command_line.SetProgram(base::FilePath("gnome-volume-control"));
- break;
- case base::nix::DESKTOP_ENVIRONMENT_KDE3:
- case base::nix::DESKTOP_ENVIRONMENT_KDE4:
- command_line.SetProgram(base::FilePath("kmix"));
- break;
- case base::nix::DESKTOP_ENVIRONMENT_UNITY:
- command_line.SetProgram(base::FilePath("gnome-control-center"));
- command_line.AppendArg("sound");
- command_line.AppendArg("input");
- break;
- default:
- LOG(ERROR) << "Failed to show audio input settings: we don't know "
- << "what command to use for your desktop environment.";
- return;
- }
- base::LaunchProcess(command_line, base::LaunchOptions(), NULL);
-}
-
-// Implementation of AudioManager.
-bool AudioManagerLinux::HasAudioOutputDevices() {
- return HasAnyAlsaAudioDevice(kStreamPlayback);
-}
-
-bool AudioManagerLinux::HasAudioInputDevices() {
- return HasAnyAlsaAudioDevice(kStreamCapture);
-}
-
-AudioManagerLinux::AudioManagerLinux()
- : wrapper_(new AlsaWrapper()) {
- SetMaxOutputStreamsAllowed(kMaxOutputStreams);
-}
-
-AudioManagerLinux::~AudioManagerLinux() {
- Shutdown();
-}
-
-void AudioManagerLinux::ShowAudioInputSettings() {
- ShowLinuxAudioInputSettings();
-}
-
-void AudioManagerLinux::GetAudioInputDeviceNames(
- AudioDeviceNames* device_names) {
- DCHECK(device_names->empty());
- GetAlsaAudioDevices(kStreamCapture, device_names);
-}
-
-void AudioManagerLinux::GetAudioOutputDeviceNames(
- AudioDeviceNames* device_names) {
- DCHECK(device_names->empty());
- GetAlsaAudioDevices(kStreamPlayback, device_names);
-}
-
-AudioParameters AudioManagerLinux::GetInputStreamParameters(
- const std::string& device_id) {
- static const int kDefaultInputBufferSize = 1024;
-
- return AudioParameters(
- AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
- kDefaultSampleRate, 16, kDefaultInputBufferSize);
-}
-
-void AudioManagerLinux::GetAlsaAudioDevices(
- StreamType type,
- 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(type, hints, device_names);
-
- // Destroy the hints now that we're done with it.
- wrapper_->DeviceNameFreeHint(hints);
- } else {
- DLOG(WARNING) << "GetAlsaAudioDevices: unable to get device hints: "
- << wrapper_->StrError(error);
- }
- }
-}
-
-void AudioManagerLinux::GetAlsaDevicesInfo(
- AudioManagerLinux::StreamType type,
- void** hints,
- media::AudioDeviceNames* device_names) {
- static const char kIoHintName[] = "IOID";
- static const char kNameHintName[] = "NAME";
- static const char kDescriptionHintName[] = "DESC";
-
- const char* unwanted_device_type = UnwantedDeviceTypeWhenEnumerating(type);
-
- for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) {
- // 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(unwanted_device_type, io.get()) == 0)
- continue;
-
- // 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,
- AudioManagerBase::kDefaultDeviceId));
- }
-
- // Get the unique device name for the device.
- scoped_ptr_malloc<char> unique_device_name(
- wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName));
-
- // Find out if the device is available.
- if (IsAlsaDeviceAvailable(type, 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) {
- // 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);
- }
- }
-}
-
-// static
-bool AudioManagerLinux::IsAlsaDeviceAvailable(
- AudioManagerLinux::StreamType type,
- const char* device_name) {
- if (!device_name)
- 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;
- }
-}
-
-// static
-const char* AudioManagerLinux::UnwantedDeviceTypeWhenEnumerating(
- AudioManagerLinux::StreamType wanted_type) {
- return wanted_type == kStreamPlayback ? "Input" : "Output";
-}
-
-bool AudioManagerLinux::HasAnyAlsaAudioDevice(
- AudioManagerLinux::StreamType stream) {
- static const char kPcmInterfaceName[] = "pcm";
- static const char kIoHintName[] = "IOID";
- 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));
- 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.
- 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;
-}
-
-AudioOutputStream* AudioManagerLinux::MakeLinearOutputStream(
- const AudioParameters& params) {
- DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
- return MakeOutputStream(params);
-}
-
-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);
-}
-
-AudioInputStream* AudioManagerLinux::MakeLinearInputStream(
- const AudioParameters& params, const std::string& device_id) {
- DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
- return MakeInputStream(params, device_id);
-}
-
-AudioInputStream* AudioManagerLinux::MakeLowLatencyInputStream(
- const AudioParameters& params, const std::string& device_id) {
- DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
- return MakeInputStream(params, device_id);
-}
-
-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;
- int buffer_size = kDefaultOutputBufferSize;
- int bits_per_sample = 16;
- int input_channels = 0;
- if (input_params.IsValid()) {
- // Some clients, such as WebRTC, have a more limited use case and work
- // acceptably with a smaller buffer size. The check below allows clients
- // which want to try a smaller buffer size on Linux to do so.
- // TODO(dalecurtis): This should include bits per channel and channel layout
- // eventually.
- sample_rate = input_params.sample_rate();
- bits_per_sample = input_params.bits_per_sample();
- channel_layout = input_params.channel_layout();
- input_channels = input_params.input_channels();
- buffer_size = std::min(input_params.frames_per_buffer(), buffer_size);
- }
-
- int user_buffer_size = GetUserBufferSize();
- if (user_buffer_size)
- buffer_size = user_buffer_size;
-
- return AudioParameters(
- AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
- sample_rate, bits_per_sample, buffer_size);
-}
-
-AudioOutputStream* AudioManagerLinux::MakeOutputStream(
- const AudioParameters& params) {
- std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice;
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAlsaOutputDevice)) {
- device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kAlsaOutputDevice);
- }
- return new AlsaPcmOutputStream(device_name, params, wrapper_.get(), this);
-}
-
-AudioInputStream* AudioManagerLinux::MakeInputStream(
- const AudioParameters& params, const std::string& device_id) {
- std::string device_name = (device_id == AudioManagerBase::kDefaultDeviceId) ?
- AlsaPcmInputStream::kAutoSelectDevice : device_id;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) {
- device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kAlsaInputDevice);
- }
-
- return new AlsaPcmInputStream(this, device_name, params, wrapper_.get());
-}
-
AudioManager* CreateAudioManager() {
#if defined(USE_CRAS)
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
@@ -381,8 +42,12 @@ AudioManager* CreateAudioManager() {
}
#endif
+#if defined(USE_ALSA)
UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kAlsa, kAudioIOMax);
- return new AudioManagerLinux();
+ return new AudioManagerAlsa();
+#else
+ return new FakeAudioManager();
+#endif
}
} // namespace media
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index 4aac9c5..c5b78d7 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -10,8 +10,8 @@
#include "base/logging.h"
#include "base/nix/xdg_util.h"
#include "base/stl_util.h"
+#include "media/audio/alsa/audio_manager_alsa.h"
#include "media/audio/audio_parameters.h"
-#include "media/audio/linux/audio_manager_linux.h"
#include "media/audio/pulse/pulse_input.h"
#include "media/audio/pulse/pulse_output.h"
#include "media/audio/pulse/pulse_unified.h"
@@ -77,7 +77,7 @@ bool AudioManagerPulse::HasAudioInputDevices() {
}
void AudioManagerPulse::ShowAudioInputSettings() {
- AudioManagerLinux::ShowLinuxAudioInputSettings();
+ AudioManagerAlsa::ShowLinuxAudioInputSettings();
}
void AudioManagerPulse::GetAudioDeviceNames(
diff --git a/media/media.gyp b/media/media.gyp
index d1e638a..8c3a2af 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -22,7 +22,7 @@
'media_use_libvpx%': 1,
}],
# ALSA usage.
- ['OS=="linux" or OS=="freebsd" or OS=="solaris"', {
+ ['(OS=="linux" or OS=="freebsd" or OS=="solaris") and embedded!=1', {
'use_alsa%': 1,
}, {
'use_alsa%': 0,
@@ -62,6 +62,16 @@
],
'sources': [
'audio/agc_audio_stream.h',
+ 'audio/alsa/alsa_input.cc',
+ 'audio/alsa/alsa_input.h',
+ 'audio/alsa/alsa_output.cc',
+ 'audio/alsa/alsa_output.h',
+ 'audio/alsa/alsa_util.cc',
+ 'audio/alsa/alsa_util.h',
+ 'audio/alsa/alsa_wrapper.cc',
+ 'audio/alsa/alsa_wrapper.h',
+ 'audio/alsa/audio_manager_alsa.cc',
+ 'audio/alsa/audio_manager_alsa.h',
'audio/android/audio_manager_android.cc',
'audio/android/audio_manager_android.h',
'audio/android/opensles_input.cc',
@@ -115,16 +125,10 @@
'audio/fake_audio_consumer.h',
'audio/fake_audio_input_stream.cc',
'audio/fake_audio_input_stream.h',
+ 'audio/fake_audio_manager.cc',
+ 'audio/fake_audio_manager.h',
'audio/fake_audio_output_stream.cc',
'audio/fake_audio_output_stream.h',
- 'audio/linux/alsa_input.cc',
- 'audio/linux/alsa_input.h',
- 'audio/linux/alsa_output.cc',
- 'audio/linux/alsa_output.h',
- 'audio/linux/alsa_util.cc',
- 'audio/linux/alsa_util.h',
- 'audio/linux/alsa_wrapper.cc',
- 'audio/linux/alsa_wrapper.h',
'audio/linux/audio_manager_linux.cc',
'audio/linux/audio_manager_linux.h',
'audio/mac/aggregate_device_manager.cc',
@@ -573,9 +577,11 @@
'-lasound',
],
},
+ 'defines': [
+ 'USE_ALSA',
+ ],
}, { # use_alsa==0
- 'sources/': [ ['exclude', '/alsa_'],
- ['exclude', '/audio_manager_linux'] ],
+ 'sources/': [ ['exclude', '(^|/)alsa/'], ],
}],
['OS!="openbsd"', {
'sources!': [
@@ -875,6 +881,7 @@
],
'sources': [
'audio/android/audio_android_unittest.cc',
+ 'audio/alsa/alsa_output_unittest.cc',
'audio/audio_input_controller_unittest.cc',
'audio/audio_input_unittest.cc',
'audio/audio_input_volume_unittest.cc',
@@ -886,7 +893,6 @@
'audio/audio_parameters_unittest.cc',
'audio/audio_power_monitor_unittest.cc',
'audio/fake_audio_consumer_unittest.cc',
- 'audio/linux/alsa_output_unittest.cc',
'audio/mac/audio_auhal_mac_unittest.cc',
'audio/mac/audio_device_listener_mac_unittest.cc',
'audio/mac/audio_low_latency_input_mac_unittest.cc',
@@ -1064,7 +1070,7 @@
}],
['use_alsa==0', {
'sources!': [
- 'audio/linux/alsa_output_unittest.cc',
+ 'audio/alsa/alsa_output_unittest.cc',
'audio/audio_low_latency_input_output_unittest.cc',
],
}],
diff --git a/tools/valgrind/tsan/suppressions.txt b/tools/valgrind/tsan/suppressions.txt
index 7e25d0b..6497f29 100644
--- a/tools/valgrind/tsan/suppressions.txt
+++ b/tools/valgrind/tsan/suppressions.txt
@@ -1069,7 +1069,7 @@
{
bug_256792
ThreadSanitizer:Race
- fun:media::AudioManagerLinux::~AudioManagerLinux
+ fun:media::AudioManagerAlsa::~AudioManagerAlsa
fun:content::MockAudioManager::~MockAudioManager
fun:content::MockAudioManager::~MockAudioManager
fun:base::DefaultDeleter*