// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>
#include <mmsystem.h>

#include "base/basictypes.h"
#include "base/environment.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/test/test_timeouts.h"
#include "base/win/scoped_com_initializer.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/win/audio_low_latency_input_win.h"
#include "media/audio/win/core_audio_util_win.h"
#include "media/base/seekable_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::win::ScopedCOMInitializer;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using ::testing::Gt;
using ::testing::NotNull;

namespace media {

ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) {
  if (++*count >= limit) {
    loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
  }
}

class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
 public:
  MOCK_METHOD5(OnData, void(AudioInputStream* stream,
      const uint8* src, uint32 size,
      uint32 hardware_delay_bytes, double volume));
  MOCK_METHOD1(OnClose, void(AudioInputStream* stream));
  MOCK_METHOD2(OnError, void(AudioInputStream* stream, int code));
};

// This audio sink implementation should be used for manual tests only since
// the recorded data is stored on a raw binary data file.
class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
 public:
  // Allocate space for ~10 seconds of data @ 48kHz in stereo:
  // 2 bytes per sample, 2 channels, 10ms @ 48kHz, 10 seconds <=> 1920000 bytes.
  static const size_t kMaxBufferSize = 2 * 2 * 480 * 100 * 10;

  explicit WriteToFileAudioSink(const char* file_name)
      : buffer_(0, kMaxBufferSize),
        bytes_to_write_(0) {
    FilePath file_path;
    EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_path));
    file_path = file_path.AppendASCII(file_name);
    binary_file_ = file_util::OpenFile(file_path, "wb");
    DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file.";
    LOG(INFO) << ">> Output file: " << file_path.value()
              << " has been created.";
  }

  virtual ~WriteToFileAudioSink() {
    size_t bytes_written = 0;
    while (bytes_written < bytes_to_write_) {
      const uint8* chunk;
      int chunk_size;

      // Stop writing if no more data is available.
      if (!buffer_.GetCurrentChunk(&chunk, &chunk_size))
        break;

      // Write recorded data chunk to the file and prepare for next chunk.
      fwrite(chunk, 1, chunk_size, binary_file_);
      buffer_.Seek(chunk_size);
      bytes_written += chunk_size;
    }
    file_util::CloseFile(binary_file_);
  }

  // AudioInputStream::AudioInputCallback implementation.
  virtual void OnData(AudioInputStream* stream,
                      const uint8* src,
                      uint32 size,
                      uint32 hardware_delay_bytes,
                      double volume) {
    // Store data data in a temporary buffer to avoid making blocking
    // fwrite() calls in the audio callback. The complete buffer will be
    // written to file in the destructor.
    if (buffer_.Append(src, size)) {
      bytes_to_write_ += size;
    }
  }

  virtual void OnClose(AudioInputStream* stream) {}
  virtual void OnError(AudioInputStream* stream, int code) {}

 private:
  media::SeekableBuffer buffer_;
  FILE* binary_file_;
  size_t bytes_to_write_;
};

// Convenience method which ensures that we are not running on the build
// bots and that at least one valid input device can be found. We also
// verify that we are not running on XP since the low-latency (WASAPI-
// based) version requires Windows Vista or higher.
static bool CanRunAudioTests(AudioManager* audio_man) {
  if (!CoreAudioUtil::IsSupported()) {
    LOG(WARNING) << "This tests requires Windows Vista or higher.";
    return false;
  }
  // TODO(henrika): note that we use Wave today to query the number of
  // existing input devices.
  bool input = audio_man->HasAudioInputDevices();
  LOG_IF(WARNING, !input) << "No input device detected.";
  return input;
}

// Convenience method which creates a default AudioInputStream object but
// also allows the user to modify the default settings.
class AudioInputStreamWrapper {
 public:
  explicit AudioInputStreamWrapper(AudioManager* audio_manager)
      : com_init_(ScopedCOMInitializer::kMTA),
        audio_man_(audio_manager),
        format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
        channel_layout_(CHANNEL_LAYOUT_STEREO),
        bits_per_sample_(16) {
    // Use native/mixing sample rate and 10ms frame size as default.
    sample_rate_ = static_cast<int>(
        WASAPIAudioInputStream::HardwareSampleRate(
            AudioManagerBase::kDefaultDeviceId));
    samples_per_packet_ = sample_rate_ / 100;
  }

