1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/environment.h"
6 #include "base/logging.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "media/audio/audio_manager.h"
9 #include "media/audio/audio_manager_base.h"
10 #include "testing/gtest/include/gtest/gtest.h"
13 #include "media/audio/linux/audio_manager_linux.h"
14 #endif // defined(OS_LINUX)
17 #include "base/win/scoped_com_initializer.h"
18 #include "media/audio/win/audio_manager_win.h"
19 #include "media/audio/win/wavein_input_win.h"
22 #if defined(USE_PULSEAUDIO)
23 #include "media/audio/pulse/audio_manager_pulse.h"
24 #endif // defined(USE_PULSEAUDIO)
28 // Test fixture which allows us to override the default enumeration API on
30 class AudioManagerTest
31 : public ::testing::Test
{
34 : audio_manager_(AudioManager::Create())
36 , com_init_(base::win::ScopedCOMInitializer::kMTA
)
42 bool SetMMDeviceEnumeration() {
43 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
44 // Windows Wave is used as default if Windows XP was detected =>
45 // return false since MMDevice is not supported on XP.
46 if (amw
->enumeration_type() == AudioManagerWin::kWaveEnumeration
)
49 amw
->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration
);
53 void SetWaveEnumeration() {
54 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
55 amw
->SetEnumerationType(AudioManagerWin::kWaveEnumeration
);
58 std::string
GetDeviceIdFromPCMWaveInAudioInputStream(
59 const std::string
& device_id
) {
60 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
61 AudioParameters
parameters(
62 AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
63 AudioParameters::kAudioCDSampleRate
, 16,
65 scoped_ptr
<PCMWaveInAudioInputStream
> stream(
66 static_cast<PCMWaveInAudioInputStream
*>(
67 amw
->CreatePCMWaveInAudioInputStream(parameters
, device_id
)));
68 return stream
.get() ? stream
->device_id_
: std::string();
72 // Helper method which verifies that the device list starts with a valid
73 // default record followed by non-default device names.
74 static void CheckDeviceNames(const AudioDeviceNames
& device_names
) {
75 VLOG(2) << "Got " << device_names
.size() << " audio devices.";
76 if (!device_names
.empty()) {
77 AudioDeviceNames::const_iterator it
= device_names
.begin();
79 // The first device in the list should always be the default device.
80 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName
),
82 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId
), it
->unique_id
);
85 // Other devices should have non-empty name and id and should not contain
86 // default name or id.
87 while (it
!= device_names
.end()) {
88 EXPECT_FALSE(it
->device_name
.empty());
89 EXPECT_FALSE(it
->unique_id
.empty());
90 VLOG(2) << "Device ID(" << it
->unique_id
91 << "), label: " << it
->device_name
;
92 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName
),
94 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId
),
99 // Log a warning so we can see the status on the build bots. No need to
100 // break the test though since this does successfully test the code and
101 // some failure cases.
102 LOG(WARNING
) << "No input devices detected";
106 bool CanRunInputTest() {
107 return audio_manager_
->HasAudioInputDevices();
110 bool CanRunOutputTest() {
111 return audio_manager_
->HasAudioOutputDevices();
114 scoped_ptr
<AudioManager
> audio_manager_
;
117 // The MMDevice API requires COM to be initialized on the current thread.
118 base::win::ScopedCOMInitializer com_init_
;
122 // Test that devices can be enumerated.
123 TEST_F(AudioManagerTest
, EnumerateInputDevices
) {
124 if (!CanRunInputTest())
127 AudioDeviceNames device_names
;
128 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
129 CheckDeviceNames(device_names
);
132 // Test that devices can be enumerated.
133 TEST_F(AudioManagerTest
, EnumerateOutputDevices
) {
134 if (!CanRunOutputTest())
137 AudioDeviceNames device_names
;
138 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
139 CheckDeviceNames(device_names
);
142 // Run additional tests for Windows since enumeration can be done using
143 // two different APIs. MMDevice is default for Vista and higher and Wave
144 // is default for XP and lower.
147 // Override default enumeration API and force usage of Windows MMDevice.
148 // This test will only run on Windows Vista and higher.
149 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinMMDevice
) {
150 if (!CanRunInputTest())
153 AudioDeviceNames device_names
;
154 if (!SetMMDeviceEnumeration()) {
155 // Usage of MMDevice will fail on XP and lower.
156 LOG(WARNING
) << "MM device enumeration is not supported.";
159 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
160 CheckDeviceNames(device_names
);
163 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinMMDevice
) {
164 if (!CanRunOutputTest())
167 AudioDeviceNames device_names
;
168 if (!SetMMDeviceEnumeration()) {
169 // Usage of MMDevice will fail on XP and lower.
170 LOG(WARNING
) << "MM device enumeration is not supported.";
173 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
174 CheckDeviceNames(device_names
);
177 // Override default enumeration API and force usage of Windows Wave.
178 // This test will run on Windows XP, Windows Vista and Windows 7.
179 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinWave
) {
180 if (!CanRunInputTest())
183 AudioDeviceNames device_names
;
184 SetWaveEnumeration();
185 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
186 CheckDeviceNames(device_names
);
189 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinWave
) {
190 if (!CanRunOutputTest())
193 AudioDeviceNames device_names
;
194 SetWaveEnumeration();
195 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
196 CheckDeviceNames(device_names
);
199 TEST_F(AudioManagerTest
, WinXPDeviceIdUnchanged
) {
200 if (!CanRunInputTest())
203 AudioDeviceNames xp_device_names
;
204 SetWaveEnumeration();
205 audio_manager_
->GetAudioInputDeviceNames(&xp_device_names
);
206 CheckDeviceNames(xp_device_names
);
208 // Device ID should remain unchanged, including the default device ID.
209 for (AudioDeviceNames::iterator i
= xp_device_names
.begin();
210 i
!= xp_device_names
.end(); ++i
) {
211 EXPECT_EQ(i
->unique_id
,
212 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
));
216 TEST_F(AudioManagerTest
, ConvertToWinXPInputDeviceId
) {
217 if (!CanRunInputTest())
220 if (!SetMMDeviceEnumeration()) {
221 // Usage of MMDevice will fail on XP and lower.
222 LOG(WARNING
) << "MM device enumeration is not supported.";
226 AudioDeviceNames device_names
;
227 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
228 CheckDeviceNames(device_names
);
230 for (AudioDeviceNames::iterator i
= device_names
.begin();
231 i
!= device_names
.end(); ++i
) {
232 std::string converted_id
=
233 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
);
234 if (i
== device_names
.begin()) {
235 // The first in the list is the default device ID, which should not be
236 // changed when passed to PCMWaveInAudioInputStream.
237 EXPECT_EQ(i
->unique_id
, converted_id
);
239 // MMDevice-style device IDs should be converted to WaveIn-style device
241 EXPECT_NE(i
->unique_id
, converted_id
);
246 #endif // defined(OS_WIN)
248 #if defined(USE_PULSEAUDIO)
249 // On Linux, there are two implementations available and both can
250 // sometimes be tested on a single system. These tests specifically
253 TEST_F(AudioManagerTest
, EnumerateInputDevicesPulseaudio
) {
254 if (!CanRunInputTest())
257 audio_manager_
.reset(AudioManagerPulse::Create());
258 if (audio_manager_
.get()) {
259 AudioDeviceNames device_names
;
260 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
261 CheckDeviceNames(device_names
);
263 LOG(WARNING
) << "No pulseaudio on this system.";
267 TEST_F(AudioManagerTest
, EnumerateOutputDevicesPulseaudio
) {
268 if (!CanRunOutputTest())
271 audio_manager_
.reset(AudioManagerPulse::Create());
272 if (audio_manager_
.get()) {
273 AudioDeviceNames device_names
;
274 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
275 CheckDeviceNames(device_names
);
277 LOG(WARNING
) << "No pulseaudio on this system.";
280 #endif // defined(USE_PULSEAUDIO)
282 #if defined(USE_ALSA)
283 // On Linux, there are two implementations available and both can
284 // sometimes be tested on a single system. These tests specifically
287 TEST_F(AudioManagerTest
, EnumerateInputDevicesAlsa
) {
288 if (!CanRunInputTest())
291 VLOG(2) << "Testing AudioManagerLinux.";
292 audio_manager_
.reset(new AudioManagerLinux());
293 AudioDeviceNames device_names
;
294 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
295 CheckDeviceNames(device_names
);
298 TEST_F(AudioManagerTest
, EnumerateOutputDevicesAlsa
) {
299 if (!CanRunOutputTest())
302 VLOG(2) << "Testing AudioManagerLinux.";
303 audio_manager_
.reset(new AudioManagerLinux());
304 AudioDeviceNames device_names
;
305 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
306 CheckDeviceNames(device_names
);
308 #endif // defined(USE_ALSA)
310 TEST_F(AudioManagerTest
, GetDefaultOutputStreamParameters
) {
311 #if defined(OS_WIN) || defined(OS_MACOSX)
312 if (!CanRunInputTest())
315 AudioParameters params
= audio_manager_
->GetDefaultOutputStreamParameters();
316 EXPECT_TRUE(params
.IsValid());
317 #endif // defined(OS_WIN) || defined(OS_MACOSX)
320 TEST_F(AudioManagerTest
, GetAssociatedOutputDeviceID
) {
321 #if defined(OS_WIN) || defined(OS_MACOSX)
322 if (!CanRunInputTest() || !CanRunOutputTest())
325 AudioDeviceNames device_names
;
326 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
327 bool found_an_associated_device
= false;
328 for (AudioDeviceNames::iterator it
= device_names
.begin();
329 it
!= device_names
.end();
331 EXPECT_FALSE(it
->unique_id
.empty());
332 EXPECT_FALSE(it
->device_name
.empty());
333 std::string
output_device_id(
334 audio_manager_
->GetAssociatedOutputDeviceID(it
->unique_id
));
335 if (!output_device_id
.empty()) {
336 VLOG(2) << it
->unique_id
<< " matches with " << output_device_id
;
337 found_an_associated_device
= true;
341 EXPECT_TRUE(found_an_associated_device
);
342 #endif // defined(OS_WIN) || defined(OS_MACOSX)