summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-11 16:43:49 +0000
committerjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-11 16:43:49 +0000
commitf6696b9fd21eda8afc74dfec3d20236d25dbaf02 (patch)
tree2a69d0b88c21e4cb1e8569635f62ce5ee875090c /media
parentaf6cc64e8114d37985487d0bc3ded3d552c2ad7f (diff)
downloadchromium_src-f6696b9fd21eda8afc74dfec3d20236d25dbaf02.zip
chromium_src-f6696b9fd21eda8afc74dfec3d20236d25dbaf02.tar.gz
chromium_src-f6696b9fd21eda8afc74dfec3d20236d25dbaf02.tar.bz2
Implement GetAudioOutputDevices for Windows.
Rename ConvertToWinXPDeviceId to ConvertToWinXPInputDeviceId to avoid confusion since the other APIs in the same header are now available for both input and output devices. Get rid of a few unnecessary media:: prefixes (we're in the namespace already). BUG=276894 Review URL: https://chromiumcodereview.appspot.com/23903022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222574 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/audio_input_device_unittest.cc2
-rw-r--r--media/audio/audio_manager_unittest.cc49
-rw-r--r--media/audio/win/audio_manager_win.cc32
-rw-r--r--media/audio/win/audio_manager_win.h8
-rw-r--r--media/audio/win/device_enumeration_win.cc59
-rw-r--r--media/audio/win/device_enumeration_win.h16
6 files changed, 133 insertions, 33 deletions
diff --git a/media/audio/audio_input_device_unittest.cc b/media/audio/audio_input_device_unittest.cc
index dc211a4..61a9783 100644
--- a/media/audio/audio_input_device_unittest.cc
+++ b/media/audio/audio_input_device_unittest.cc
@@ -164,7 +164,7 @@ TEST_F(AudioInputDeviceTest, WinXPDeviceIdUnchanged) {
}
}
-TEST_F(AudioInputDeviceTest, ConvertToWinXPDeviceId) {
+TEST_F(AudioInputDeviceTest, ConvertToWinXPInputDeviceId) {
if (!CanRunAudioTest())
return;
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 8d68b00..96300c9 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -11,6 +11,10 @@
#include "media/audio/linux/audio_manager_linux.h"
#endif // defined(OS_LINUX)
+#if defined(OS_WIN)
+#include "media/audio/win/audio_manager_win.h"
+#endif // defined(OS_WIN)
+
#if defined(USE_PULSEAUDIO)
#include "media/audio/pulse/audio_manager_pulse.h"
#endif // defined(USE_PULSEAUDIO)
@@ -31,7 +35,30 @@ void GetAudioOutputDeviceNamesImpl(AudioManager* audio_manager) {
}
}
-TEST(AudioManagerTest, GetAudioOutputDeviceNames) {
+// So that tests herein can be friends of AudioManagerWin.
+//
+// TODO(joi): Make this go away by unifying audio_manager_unittest.cc
+// and audio_input_device_unittest.cc
+class AudioManagerTest : public ::testing::Test {
+ public:
+ bool SetupForSecondTest(AudioManager* amw) {
+#if defined(OS_WIN)
+ AudioManagerWin* audio_manager_win = static_cast<AudioManagerWin*>(amw);
+ if (audio_manager_win->enumeration_type() ==
+ AudioManagerWin::kWaveEnumeration) {
+ // This will be true only if running on Windows XP.
+ VLOG(2) << "AudioManagerWin on WinXP; nothing more to test.";
+ } else {
+ VLOG(2) << "Testing AudioManagerWin in fallback WinXP mode.";
+ audio_manager_win->SetEnumerationType(AudioManagerWin::kWaveEnumeration);
+ return true;
+ }
+#endif // defined(OS_WIN)
+ return false;
+ }
+};
+
+TEST_F(AudioManagerTest, GetAudioOutputDeviceNames) {
// On Linux, we may be able to test both the Alsa and Pulseaudio
// versions of the audio manager.
#if defined(USE_PULSEAUDIO)
@@ -57,9 +84,24 @@ TEST(AudioManagerTest, GetAudioOutputDeviceNames) {
scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
GetAudioOutputDeviceNamesImpl(audio_manager.get());
#endif // defined(OS_MACOSX)
+
+#if defined(OS_WIN)
+ {
+ // TODO(joi): Unify the tests in audio_input_device_unittest.cc
+ // with the tests in this file, and reuse the Windows-specific
+ // bits from that file.
+ VLOG(2) << "Testing AudioManagerWin in its default mode.";
+ scoped_ptr<AudioManager> audio_manager_win(AudioManager::Create());
+ GetAudioOutputDeviceNamesImpl(audio_manager_win.get());
+
+ if (SetupForSecondTest(audio_manager_win.get())) {
+ GetAudioOutputDeviceNamesImpl(audio_manager_win.get());
+ }
+ }
+#endif // defined(OS_WIN)
}
-TEST(AudioManagerTest, GetDefaultOutputStreamParameters) {
+TEST_F(AudioManagerTest, GetDefaultOutputStreamParameters) {
#if defined(OS_WIN) || defined(OS_MACOSX)
scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
ASSERT_TRUE(audio_manager);
@@ -71,7 +113,7 @@ TEST(AudioManagerTest, GetDefaultOutputStreamParameters) {
#endif // defined(OS_WIN) || defined(OS_MACOSX)
}
-TEST(AudioManagerTest, GetAssociatedOutputDeviceID) {
+TEST_F(AudioManagerTest, GetAssociatedOutputDeviceID) {
#if defined(OS_WIN) || defined(OS_MACOSX)
scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
ASSERT_TRUE(audio_manager);
@@ -99,4 +141,5 @@ TEST(AudioManagerTest, GetAssociatedOutputDeviceID) {
EXPECT_TRUE(found_an_associated_device);
#endif // defined(OS_WIN) || defined(OS_MACOSX)
}
+
} // namespace media
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index ff6e3f7..e3a9588 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -240,28 +240,44 @@ void AudioManagerWin::ShowAudioInputSettings() {
base::LaunchProcess(command_line, base::LaunchOptions(), NULL);
}
-void AudioManagerWin::GetAudioInputDeviceNames(
- media::AudioDeviceNames* device_names) {
+void AudioManagerWin::GetAudioDeviceNamesImpl(
+ bool input,
+ AudioDeviceNames* device_names) {
DCHECK(device_names->empty());
DCHECK(enumeration_type() != kUninitializedEnumeration);
// Enumerate all active audio-endpoint capture devices.
if (enumeration_type() == kWaveEnumeration) {
// Utilize the Wave API for Windows XP.
- media::GetInputDeviceNamesWinXP(device_names);
+ if (input)
+ GetInputDeviceNamesWinXP(device_names);
+ else
+ GetOutputDeviceNamesWinXP(device_names);
} else {
// Utilize the MMDevice API (part of Core Audio) for Vista and higher.
- media::GetInputDeviceNamesWin(device_names);
+ if (input)
+ GetInputDeviceNamesWin(device_names);
+ else
+ GetOutputDeviceNamesWin(device_names);
}
// Always add default device parameters as first element.
if (!device_names->empty()) {
- media::AudioDeviceName name;
+ AudioDeviceName name;
name.device_name = AudioManagerBase::kDefaultDeviceName;
name.unique_id = AudioManagerBase::kDefaultDeviceId;
device_names->push_front(name);
}
}
+void AudioManagerWin::GetAudioInputDeviceNames(AudioDeviceNames* device_names) {
+ GetAudioDeviceNamesImpl(true, device_names);
+}
+
+void AudioManagerWin::GetAudioOutputDeviceNames(
+ AudioDeviceNames* device_names) {
+ GetAudioDeviceNamesImpl(false, device_names);
+}
+
AudioParameters AudioManagerWin::GetInputStreamParameters(
const std::string& device_id) {
int sample_rate = 48000;
@@ -297,7 +313,7 @@ AudioOutputStream* AudioManagerWin::MakeLinearOutputStream(
return new PCMWaveOutAudioOutputStream(this,
params,
- media::NumberOfWaveOutBuffers(),
+ NumberOfWaveOutBuffers(),
WAVE_MAPPER);
}
@@ -320,7 +336,7 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
<< "Opening by device id not supported by PCMWaveOutAudioOutputStream";
DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista.";
return new PCMWaveOutAudioOutputStream(
- this, params, media::NumberOfWaveOutBuffers(), WAVE_MAPPER);
+ this, params, NumberOfWaveOutBuffers(), WAVE_MAPPER);
}
// TODO(rtoy): support more than stereo input.
@@ -460,7 +476,7 @@ AudioInputStream* AudioManagerWin::CreatePCMWaveInAudioInputStream(
std::string xp_device_id = device_id;
if (device_id != AudioManagerBase::kDefaultDeviceId &&
enumeration_type_ == kMMDeviceEnumeration) {
- xp_device_id = media::ConvertToWinXPDeviceId(device_id);
+ xp_device_id = ConvertToWinXPInputDeviceId(device_id);
if (xp_device_id.empty()) {
DLOG(ERROR) << "Cannot find a waveIn device which matches the device ID "
<< device_id;
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 16535a3..b3e8de9 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -25,7 +25,9 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
virtual bool HasAudioInputDevices() OVERRIDE;
virtual string16 GetAudioInputDeviceModel() OVERRIDE;
virtual void ShowAudioInputSettings() OVERRIDE;
- virtual void GetAudioInputDeviceNames(media::AudioDeviceNames* device_names)
+ virtual void GetAudioInputDeviceNames(AudioDeviceNames* device_names)
+ OVERRIDE;
+ virtual void GetAudioOutputDeviceNames(AudioDeviceNames* device_names)
OVERRIDE;
virtual AudioParameters GetInputStreamParameters(
const std::string& device_id) OVERRIDE;
@@ -60,6 +62,8 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
};
// Allow unit test to modify the utilized enumeration API.
+ // TODO(joi): Collapse these tests into one.
+ friend class AudioManagerTest;
friend class AudioInputDeviceTest;
EnumerationType enumeration_type_;
@@ -81,6 +85,8 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
void CreateDeviceListener();
void DestroyDeviceListener();
+ void GetAudioDeviceNamesImpl(bool input, AudioDeviceNames* device_names);
+
// Listen for output device changes.
scoped_ptr<AudioDeviceListenerWin> output_device_listener_;
diff --git a/media/audio/win/device_enumeration_win.cc b/media/audio/win/device_enumeration_win.cc
index 36ed291..50d0b7a 100644
--- a/media/audio/win/device_enumeration_win.cc
+++ b/media/audio/win/device_enumeration_win.cc
@@ -8,13 +8,13 @@
#include "media/audio/win/audio_manager_win.h"
+#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_propvariant.h"
-using media::AudioDeviceNames;
using base::win::ScopedComPtr;
using base::win::ScopedCoMem;
@@ -25,7 +25,10 @@ using base::win::ScopedCoMem;
namespace media {
-bool GetInputDeviceNamesWin(AudioDeviceNames* device_names) {
+namespace {
+
+bool GetDeviceNamesWinImpl(EDataFlow data_flow,
+ AudioDeviceNames* device_names) {
// It is assumed that this method is called from a COM thread, i.e.,
// CoInitializeEx() is not called here again to avoid STA/MTA conflicts.
ScopedComPtr<IMMDeviceEnumerator> enumerator;
@@ -37,24 +40,24 @@ bool GetInputDeviceNamesWin(AudioDeviceNames* device_names) {
return false;
}
- // Generate a collection of active audio capture endpoint devices.
+ // Generate a collection of active audio endpoint devices.
// This method will succeed even if all devices are disabled.
ScopedComPtr<IMMDeviceCollection> collection;
- hr = enumerator->EnumAudioEndpoints(eCapture,
+ hr = enumerator->EnumAudioEndpoints(data_flow,
DEVICE_STATE_ACTIVE,
collection.Receive());
if (FAILED(hr))
return false;
- // Retrieve the number of active capture devices.
+ // Retrieve the number of active devices.
UINT number_of_active_devices = 0;
collection->GetCount(&number_of_active_devices);
if (number_of_active_devices == 0)
return true;
- media::AudioDeviceName device;
+ AudioDeviceName device;
- // Loop over all active capture devices and add friendly name and
+ // Loop over all active devices and add friendly name and
// unique ID to the |device_names| list.
for (UINT i = 0; i < number_of_active_devices; ++i) {
// Retrieve unique name of endpoint device.
@@ -92,14 +95,22 @@ bool GetInputDeviceNamesWin(AudioDeviceNames* device_names) {
return true;
}
-bool GetInputDeviceNamesWinXP(AudioDeviceNames* device_names) {
+// The waveform API is weird in that it has completely separate but
+// almost identical functions and structs for input devices vs. output
+// devices. We deal with this by implementing the logic as a templated
+// function that takes the functions and struct type to use as
+// template parameters.
+template <UINT (__stdcall *NumDevsFunc)(),
+ typename CAPSSTRUCT,
+ MMRESULT (__stdcall *DevCapsFunc)(UINT_PTR, CAPSSTRUCT*, UINT)>
+bool GetDeviceNamesWinXPImpl(AudioDeviceNames* device_names) {
// Retrieve the number of active waveform input devices.
- UINT number_of_active_devices = waveInGetNumDevs();
+ UINT number_of_active_devices = NumDevsFunc();
if (number_of_active_devices == 0)
return true;
- media::AudioDeviceName device;
- WAVEINCAPS capabilities;
+ AudioDeviceName device;
+ CAPSSTRUCT capabilities;
MMRESULT err = MMSYSERR_NOERROR;
// Loop over all active capture devices and add friendly name and
@@ -108,7 +119,7 @@ bool GetInputDeviceNamesWinXP(AudioDeviceNames* device_names) {
// there is no safe method to retrieve a unique device name on XP.
for (UINT i = 0; i < number_of_active_devices; ++i) {
// Retrieve the capabilities of the specified waveform-audio input device.
- err = waveInGetDevCaps(i, &capabilities, sizeof(capabilities));
+ err = DevCapsFunc(i, &capabilities, sizeof(capabilities));
if (err != MMSYSERR_NOERROR)
continue;
@@ -118,7 +129,7 @@ bool GetInputDeviceNamesWinXP(AudioDeviceNames* device_names) {
device.device_name = WideToUTF8(capabilities.szPname);
// Store the "unique" name (we use same as friendly name on Windows XP).
- device.unique_id = WideToUTF8(capabilities.szPname);
+ device.unique_id = device.device_name;
// Add combination of user-friendly and unique name to the output list.
device_names->push_back(device);
@@ -127,7 +138,27 @@ bool GetInputDeviceNamesWinXP(AudioDeviceNames* device_names) {
return true;
}
-std::string ConvertToWinXPDeviceId(const std::string& device_id) {
+} // namespace
+
+bool GetInputDeviceNamesWin(AudioDeviceNames* device_names) {
+ return GetDeviceNamesWinImpl(eCapture, device_names);
+}
+
+bool GetOutputDeviceNamesWin(AudioDeviceNames* device_names) {
+ return GetDeviceNamesWinImpl(eRender, device_names);
+}
+
+bool GetInputDeviceNamesWinXP(AudioDeviceNames* device_names) {
+ return GetDeviceNamesWinXPImpl<
+ waveInGetNumDevs, WAVEINCAPSW, waveInGetDevCapsW>(device_names);
+}
+
+bool GetOutputDeviceNamesWinXP(AudioDeviceNames* device_names) {
+ return GetDeviceNamesWinXPImpl<
+ waveOutGetNumDevs, WAVEOUTCAPSW, waveOutGetDevCapsW>(device_names);
+}
+
+std::string ConvertToWinXPInputDeviceId(const std::string& device_id) {
UINT number_of_active_devices = waveInGetNumDevs();
MMRESULT result = MMSYSERR_NOERROR;
diff --git a/media/audio/win/device_enumeration_win.h b/media/audio/win/device_enumeration_win.h
index 3d44670..e61a331 100644
--- a/media/audio/win/device_enumeration_win.h
+++ b/media/audio/win/device_enumeration_win.h
@@ -11,28 +11,32 @@
namespace media {
-// Returns a list of audio input device structures (name and unique device ID)
-// using the MMDevice API which is supported on Windows Vista and higher.
+// Returns a list of audio input or output device structures (name and
+// unique device ID) using the MMDevice API which is supported on
+// Windows Vista and higher.
// Example record in the output list:
// - device_name: "Microphone (Realtek High Definition Audio)".
// - unique_id: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}"
// This method must be called from a COM thread using MTA.
bool GetInputDeviceNamesWin(media::AudioDeviceNames* device_names);
+bool GetOutputDeviceNamesWin(media::AudioDeviceNames* device_names);
-// Returns a list of audio input device structures (name and unique device ID)
-// using the WaveIn API which is supported on Windows XP and higher.
+// Returns a list of audio input or output device structures (name and
+// unique device ID) using the WaveIn API which is supported on
+// Windows XP and higher.
// Example record in the output list:
// - device_name: "Microphone (Realtek High Defini".
// - unique_id: "Microphone (Realtek High Defini" (same as friendly name).
bool GetInputDeviceNamesWinXP(media::AudioDeviceNames* device_names);
+bool GetOutputDeviceNamesWinXP(media::AudioDeviceNames* device_names);
-// Converts a device ID generated by |GetInputDeviceNamesWin()| to the
+// Converts an input device ID generated by |GetInputDeviceNamesWin()| to the
// corresponding ID by |GetInputDeviceNamesWinXP()|. Returns an empty string on
// failure.
// Example input and output:
// - input ID: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}"
// - output ID: "Microphone (Realtek High Defini"
-std::string ConvertToWinXPDeviceId(const std::string& device_id);
+std::string ConvertToWinXPInputDeviceId(const std::string& device_id);
} // namespace media