  ~AudioInputStreamWrapper() {}

  // Creates AudioInputStream object using default parameters.
  AudioInputStream* Create() {
    return CreateInputStream();
  }

  // Creates AudioInputStream object using non-default parameters where the
  // frame size is modified.
  AudioInputStream* Create(int samples_per_packet) {
    samples_per_packet_ = samples_per_packet;
    return CreateInputStream();
  }

  AudioParameters::Format format() const { return format_; }
  int channels() const {
    return ChannelLayoutToChannelCount(channel_layout_);
  }
  int bits_per_sample() const { return bits_per_sample_; }
  int sample_rate() const { return sample_rate_; }
  int samples_per_packet() const { return samples_per_packet_; }

 private:
  AudioInputStream* CreateInputStream() {
    AudioInputStream* ais = audio_man_->MakeAudioInputStream(
        AudioParameters(format_, channel_layout_, sample_rate_,
                        bits_per_sample_, samples_per_packet_),
                        AudioManagerBase::kDefaultDeviceId);
    EXPECT_TRUE(ais);
    return ais;
  }

  ScopedCOMInitializer com_init_;
  AudioManager* audio_man_;
  AudioParameters::Format format_;
  ChannelLayout channel_layout_;
  int bits_per_sample_;
  int sample_rate_;
  int samples_per_packet_;
};

// Convenience method which creates a default AudioInputStream object.
static AudioInputStream* CreateDefaultAudioInputStream(
    AudioManager* audio_manager) {
  AudioInputStreamWrapper aisw(audio_manager);
  AudioInputStream* ais = aisw.Create();
  return ais;
}

// Verify that we can retrieve the current hardware/mixing sample rate
// for all available input devices.
TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;

  ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);

  // Retrieve a list of all available input devices.
  media::AudioDeviceNames device_names;
  audio_manager->GetAudioInputDeviceNames(&device_names);

  // Scan all available input devices and repeat the same test for all of them.
  for (media::AudioDeviceNames::const_iterator it = device_names.begin();
       it != device_names.end(); ++it) {
    // Retrieve the hardware sample rate given a specified audio input device.
    // TODO(tommi): ensure that we don't have to cast here.
    int fs = static_cast<int>(WASAPIAudioInputStream::HardwareSampleRate(
        it->unique_id));
    EXPECT_GE(fs, 0);
  }
}

// Test Create(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;
  AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager.get());
  ais->Close();
}

// Test Open(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;
  AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager.get());
  EXPECT_TRUE(ais->Open());
  ais->Close();
}

// Test Open(), Start(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;
  AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager.get());
  EXPECT_TRUE(ais->Open());
  MockAudioInputCallback sink;
  ais->Start(&sink);
  EXPECT_CALL(sink, OnClose(ais))
      .Times(1);
  ais->Close();
}

// Test Open(), Start(), Stop(), Close() calling sequence.
TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;
  AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager.get());
  EXPECT_TRUE(ais->Open());
  MockAudioInputCallback sink;
  ais->Start(&sink);
  ais->Stop();
  EXPECT_CALL(sink, OnClose(ais))
      .Times(1);
  ais->Close();
}

// Test some additional calling sequences.
TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;
  AudioInputStream* ais = CreateDefaultAudioInputStream(audio_manager.get());
  WASAPIAudioInputStream* wais = static_cast<WASAPIAudioInputStream*>(ais);

  // Open(), Open() should fail the second time.
  EXPECT_TRUE(ais->Open());
  EXPECT_FALSE(ais->Open());

  MockAudioInputCallback sink;

  // Start(), Start() is a valid calling sequence (second call does nothing).
  ais->Start(&sink);
  EXPECT_TRUE(wais->started());
  ais->Start(&sink);
  EXPECT_TRUE(wais->started());

  // Stop(), Stop() is a valid calling sequence (second call does nothing).
  ais->Stop();
  EXPECT_FALSE(wais->started());
  ais->Stop();
  EXPECT_FALSE(wais->started());

  EXPECT_CALL(sink, OnClose(ais))
    .Times(1);
  ais->Close();
}

TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;

  int count = 0;
  MessageLoopForUI loop;

  // 10 ms packet size.

  // Create default WASAPI input stream which records in stereo using
  // the shared mixing rate. The default buffer size is 10ms.
  AudioInputStreamWrapper aisw(audio_manager.get());
  AudioInputStream* ais = aisw.Create();
  EXPECT_TRUE(ais->Open());

  MockAudioInputCallback sink;

  // Derive the expected size in bytes of each recorded packet.
  uint32 bytes_per_packet = aisw.channels() * aisw.samples_per_packet() *
      (aisw.bits_per_sample() / 8);

  // We use 10ms packets and will run the test until ten packets are received.
  // All should contain valid packets of the same size and a valid delay
  // estimate.
  EXPECT_CALL(sink, OnData(
      ais, NotNull(), bytes_per_packet, Gt(bytes_per_packet), _))
      .Times(AtLeast(10))
      .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
  ais->Start(&sink);
  loop.Run();
  ais->Stop();

  // Store current packet size (to be used in the subsequent tests).
  int samples_per_packet_10ms = aisw.samples_per_packet();

  EXPECT_CALL(sink, OnClose(ais))
      .Times(1);
  ais->Close();

  // 20 ms packet size.

  count = 0;
  ais = aisw.Create(2 * samples_per_packet_10ms);
  EXPECT_TRUE(ais->Open());
  bytes_per_packet = aisw.channels() * aisw.samples_per_packet() *
      (aisw.bits_per_sample() / 8);

  EXPECT_CALL(sink, OnData(
      ais, NotNull(), bytes_per_packet, Gt(bytes_per_packet), _))
      .Times(AtLeast(10))
      .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
  ais->Start(&sink);
  loop.Run();
  ais->Stop();

  EXPECT_CALL(sink, OnClose(ais))
      .Times(1);
  ais->Close();

  // 5 ms packet size.

  count = 0;
  ais = aisw.Create(samples_per_packet_10ms / 2);
  EXPECT_TRUE(ais->Open());
  bytes_per_packet = aisw.channels() * aisw.samples_per_packet() *
    (aisw.bits_per_sample() / 8);

  EXPECT_CALL(sink, OnData(
      ais, NotNull(), bytes_per_packet, Gt(bytes_per_packet), _))
      .Times(AtLeast(10))
      .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
  ais->Start(&sink);
  loop.Run();
  ais->Stop();

  EXPECT_CALL(sink, OnClose(ais))
      .Times(1);
  ais->Close();
}

// This test is intended for manual tests and should only be enabled
// when it is required to store the captured data on a local file.
// By default, GTest will print out YOU HAVE 1 DISABLED TEST.
// To include disabled tests in test execution, just invoke the test program
// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
// environment variable to a value greater than 0.
TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
  scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
  if (!CanRunAudioTests(audio_manager.get()))
    return;

  // Name of the output PCM file containing captured data. The output file
  // will be stored in the directory containing 'media_unittests.exe'.
  // Example of full name: \src\build\Debug\out_stereo_10sec.pcm.
  const char* file_name = "out_stereo_10sec.pcm";

  AudioInputStreamWrapper aisw(audio_manager.get());
  AudioInputStream* ais = aisw.Create();
  EXPECT_TRUE(ais->Open());

  LOG(INFO) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]";
  WriteToFileAudioSink file_sink(file_name);
  LOG(INFO) << ">> Speak into the default microphone while recording.";
  ais->Start(&file_sink);
  base::PlatformThread::Sleep(TestTimeouts::action_timeout());
  ais->Stop();
  LOG(INFO) << ">> Recording has stopped.";
  ais->Close();
}

}  // namespace media
