1// Copyright (c) 2012 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. 4 5#include <cmath> 6 7#include "base/logging.h" 8#include "base/memory/scoped_ptr.h" 9#include "media/audio/audio_io.h" 10#include "media/audio/audio_manager_base.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13#if defined(OS_WIN) 14#include "base/win/scoped_com_initializer.h" 15#include "media/audio/win/core_audio_util_win.h" 16#endif 17 18namespace media { 19 20double GetVolumeAfterSetVolumeOnLinux(AudioInputStream* ais, 21 double target_volume) { 22 // SetVolume() is asynchronous on Linux, we need to keep trying until 23 // the SetVolume() operation is done. 24 static const int kTimesToRun = 10; 25 double volume = 0.0; 26 for (int i = 0; i < kTimesToRun; ++i) { 27 volume = ais->GetVolume(); 28 if (volume == target_volume) 29 break; 30 31 // Sleep 100ms to wait for the operation. 32 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); 33 } 34 35 return volume; 36} 37 38class AudioInputVolumeTest : public ::testing::Test { 39 protected: 40 AudioInputVolumeTest() 41 : audio_manager_(AudioManager::CreateForTesting()) 42#if defined(OS_WIN) 43 , com_init_(base::win::ScopedCOMInitializer::kMTA) 44#endif 45 { 46 } 47 48 bool CanRunAudioTests() { 49#if defined(OS_WIN) 50 // TODO(henrika): add support for volume control on Windows XP as well. 51 // For now, we might as well signal false already here to avoid running 52 // these tests on Windows XP. 53 if (!CoreAudioUtil::IsSupported()) 54 return false; 55#endif 56 if (!audio_manager_) 57 return false; 58 59 return audio_manager_->HasAudioInputDevices(); 60 } 61 62 // Helper method which checks if the stream has volume support. 63 bool HasDeviceVolumeControl(AudioInputStream* stream) { 64 if (!stream) 65 return false; 66 67 return (stream->GetMaxVolume() != 0.0); 68 } 69 70 AudioInputStream* CreateAndOpenStream(const std::string& device_id) { 71 const AudioParameters& params = 72 audio_manager_->GetInputStreamParameters(device_id); 73 AudioInputStream* ais = audio_manager_->MakeAudioInputStream( 74 params, device_id); 75 EXPECT_TRUE(NULL != ais); 76 77#if defined(OS_LINUX) || defined(OS_OPENBSD) 78 // Some linux devices do not support our settings, we may fail to open 79 // those devices. 80 if (!ais->Open()) { 81 // Default device should always be able to be opened. 82 EXPECT_TRUE(AudioManagerBase::kDefaultDeviceId != device_id); 83 ais->Close(); 84 ais = NULL; 85 } 86#elif defined(OS_WIN) || defined(OS_MACOSX) 87 EXPECT_TRUE(ais->Open()); 88#endif 89 90 return ais; 91 } 92 93 scoped_ptr<AudioManager> audio_manager_; 94 95#if defined(OS_WIN) 96 base::win::ScopedCOMInitializer com_init_; 97#endif 98}; 99 100#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 101// Currently failing on linux ARM bot: http://crbug/238490 102// Also flaky on x86_64: http://crbug/236936 103#define MAYBE_InputVolumeTest DISABLED_InputVolumeTest 104#else 105#define MAYBE_InputVolumeTest InputVolumeTest 106#endif 107 108TEST_F(AudioInputVolumeTest, MAYBE_InputVolumeTest) { 109 if (!CanRunAudioTests()) 110 return; 111 112 // Retrieve a list of all available input devices. 113 AudioDeviceNames device_names; 114 audio_manager_->GetAudioInputDeviceNames(&device_names); 115 if (device_names.empty()) { 116 LOG(WARNING) << "Could not find any available input device"; 117 return; 118 } 119 120 // Scan all available input devices and repeat the same test for all of them. 121 for (AudioDeviceNames::const_iterator it = device_names.begin(); 122 it != device_names.end(); 123 ++it) { 124 AudioInputStream* ais = CreateAndOpenStream(it->unique_id); 125 if (!ais) { 126 DLOG(WARNING) << "Failed to open stream for device " << it->unique_id; 127 continue; 128 } 129 130 if (!HasDeviceVolumeControl(ais)) { 131 DLOG(WARNING) << "Device: " << it->unique_id 132 << ", does not have volume control."; 133 ais->Close(); 134 continue; 135 } 136 137 double max_volume = ais->GetMaxVolume(); 138 EXPECT_GT(max_volume, 0.0); 139 140 // Store the current input-device volume level. 141 double original_volume = ais->GetVolume(); 142 EXPECT_GE(original_volume, 0.0); 143#if defined(OS_WIN) || defined(OS_MACOSX) 144 // Note that |original_volume| can be higher than |max_volume| on Linux. 145 EXPECT_LE(original_volume, max_volume); 146#endif 147 148 // Set the volume to the maxiumum level.. 149 ais->SetVolume(max_volume); 150 double current_volume = ais->GetVolume(); 151 EXPECT_EQ(max_volume, current_volume); 152 153 // Set the volume to the minimum level (=0). 154 double new_volume = 0.0; 155 ais->SetVolume(new_volume); 156#if defined(OS_LINUX) 157 current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume); 158#else 159 current_volume = ais->GetVolume(); 160#endif 161 EXPECT_EQ(new_volume, current_volume); 162 163 // Set the volume to the mid level (50% of max). 164 // Verify that the absolute error is small enough. 165 new_volume = max_volume / 2; 166 ais->SetVolume(new_volume); 167#if defined(OS_LINUX) 168 current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume); 169#else 170 current_volume = ais->GetVolume(); 171#endif 172 EXPECT_LT(current_volume, max_volume); 173 EXPECT_GT(current_volume, 0); 174 EXPECT_NEAR(current_volume, new_volume, 0.25 * max_volume); 175 176 // Restores the volume to the original value. 177 ais->SetVolume(original_volume); 178 current_volume = ais->GetVolume(); 179 EXPECT_EQ(original_volume, current_volume); 180 181 ais->Close(); 182 } 183} 184 185} // namespace media 186