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) 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 108 TEST_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