diff options
-rw-r--r-- | media/audio/audio_device_name.h | 22 | ||||
-rw-r--r-- | media/audio/audio_input_device_unittest.cc | 32 | ||||
-rw-r--r-- | media/audio/audio_manager.h | 7 | ||||
-rw-r--r-- | media/audio/audio_manager_base.cc | 6 | ||||
-rw-r--r-- | media/audio/audio_manager_base.h | 5 | ||||
-rw-r--r-- | media/audio/audio_output_proxy_unittest.cc | 4 | ||||
-rw-r--r-- | media/audio/linux/audio_manager_linux.cc | 91 | ||||
-rw-r--r-- | media/audio/linux/audio_manager_linux.h | 4 | ||||
-rw-r--r-- | media/audio/mac/audio_manager_mac.cc | 14 | ||||
-rw-r--r-- | media/audio/mac/audio_manager_mac.h | 1 | ||||
-rw-r--r-- | media/audio/win/audio_manager_win.cc | 14 | ||||
-rw-r--r-- | media/audio/win/audio_manager_win.h | 1 | ||||
-rw-r--r-- | media/media.gyp | 2 |
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', |