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 18 namespace media { 19 20 double 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 38 class 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) && defined(ARCH_CPU_ARM_FAMILY) 101 // Currently failing on linux ARM bot: http://crbug/238490 102 #define MAYBE_InputVolumeTest DISABLED_InputVolumeTest 103 #else 104 #define MAYBE_InputVolumeTest InputVolumeTest 105 #endif 106 107 TEST_F(AudioInputVolumeTest, MAYBE_InputVolumeTest) { 108 if (!CanRunAudioTests()) 109 return; 110 111 // Retrieve a list of all available input devices. 112 AudioDeviceNames device_names; 113 audio_manager_->GetAudioInputDeviceNames(&device_names); 114 if (device_names.empty()) { 115 LOG(WARNING) << "Could not find any available input device"; 116 return; 117 } 118 119 // Scan all available input devices and repeat the same test for all of them. 120 for (AudioDeviceNames::const_iterator it = device_names.begin(); 121 it != device_names.end(); 122 ++it) { 123 AudioInputStream* ais = CreateAndOpenStream(it->unique_id); 124 if (!ais) { 125 DLOG(WARNING) << "Failed to open stream for device " << it->unique_id; 126 continue; 127 } 128 129 if (!HasDeviceVolumeControl(ais)) { 130 DLOG(WARNING) << "Device: " << it->unique_id 131 << ", does not have volume control."; 132 ais->Close(); 133 continue; 134 } 135 136 double max_volume = ais->GetMaxVolume(); 137 EXPECT_GT(max_volume, 0.0); 138 139 // Store the current input-device volume level. 140 double original_volume = ais->GetVolume(); 141 EXPECT_GE(original_volume, 0.0); 142 #if defined(OS_WIN) || defined(OS_MACOSX) 143 // Note that |original_volume| can be higher than |max_volume| on Linux. 144 EXPECT_LE(original_volume, max_volume); 145 #endif 146 147 // Set the volume to the maxiumum level.. 148 ais->SetVolume(max_volume); 149 double current_volume = ais->GetVolume(); 150 EXPECT_EQ(max_volume, current_volume); 151 152 // Set the volume to the mininum level (=0). 153 double new_volume = 0.0; 154 ais->SetVolume(new_volume); 155 #if defined(OS_LINUX) 156 current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume); 157 #else 158 current_volume = ais->GetVolume(); 159 #endif 160 EXPECT_EQ(new_volume, current_volume); 161 162 // Set the volume to the mid level (50% of max). 163 // Verify that the absolute error is small enough. 164 new_volume = max_volume / 2; 165 ais->SetVolume(new_volume); 166 #if defined(OS_LINUX) 167 current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume); 168 #else 169 current_volume = ais->GetVolume(); 170 #endif 171 EXPECT_LT(current_volume, max_volume); 172 EXPECT_GT(current_volume, 0); 173 EXPECT_NEAR(current_volume, new_volume, 0.25 * max_volume); 174 175 // Restores the volume to the original value. 176 ais->SetVolume(original_volume); 177 current_volume = ais->GetVolume(); 178 EXPECT_EQ(original_volume, current_volume); 179 180 ais->Close(); 181 } 182 } 183 184 } // namespace media 185