// 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 "media/audio/win/waveout_output_win.h"

#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")

#include "base/basictypes.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_util.h"
#include "media/audio/win/audio_manager_win.h"

namespace media {

// Some general thoughts about the waveOut API which is badly documented :
// - We use CALLBACK_EVENT mode in which XP signals events such as buffer
//   releases.
// - We use RegisterWaitForSingleObject() so one of threads in thread pool
//   automatically calls our callback that feeds more data to Windows.
// - Windows does not provide a way to query if the device is playing or paused
//   thus it forces you to maintain state, which naturally is not exactly
//   synchronized to the actual device state.

// Sixty four MB is the maximum buffer size per AudioOutputStream.
static const uint32 kMaxOpenBufferSize = 1024 * 1024 * 64;

// See Also
// http://www.thx.com/consumer/home-entertainment/home-theater/surround-sound-speaker-set-up/
// http://en.wikipedia.org/wiki/Surround_sound

static const int kMaxChannelsToMask = 8;
static const unsigned int kChannelsToMask[kMaxChannelsToMask + 1] = {
  0,
  // 1 = Mono
  SPEAKER_FRONT_CENTER,
  // 2 = Stereo
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT,
  // 3 = Stereo + Center
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER,
  // 4 = Quad
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
  SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
  // 5 = 5.0
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
  SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
  // 6 = 5.1
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
  SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
  SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
  // 7 = 6.1
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
  SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
  SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
  SPEAKER_BACK_CENTER,
  // 8 = 7.1
  SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
  SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
  SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
  SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
  // TODO(fbarchard): Add additional masks for 7.2 and beyond.
};

inline size_t PCMWaveOutAudioOutputStream::BufferSize() const {
  // Round size of buffer up to the nearest 16 bytes.
  return (sizeof(WAVEHDR) + buffer_size_ + 15u) & static_cast<size_t>(~15);
}

inline WAVEHDR* PCMWaveOutAudioOutputStream::GetBuffer(int n) const {
  DCHECK_GE(n, 0);
  DCHECK_LT(n, num_buffers_);
  return reinterpret_cast<WAVEHDR*>(&buffers_[n * BufferSize()]);
}

PCMWaveOutAudioOutputStream::PCMWaveOutAudioOutputStream(
    AudioManagerWin* manager, const AudioParameters& params, int num_buffers,
    UINT device_id)
    : state_(PCMA_BRAND_NEW),
      manager_(manager),
      device_id_(device_id),
      waveout_(NULL),
      callback_(NULL),
      num_buffers_(num_buffers),
      buffer_size_(params.GetBytesPerBuffer()),
      volume_(1),
      channels_(params.channels()),
      pending_bytes_(0),
      waiting_handle_(NULL),
      audio_bus_(AudioBus::Create(params)) {
  format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  format_.Format.nChannels = params.channels();
  format_.Format.nSamplesPerSec = params.sample_rate();
  format_.Format.wBitsPerSample = params.bits_per_sample();
  format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX);
  // The next are computed from above.
  format_.Format.nBlockAlign = (format_.Format.nChannels *
                                format_.Format.wBitsPerSample) / 8;
  format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign *
                                   format_.Format.nSamplesPerSec;
  if (params.channels() > kMaxChannelsToMask) {
    format_.dwChannelMask = kChannelsToMask[kMaxChannelsToMask];
  } else {
    format_.dwChannelMask = kChannelsToMask[params.channels()];
  }
  format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  format_.Samples.wValidBitsPerSample = params.bits_per_sample();
}

PCMWaveOutAudioOutputStream::~PCMWaveOutAudioOutputStream() {
  DCHECK(NULL == waveout_);
}

