summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/audio/audio_device_name.h22
-rw-r--r--media/audio/audio_input_device_unittest.cc32
-rw-r--r--media/audio/audio_manager.h7
-rw-r--r--media/audio/audio_manager_base.cc6
-rw-r--r--media/audio/audio_manager_base.h5
-rw-r--r--media/audio/audio_output_proxy_unittest.cc4
-rw-r--r--media/audio/linux/audio_manager_linux.cc91
-rw-r--r--media/audio/linux/audio_manager_linux.h4
-rw-r--r--media/audio/mac/audio_manager_mac.cc14
-rw-r--r--media/audio/mac/audio_manager_mac.h1
-rw-r--r--media/audio/win/audio_manager_win.cc14
-rw-r--r--media/audio/win/audio_manager_win.h1
-rw-r--r--media/media.gyp2
13 files changed, 198 insertions, 5 deletions
diff --git a/media/audio/audio_device_name.h b/media/audio/audio_device_name.h
new file mode 100644
index 0000000..ef3cd77
--- /dev/null
+++ b/media/audio/audio_device_name.h
@@ -0,0 +1,22 @@
+// 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.
+
+#ifndef MEDIA_AUDIO_AUDIO_DEVICE_NAME_H_
+#define MEDIA_AUDIO_AUDIO_DEVICE_NAME_H_
+
+#include <list>
+#include <string>
+
+namespace media {
+
+struct AudioDeviceName {
+ std::string device_name; // Name and also display name of the device.
+ std::string unique_id; // Unique identifier for the device.
+};
+
+typedef std::list<AudioDeviceName> AudioDeviceNames;
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_AUDIO_DEVICE_NAME_H_
diff --git a/media/audio/audio_input_device_unittest.cc b/media/audio/audio_input_device_unittest.cc
new file mode 100644
index 0000000..1f342ba
--- /dev/null
+++ b/media/audio/audio_input_device_unittest.cc
@@ -0,0 +1,32 @@
+// 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_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+// Test that devices can be enumerated.
+TEST(AudioInputDeviceTest, EnumerateDevices) {
+ AudioDeviceNames device_names;
+ ASSERT_TRUE(AudioManager::GetAudioManager() != NULL);
+ AudioManager::GetAudioManager()->GetAudioInputDeviceNames(
+ &device_names);
+ if (!device_names.empty()) {
+ AudioDeviceNames::const_iterator it = device_names.begin();
+ // The first device in the list is the prepended default device.
+ EXPECT_EQ("Default", it->device_name);
+ EXPECT_EQ("0", it->unique_id);
+ ++it;
+
+ // Other devices should have non-empty name and id.
+ while (it != device_names.end()) {
+ EXPECT_EQ("", it->device_name);
+ EXPECT_EQ("", it->unique_id);
+ ++it;
+ }
+ }
+}
+
+} // namespace media
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 370fd8e..4e9c6b3 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "base/string16.h"
#include "base/task.h"
+#include "media/audio/audio_device_name.h"
#include "media/audio/audio_parameters.h"
class AudioInputStream;
@@ -45,6 +46,12 @@ class AudioManager {
// threads to avoid blocking the rest of the application.
virtual void ShowAudioInputSettings() = 0;
+ // Appends a list of available input devices. It is not guaranteed that
+ // all the devices in the list support all formats and sample rates for
+ // recording.
+ virtual void GetAudioInputDeviceNames(
+ media::AudioDeviceNames* device_names) = 0;
+
// Factory for all the supported stream formats. |params| defines parameters
// of the audio stream to be created.
//
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 6aa67f21..d0614f4 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -8,6 +8,8 @@
static const int kStreamCloseDelayMs = 5000;
+const char AudioManagerBase::kDefaultDeviceName[] = "Default";
+
AudioManagerBase::AudioManagerBase()
: audio_thread_("AudioThread"),
initialized_(false) {
@@ -56,3 +58,7 @@ bool AudioManagerBase::CanShowAudioInputSettings() {
void AudioManagerBase::ShowAudioInputSettings() {
}
+
+void AudioManagerBase::GetAudioInputDeviceNames(
+ media::AudioDeviceNames* device_names) {
+}
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index a5140a2..239ac5c 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -15,6 +15,9 @@ class AudioOutputDispatcher;
// AudioManagerBase provides AudioManager functions common for all platforms.
class AudioManagerBase : public AudioManager {
public:
+ // Name of the generic "default" device.
+ static const char kDefaultDeviceName[];
+
AudioManagerBase();
virtual void Init();
@@ -27,6 +30,8 @@ class AudioManagerBase : public AudioManager {
virtual bool CanShowAudioInputSettings();
virtual void ShowAudioInputSettings();
+ virtual void GetAudioInputDeviceNames(media::AudioDeviceNames* device_names);
+
virtual AudioOutputStream* MakeAudioOutputStreamProxy(
const AudioParameters& params);
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc
index 814aca4..1de3149 100644
--- a/media/audio/audio_output_proxy_unittest.cc
+++ b/media/audio/audio_output_proxy_unittest.cc
@@ -33,7 +33,7 @@ class MockAudioOutputStream : public AudioOutputStream {
class MockAudioManager : public AudioManager {
public:
- MockAudioManager() { };
+ MockAudioManager() {}
MOCK_METHOD0(Init, void());
MOCK_METHOD0(Cleanup, void());
@@ -51,6 +51,8 @@ class MockAudioManager : public AudioManager {
MOCK_METHOD0(CanShowAudioInputSettings, bool());
MOCK_METHOD0(ShowAudioInputSettings, void());
MOCK_METHOD0(GetMessageLoop, MessageLoop*());
+ MOCK_METHOD1(GetAudioInputDeviceNames, void(
+ media::AudioDeviceNames* device_name));
};
class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index b1108be..58b4c0e 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -23,6 +23,30 @@ static const size_t kMaxOutputStreams = 50;
static const int kMaxInputChannels = 2;
+// 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",
+ "null",
+ "pulse",
+ "dmix",
+ "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.
@@ -30,8 +54,31 @@ bool AudioManagerLinux::HasAudioOutputDevices() {
}
bool AudioManagerLinux::HasAudioInputDevices() {
- // TODO(satish): Make this actually query audio devices.
- return true;
+ if (!initialized()) {
+ return false;
+ }
+
+ // Constants specified by the ALSA API for device hints.
+ static const int kGetAllDevices = -1;
+ static const char kPcmInterfaceName[] = "pcm";
+ bool has_device = false;
+ void** hints = NULL;
+
+ // Use the same approach to find the devices as in
+ // AlsaPcmOutputStream::FindDeviceForChannels
+ // Get Alsa device hints.
+ int error = wrapper_->DeviceNameHint(kGetAllDevices,
+ kPcmInterfaceName,
+ &hints);
+ if (error == 0) {
+ has_device = HasAnyValidAudioInputDevice(hints);
+ } else {
+ LOG(ERROR) << "Unable to get device hints: " << wrapper_->StrError(error);
+ }
+
+ // Destroy the hint now that we're done with it.
+ wrapper_->DeviceNameFreeHint(hints);
+ return has_device;
}
AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream(
@@ -96,8 +143,8 @@ AudioManagerLinux::AudioManagerLinux() {
}
AudioManagerLinux::~AudioManagerLinux() {
- // Make sure we stop the thread first. If we let the default destructor to
- // destruct the members, we may destroy audio streams before stopping the
+ // Make sure we stop the thread first. If we allow the default destructor to
+ // destroy the members, we may destroy audio streams before stopping the
// thread, resulting an unexpected behavior.
// This way we make sure activities of the audio streams are all stopped
// before we destroy them.
@@ -147,6 +194,42 @@ void AudioManagerLinux::ShowAudioInputSettings() {
base::LaunchApp(CommandLine(FilePath(command)), false, false, NULL);
}
+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);
+ }
+}
+
+bool AudioManagerLinux::HasAnyValidAudioInputDevice(void** hints) {
+ static const char kIoHintName[] = "IOID";
+ static const char kNameHintName[] = "NAME";
+ static const char kOutputDevice[] = "Output";
+
+ for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) {
+ // Only examine devices that are input 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(kOutputDevice, io.get()) == 0)
+ continue;
+
+ scoped_ptr_malloc<char> hint_device_name(
+ wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName));
+ if (IsValidAudioInputDevice(hint_device_name.get()))
+ return true;
+ }
+
+ return false;
+}
+
// static
AudioManager* AudioManager::CreateAudioManager() {
return new AudioManagerLinux();
diff --git a/media/audio/linux/audio_manager_linux.h b/media/audio/linux/audio_manager_linux.h
index b7d43f0..6a5d287 100644
--- a/media/audio/linux/audio_manager_linux.h
+++ b/media/audio/linux/audio_manager_linux.h
@@ -30,6 +30,7 @@ class AudioManagerLinux : public AudioManagerBase {
virtual AudioInputStream* MakeAudioInputStream(AudioParameters params);
virtual bool CanShowAudioInputSettings();
virtual void ShowAudioInputSettings();
+ virtual void GetAudioInputDeviceNames(media::AudioDeviceNames* device_names);
virtual void MuteAll();
virtual void UnMuteAll();
@@ -40,6 +41,9 @@ class AudioManagerLinux : public AudioManagerBase {
virtual ~AudioManagerLinux();
private:
+ // Helper method to query if there is any valid input device
+ bool HasAnyValidAudioInputDevice(void** hint);
+
scoped_ptr<AlsaWrapper> wrapper_;
base::Lock lock_;
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 8b2c918..84d5fee 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -81,6 +81,20 @@ bool AudioManagerMac::HasAudioInputDevices() {
return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
}
+void AudioManagerMac::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);
+ }
+}
+
AudioOutputStream* AudioManagerMac::MakeAudioOutputStream(
AudioParameters params) {
if (!params.IsValid())
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index 1977bac..2556aec 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -21,6 +21,7 @@ class AudioManagerMac : public AudioManagerBase {
// Implementation of AudioManager.
virtual bool HasAudioOutputDevices();
virtual bool HasAudioInputDevices();
+ virtual void GetAudioInputDeviceNames(media::AudioDeviceNames* device_names);
virtual AudioOutputStream* MakeAudioOutputStream(AudioParameters params);
virtual AudioInputStream* MakeAudioInputStream(AudioParameters params);
virtual void MuteAll();
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index 998a9d8..aade91e 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -253,6 +253,20 @@ void AudioManagerWin::ShowAudioInputSettings() {
base::LaunchApp(command_line, false, false, NULL);
}
+void AudioManagerWin::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);
+ }
+}
+
// static
AudioManager* AudioManager::CreateAudioManager() {
return new AudioManagerWin();
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 1edd6a6..a6e9874 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -29,6 +29,7 @@ class AudioManagerWin : public AudioManagerBase {
virtual string16 GetAudioInputDeviceModel();
virtual bool CanShowAudioInputSettings();
virtual void ShowAudioInputSettings();
+ virtual void GetAudioInputDeviceNames(media::AudioDeviceNames* device_names);
// Windows-only methods to free a stream created in MakeAudioStream. These
// are called internally by the audio stream when it has been closed.
diff --git a/media/media.gyp b/media/media.gyp
index 59c3690..d90b43e 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -28,6 +28,7 @@
'audio/audio_io.h',
'audio/audio_input_controller.cc',
'audio/audio_input_controller.h',
+ 'audio/audio_device_name.h',
'audio/audio_manager.cc',
'audio/audio_manager.h',
'audio/audio_manager_base.cc',
@@ -388,6 +389,7 @@
],
'sources': [
'audio/audio_input_controller_unittest.cc',
+ 'audio/audio_input_device_unittest.cc',
'audio/audio_input_unittest.cc',
'audio/audio_output_controller_unittest.cc',
'audio/audio_output_proxy_unittest.cc',