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) && 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