Home | History | Annotate | Download | only in audio
      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