bool PCMWaveOutAudioOutputStream::Open() {
  if (state_ != PCMA_BRAND_NEW)
    return false;
  if (BufferSize() * num_buffers_ > kMaxOpenBufferSize)
    return false;
  if (num_buffers_ < 2 || num_buffers_ > 5)
    return false;

  // Create buffer event.
  buffer_event_.Set(::CreateEvent(NULL,    // Security attributes.
                                  FALSE,   // It will auto-reset.
                                  FALSE,   // Initial state.
                                  NULL));  // No name.
  if (!buffer_event_.Get())
    return false;

  // Open the device.
  // We'll be getting buffer_event_ events when it's time to refill the buffer.
  MMRESULT result = ::waveOutOpen(
      &waveout_,
      device_id_,
      reinterpret_cast<LPCWAVEFORMATEX>(&format_),
      reinterpret_cast<DWORD_PTR>(buffer_event_.Get()),
      NULL,
      CALLBACK_EVENT);
  if (result != MMSYSERR_NOERROR)
    return false;

  SetupBuffers();
  state_ = PCMA_READY;
  return true;
}

void PCMWaveOutAudioOutputStream::SetupBuffers() {
  buffers_.reset(new char[BufferSize() * num_buffers_]);
  for (int ix = 0; ix != num_buffers_; ++ix) {
    WAVEHDR* buffer = GetBuffer(ix);
    buffer->lpData = reinterpret_cast<char*>(buffer) + sizeof(WAVEHDR);
    buffer->dwBufferLength = buffer_size_;
    buffer->dwBytesRecorded = 0;
    buffer->dwFlags = WHDR_DONE;
    buffer->dwLoops = 0;
    // Tell windows sound drivers about our buffers. Not documented what
    // this does but we can guess that causes the OS to keep a reference to
    // the memory pages so the driver can use them without worries.
    ::waveOutPrepareHeader(waveout_, buffer, sizeof(WAVEHDR));
  }
}

void PCMWaveOutAudioOutputStream::FreeBuffers() {
  for (int ix = 0; ix != num_buffers_; ++ix) {
    ::waveOutUnprepareHeader(waveout_, GetBuffer(ix), sizeof(WAVEHDR));
  }
  buffers_.reset(NULL);
}

// Initially we ask the source to fill up all audio buffers. If we don't do
// this then we would always get the driver callback when it is about to run
// samples and that would leave too little time to react.
void PCMWaveOutAudioOutputStream::Start(AudioSourceCallback* callback) {
  if (state_ != PCMA_READY)
    return;
  callback_ = callback;

  // Reset buffer event, it can be left in the arbitrary state if we
  // previously stopped the stream. Can happen because we are stopping
  // callbacks before stopping playback itself.
  if (!::ResetEvent(buffer_event_.Get())) {
    HandleError(MMSYSERR_ERROR);
    return;
  }

  // Start watching for buffer events.
  if (!::RegisterWaitForSingleObject(&waiting_handle_,
                                     buffer_event_.Get(),
                                     &BufferCallback,
                                     this,
                                     INFINITE,
                                     WT_EXECUTEDEFAULT)) {
    HandleError(MMSYSERR_ERROR);
    waiting_handle_ = NULL;
    return;
  }

  state_ = PCMA_PLAYING;

  // Queue the buffers.
  pending_bytes_ = 0;
  for (int ix = 0; ix != num_buffers_; ++ix) {
    WAVEHDR* buffer = GetBuffer(ix);
    // Caller waits for 1st packet to become available, but not for others,
    // so we wait for them here.
    if (ix != 0)
      callback_->WaitTillDataReady();
    QueueNextPacket(buffer);  // Read more data.
    pending_bytes_ += buffer->dwBufferLength;
  }

  // From now on |pending_bytes_| would be accessed by callback thread.
  // Most likely waveOutPause() or waveOutRestart() has its own memory barrier,
  // but issuing our own is safer.
  MemoryBarrier();

  MMRESULT result = ::waveOutPause(waveout_);
  if (result != MMSYSERR_NOERROR) {
    HandleError(result);
    return;
  }

  // Send the buffers to the audio driver. Note that the device is paused
  // so we avoid entering the callback method while still here.
  for (int ix = 0; ix != num_buffers_; ++ix) {
    result = ::waveOutWrite(waveout_, GetBuffer(ix), sizeof(WAVEHDR));
    if (result != MMSYSERR_NOERROR) {
      HandleError(result);
      break;
    }
  }
  result = ::waveOutRestart(waveout_);
  if (result != MMSYSERR_NOERROR) {
    HandleError(result);
    return;
  }
}

