// 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/audio_output_dispatcher_impl.h"

#include <algorithm>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_output_proxy.h"
#include "media/audio/audio_util.h"

namespace media {

AudioOutputDispatcherImpl::AudioOutputDispatcherImpl(
    AudioManager* audio_manager,
    const AudioParameters& params,
    const base::TimeDelta& close_delay)
    : AudioOutputDispatcher(audio_manager, params),
      pause_delay_(base::TimeDelta::FromMilliseconds(
          2 * params.frames_per_buffer() *
          base::Time::kMillisecondsPerSecond / params.sample_rate())),
      paused_proxies_(0),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)),
      close_timer_(FROM_HERE,
                   close_delay,
                   weak_this_.GetWeakPtr(),
                   &AudioOutputDispatcherImpl::ClosePendingStreams) {
}

AudioOutputDispatcherImpl::~AudioOutputDispatcherImpl() {
  DCHECK(proxy_to_physical_map_.empty());
  DCHECK(idle_streams_.empty());
  DCHECK(pausing_streams_.empty());
}

bool AudioOutputDispatcherImpl::OpenStream() {
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  paused_proxies_++;

  // Ensure that there is at least one open stream.
  if (idle_streams_.empty() && !CreateAndOpenStream()) {
    paused_proxies_--;
    return false;
  }

  close_timer_.Reset();
  return true;
}

bool AudioOutputDispatcherImpl::StartStream(
    AudioOutputStream::AudioSourceCallback* callback,
    AudioOutputProxy* stream_proxy) {
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  if (idle_streams_.empty() && !CreateAndOpenStream())
    return false;

  AudioOutputStream* physical_stream = idle_streams_.back();
  DCHECK(physical_stream);
  idle_streams_.pop_back();

  DCHECK_GT(paused_proxies_, 0u);
  --paused_proxies_;

  close_timer_.Reset();

  // Schedule task to allocate streams for other proxies if we need to.
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &AudioOutputDispatcherImpl::OpenTask, weak_this_.GetWeakPtr()));

  double volume = 0;
  stream_proxy->GetVolume(&volume);
  physical_stream->SetVolume(volume);
  physical_stream->Start(callback);
  proxy_to_physical_map_[stream_proxy] = physical_stream;
  return true;
}

void AudioOutputDispatcherImpl::StopStream(AudioOutputProxy* stream_proxy) {
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy);
  DCHECK(it != proxy_to_physical_map_.end());
  AudioOutputStream* physical_stream = it->second;
  proxy_to_physical_map_.erase(it);

  physical_stream->Stop();

  ++paused_proxies_;

  pausing_streams_.push_front(physical_stream);

  // Don't recycle stream until two buffers worth of time has elapsed.
  message_loop_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&AudioOutputDispatcherImpl::StopStreamTask,
                 weak_this_.GetWeakPtr()),
      pause_delay_);
}

void AudioOutputDispatcherImpl::StreamVolumeSet(AudioOutputProxy* stream_proxy,
                                                double volume) {
  DCHECK_EQ(MessageLoop::current(), message_loop_);
  AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy);
  if (it != proxy_to_physical_map_.end()) {
    AudioOutputStream* physical_stream = it->second;
    physical_stream->SetVolume(volume);
  }
}

void AudioOutputDispatcherImpl::StopStreamTask() {
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  if (pausing_streams_.empty())
    return;

  AudioOutputStream* stream = pausing_streams_.back();
  pausing_streams_.pop_back();
  idle_streams_.push_back(stream);
  close_timer_.Reset();
}

void AudioOutputDispatcherImpl::CloseStream(AudioOutputProxy* stream_proxy) {
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  while (!pausing_streams_.empty()) {
    idle_streams_.push_back(pausing_streams_.back());
    pausing_streams_.pop_back();
  }

  DCHECK_GT(paused_proxies_, 0u);
  paused_proxies_--;

  while (idle_streams_.size() > paused_proxies_) {
    idle_streams_.back()->Close();
    idle_streams_.pop_back();
  }
}

void AudioOutputDispatcherImpl::Shutdown() {
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  // Cancel any pending tasks to close paused streams or create new ones.
  weak_this_.InvalidateWeakPtrs();

  // No AudioOutputProxy objects should hold a reference to us when we get
  // to this stage.
  DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference";

  AudioOutputStreamList::iterator it = idle_streams_.begin();
  for (; it != idle_streams_.end(); ++it)
    (*it)->Close();
  idle_streams_.clear();

  it = pausing_streams_.begin();
  for (; it != pausing_streams_.end(); ++it)
    (*it)->Close();
  pausing_streams_.clear();
}

bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
  DCHECK_EQ(MessageLoop::current(), message_loop_);
  AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(params_);
  if (!stream)
    return false;

  if (!stream->Open()) {
    stream->Close();
    return false;
  }
  idle_streams_.push_back(stream);
  return true;
}

void AudioOutputDispatcherImpl::OpenTask() {
  DCHECK_EQ(MessageLoop::current(), message_loop_);
  // Make sure that we have at least one stream allocated if there
  // are paused streams.
  if (paused_proxies_ > 0 && idle_streams_.empty() &&
      pausing_streams_.empty()) {
    CreateAndOpenStream();
  }

  close_timer_.Reset();
}

// This method is called by |close_timer_|.
void AudioOutputDispatcherImpl::ClosePendingStreams() {
  DCHECK_EQ(MessageLoop::current(), message_loop_);
  while (!idle_streams_.empty()) {
    idle_streams_.back()->Close();
    idle_streams_.pop_back();
  }
}

}  // namespace media