// Stopping is tricky if we want it be fast.
// For now just do it synchronously and avoid all the complexities.
// TODO(enal): if we want faster Stop() we can create singleton that keeps track
//             of all currently playing streams. Then you don't have to wait
//             till all callbacks are completed. Of course access to singleton
//             should be under its own lock, and checking the liveness and
//             acquiring the lock on stream should be done atomically.
void PCMWaveOutAudioOutputStream::Stop() {
  if (state_ != PCMA_PLAYING)
    return;
  state_ = PCMA_STOPPING;
  MemoryBarrier();

  // Stop watching for buffer event, wait till all the callbacks are complete.
  // Should be done before ::waveOutReset() call to avoid race condition when
  // callback that is currently active and already checked that stream is still
  // being played calls ::waveOutWrite() after ::waveOutReset() returns, later
  // causing ::waveOutClose() to fail with WAVERR_STILLPLAYING.
  // TODO(enal): that delays actual stopping of playback. Alternative can be
  //             to call ::waveOutReset() twice, once before
  //             ::UnregisterWaitEx() and once after.
  if (waiting_handle_) {
    if (!::UnregisterWaitEx(waiting_handle_, INVALID_HANDLE_VALUE)) {
      state_ = PCMA_PLAYING;
      HandleError(MMSYSERR_ERROR);
      return;
    }
    waiting_handle_ = NULL;
  }

  // Stop playback.
  MMRESULT res = ::waveOutReset(waveout_);
  if (res != MMSYSERR_NOERROR) {
    state_ = PCMA_PLAYING;
    HandleError(res);
    return;
  }

  // Wait for lock to ensure all outstanding callbacks have completed.
  base::AutoLock auto_lock(lock_);

  // waveOutReset() leaves buffers in the unpredictable state, causing
  // problems if we want to close, release, or reuse them. Fix the states.
  for (int ix = 0; ix != num_buffers_; ++ix) {
    GetBuffer(ix)->dwFlags = WHDR_PREPARED;
  }

  // Don't use callback after Stop().
  callback_ = NULL;

  state_ = PCMA_READY;
}

// We can Close in any state except that trying to close a stream that is
// playing Windows generates an error. We cannot propagate it to the source,
// as callback_ is set to NULL. Just print it and hope somebody somehow
// will find it...
void PCMWaveOutAudioOutputStream::Close() {
  Stop();  // Just to be sure. No-op if not playing.
  if (waveout_) {
    MMRESULT result = ::waveOutClose(waveout_);
    // If ::waveOutClose() fails we cannot just delete the stream, callback
    // may try to access it and would crash. Better to leak the stream.
    if (result != MMSYSERR_NOERROR) {
      HandleError(result);
      state_ = PCMA_PLAYING;
      return;
    }
    state_ = PCMA_CLOSED;
    waveout_ = NULL;
    FreeBuffers();
  }
  // Tell the audio manager that we have been released. This can result in
  // the manager destroying us in-place so this needs to be the last thing
  // we do on this function.
  manager_->ReleaseOutputStream(this);
}

void PCMWaveOutAudioOutputStream::SetVolume(double volume) {
  if (!waveout_)
    return;
  volume_ = static_cast<float>(volume);
}

void PCMWaveOutAudioOutputStream::GetVolume(double* volume) {
  if (!waveout_)
    return;
  *volume = volume_;
}

void PCMWaveOutAudioOutputStream::HandleError(MMRESULT error) {
  DLOG(WARNING) << "PCMWaveOutAudio error " << error;
  if (callback_)
    callback_->OnError(this, error);
}

void PCMWaveOutAudioOutputStream::QueueNextPacket(WAVEHDR *buffer) {
  DCHECK_EQ(channels_, format_.Format.nChannels);
  // Call the source which will fill our buffer with pleasant sounds and
  // return to us how many bytes were used.
  // TODO(fbarchard): Handle used 0 by queueing more.

  // HACK: Yield if Read() is called too often.  On older platforms which are
  // still using the WaveOut backend, we run into synchronization issues where
  // the renderer has not finished filling the shared memory when Read() is
  // called.  Reading too early will lead to clicks and pops.  See issues:
  // http://crbug.com/161307 and http://crbug.com/61022
  callback_->WaitTillDataReady();

  // TODO(sergeyu): Specify correct hardware delay for AudioBuffersState.
  int frames_filled = callback_->OnMoreData(
      audio_bus_.get(), AudioBuffersState(pending_bytes_, 0));
  uint32 used = frames_filled * audio_bus_->channels() *
      format_.Format.wBitsPerSample / 8;

  if (used <= buffer_size_) {
    // Note: If this ever changes to output raw float the data must be clipped
    // and sanitized since it may come from an untrusted source such as NaCl.
    audio_bus_->ToInterleaved(
        frames_filled, format_.Format.wBitsPerSample / 8, buffer->lpData);

    buffer->dwBufferLength = used * format_.Format.nChannels / channels_;
    media::AdjustVolume(buffer->lpData, used,
                        format_.Format.nChannels,
                        format_.Format.wBitsPerSample >> 3,
                        volume_);
  } else {
    HandleError(0);
    return;
  }
  buffer->dwFlags = WHDR_PREPARED;
}

// One of the threads in our thread pool asynchronously calls this function when
// buffer_event_ is signalled. Search through all the buffers looking for freed
// ones, fills them with data, and "feed" the Windows.
// Note: by searching through all the buffers we guarantee that we fill all the
//       buffers, even when "event loss" happens, i.e. if Windows signals event
//       when it did not flip into unsignaled state from the previous signal.
void NTAPI PCMWaveOutAudioOutputStream::BufferCallback(PVOID lpParameter,
                                                       BOOLEAN timer_fired) {
  TRACE_EVENT0("audio", "PCMWaveOutAudioOutputStream::BufferCallback");

  DCHECK(!timer_fired);
  PCMWaveOutAudioOutputStream* stream =
      reinterpret_cast<PCMWaveOutAudioOutputStream*>(lpParameter);

  // Lock the stream so callbacks do not interfere with each other.
  // Several callbacks can be called simultaneously by different threads in the
  // thread pool if some of the callbacks are slow, or system is very busy and
  // scheduled callbacks are not called on time.
  base::AutoLock auto_lock(stream->lock_);
  if (stream->state_ != PCMA_PLAYING)
    return;

  for (int ix = 0; ix != stream->num_buffers_; ++ix) {
    WAVEHDR* buffer = stream->GetBuffer(ix);
    if (buffer->dwFlags & WHDR_DONE) {
      // Before we queue the next packet, we need to adjust the number of
      // pending bytes since the last write to hardware.
      stream->pending_bytes_ -= buffer->dwBufferLength;
      stream->QueueNextPacket(buffer);

      // QueueNextPacket() can take a long time, especially if several of them
      // were called back-to-back. Check if we are stopping now.
      if (stream->state_ != PCMA_PLAYING)
        return;

      // Time to send the buffer to the audio driver. Since we are reusing
      // the same buffers we can get away without calling waveOutPrepareHeader.
      MMRESULT result = ::waveOutWrite(stream->waveout_,
                                       buffer,
                                       sizeof(WAVEHDR));
      if (result != MMSYSERR_NOERROR)
        stream->HandleError(result);
      stream->pending_bytes_ += buffer->dwBufferLength;
    }
  }
}

}  // namespace media
