// 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.
//
// The object has one error state: |state_| == kInError.  When |state_| ==
// kInError, all public API functions will fail with an error (Start() will call
// the OnError() function on the callback immediately), or no-op themselves with
// the exception of Close().  Even if an error state has been entered, if Open()
// has previously returned successfully, Close() must be called.

#include "media/audio/linux/cras_output.h"

#include <cras_client.h>

#include "base/logging.h"
#include "media/audio/audio_util.h"
#include "media/audio/linux/alsa_util.h"
#include "media/audio/linux/audio_manager_linux.h"

namespace media {

// Helps make log messages readable.
std::ostream& operator<<(std::ostream& os,
                         CrasOutputStream::InternalState state) {
  switch (state) {
    case CrasOutputStream::kInError:
      os << "kInError";
      break;
    case CrasOutputStream::kCreated:
      os << "kCreated";
      break;
    case CrasOutputStream::kIsOpened:
      os << "kIsOpened";
      break;
    case CrasOutputStream::kIsPlaying:
      os << "kIsPlaying";
      break;
    case CrasOutputStream::kIsStopped:
      os << "kIsStopped";
      break;
    case CrasOutputStream::kIsClosed:
      os << "kIsClosed";
      break;
    default:
      os << "UnknownState";
      break;
  };
  return os;
}

// Overview of operation:
// 1) An object of CrasOutputStream is created by the AudioManager
// factory: audio_man->MakeAudioStream().
// 2) Next some thread will call Open(), at that point a client is created and
// configured for the correct format and sample rate.
// 3) Then Start(source) is called and a stream is added to the CRAS client
// which will create its own thread that periodically calls the source for more
// data as buffers are being consumed.
// 4) When finished Stop() is called, which is handled by stopping the stream.
// 5) Finally Close() is called. It cleans up and notifies the audio manager,
// which likely will destroy this object.

CrasOutputStream::CrasOutputStream(const AudioParameters& params,
                                   AudioManagerLinux* manager)
    : client_(NULL),
      stream_id_(0),
      samples_per_packet_(params.frames_per_buffer()),
      bytes_per_frame_(0),
      frame_rate_(params.sample_rate()),
      num_channels_(params.channels()),
      pcm_format_(alsa_util::BitsToFormat(params.bits_per_sample())),
      state_(kCreated),
      volume_(1.0),
      manager_(manager),
      source_callback_(NULL),
      audio_bus_(AudioBus::Create(params)) {
  // We must have a manager.
  DCHECK(manager_);

  // Sanity check input values.
  if (params.sample_rate() <= 0) {
    LOG(WARNING) << "Unsupported audio frequency.";
    TransitionTo(kInError);
    return;
  }

  if (AudioParameters::AUDIO_PCM_LINEAR != params.format() &&
      AudioParameters::AUDIO_PCM_LOW_LATENCY != params.format()) {
    LOG(WARNING) << "Unsupported audio format.";
    TransitionTo(kInError);
    return;
  }

  if (pcm_format_ == SND_PCM_FORMAT_UNKNOWN) {
    LOG(WARNING) << "Unsupported bits per sample: " << params.bits_per_sample();
    TransitionTo(kInError);
    return;
  }
}

CrasOutputStream::~CrasOutputStream() {
  InternalState current_state = state();
  DCHECK(current_state == kCreated ||
         current_state == kIsClosed ||
         current_state == kInError);
}

bool CrasOutputStream::Open() {
  if (!CanTransitionTo(kIsOpened)) {
    NOTREACHED() << "Invalid state: " << state();
    return false;
  }

  // We do not need to check if the transition was successful because
  // CanTransitionTo() was checked above, and it is assumed that this
  // object's public API is only called on one thread so the state cannot
  // transition out from under us.
  TransitionTo(kIsOpened);

  // Create the client and connect to the CRAS server.
  int err = cras_client_create(&client_);
  if (err < 0) {
    LOG(WARNING) << "Couldn't create CRAS client.\n";
    client_ = NULL;
    TransitionTo(kInError);
    return false;
  }
  err = cras_client_connect(client_);
  if (err) {
    LOG(WARNING) << "Couldn't connect CRAS client.\n";
    cras_client_destroy(client_);
    client_ = NULL;
    TransitionTo(kInError);
    return false;
  }
  // Then start running the client.
  err = cras_client_run_thread(client_);
  if (err) {
    LOG(WARNING) << "Couldn't run CRAS client.\n";
    cras_client_destroy(client_);
    client_ = NULL;
    TransitionTo(kInError);
    return false;
  }

  return true;
}

void CrasOutputStream::Close() {
  // Sanity Check that we can transition to closed.
  if (TransitionTo(kIsClosed) != kIsClosed) {
    NOTREACHED() << "Unable to transition Closed.";
    return;
  }

  if (client_) {
    cras_client_stop(client_);
    cras_client_destroy(client_);
    client_ = NULL;
  }

  // Signal to the manager that we're closed and can be removed.
  // Should be last call in the method as it deletes "this".
  manager_->ReleaseOutputStream(this);
}

void CrasOutputStream::Start(AudioSourceCallback* callback) {
  CHECK(callback);
  source_callback_ = callback;

  // Only start if we can enter the playing state.
  if (TransitionTo(kIsPlaying) != kIsPlaying)
    return;

  // Prepare |audio_format| and |stream_params| for the stream we
  // will create.
  cras_audio_format* audio_format = cras_audio_format_create(
      pcm_format_,
      frame_rate_,
      num_channels_);
  if (audio_format == NULL) {
    LOG(WARNING) << "Error setting up audio parameters.";
    TransitionTo(kInError);
    callback->OnError(this, -ENOMEM);
    return;
  }
  cras_stream_params* stream_params = cras_client_stream_params_create(
     CRAS_STREAM_OUTPUT,
     samples_per_packet_ * 2,  // Total latency.
     samples_per_packet_ / 2,  // Call back when this many left.
     samples_per_packet_,  // Call back with at least this much space.
     CRAS_STREAM_TYPE_DEFAULT,
     0,
     this,
     CrasOutputStream::PutSamples,
     CrasOutputStream::StreamError,
     audio_format);
  if (stream_params == NULL) {
    LOG(WARNING) << "Error setting up stream parameters.";
    TransitionTo(kInError);
    callback->OnError(this, -ENOMEM);
    cras_audio_format_destroy(audio_format);
    return;
  }

  // Before starting the stream, save the number of bytes in a frame for use in
  // the callback.
  bytes_per_frame_ = cras_client_format_bytes_per_frame(audio_format);

  // Adding the stream will start the audio callbacks requesting data.
  int err = cras_client_add_stream(client_, &stream_id_, stream_params);
  if (err < 0) {
    LOG(WARNING) << "Failed to add the stream";
    TransitionTo(kInError);
    callback->OnError(this, err);
    cras_audio_format_destroy(audio_format);
    cras_client_stream_params_destroy(stream_params);
    return;
  }

  // Set initial volume.
  cras_client_set_stream_volume(client_, stream_id_, volume_);

  // Done with config params.
  cras_audio_format_destroy(audio_format);
  cras_client_stream_params_destroy(stream_params);
}

void CrasOutputStream::Stop() {
  if (!client_)
    return;
  // Removing the stream from the client stops audio.
  cras_client_rm_stream(client_, stream_id_);
  TransitionTo(kIsStopped);
}

void CrasOutputStream::SetVolume(double volume) {
  if (!client_)
    return;
  volume_ = static_cast<float>(volume);
  cras_client_set_stream_volume(client_, stream_id_, volume_);
}

void CrasOutputStream::GetVolume(double* volume) {
  *volume = volume_;
}

// Static callback asking for samples.
int CrasOutputStream::PutSamples(cras_client* client,
                                 cras_stream_id_t stream_id,
                                 uint8* samples,
                                 size_t frames,
                                 const timespec* sample_ts,
                                 void* arg) {
  CrasOutputStream* me = static_cast<CrasOutputStream*>(arg);
  return me->Render(frames, samples, sample_ts);
}

// Static callback for stream errors.
int CrasOutputStream::StreamError(cras_client* client,
                                  cras_stream_id_t stream_id,
                                  int err,
                                  void* arg) {
  CrasOutputStream* me = static_cast<CrasOutputStream*>(arg);
  me->NotifyStreamError(err);
  return 0;
}

// Note this is run from a real time thread, so don't waste cycles here.
uint32 CrasOutputStream::Render(size_t frames,
                                uint8* buffer,
                                const timespec* sample_ts) {
  timespec latency_ts  = {0, 0};

  // Determine latency and pass that on to the source.
  cras_client_calc_playback_latency(sample_ts, &latency_ts);

  // Treat negative latency (if we are too slow to render) as 0.
  uint32 latency_usec;
  if (latency_ts.tv_sec < 0 || latency_ts.tv_nsec < 0) {
    latency_usec = 0;
  } else {
    latency_usec = (latency_ts.tv_sec * 1000000) +
        latency_ts.tv_nsec / 1000;
  }

  uint32 frames_latency = latency_usec * frame_rate_ / 1000000;
  uint32 bytes_latency = frames_latency * bytes_per_frame_;
  DCHECK_EQ(frames, static_cast<size_t>(audio_bus_->frames()));
  int frames_filled = source_callback_->OnMoreData(
      audio_bus_.get(), AudioBuffersState(0, bytes_latency));
  // 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, bytes_per_frame_ / num_channels_, buffer);
  return frames_filled;
}

void CrasOutputStream::NotifyStreamError(int err) {
  // This will remove the stream from the client.
  if (state_ == kIsClosed || state_ == kInError)
    return;  // Don't care about error if we aren't using it.
  TransitionTo(kInError);
  if (source_callback_)
    source_callback_->OnError(this, err);
}

bool CrasOutputStream::CanTransitionTo(InternalState to) {
  switch (state_) {
    case kCreated:
      return to == kIsOpened || to == kIsClosed || to == kInError;

    case kIsOpened:
      return to == kIsPlaying || to == kIsStopped ||
          to == kIsClosed || to == kInError;

    case kIsPlaying:
      return to == kIsPlaying || to == kIsStopped ||
          to == kIsClosed || to == kInError;

    case kIsStopped:
      return to == kIsPlaying || to == kIsStopped ||
          to == kIsClosed || to == kInError;

    case kInError:
      return to == kIsClosed || to == kInError;

    case kIsClosed:
      return false;
  }
  return false;
}

CrasOutputStream::InternalState
CrasOutputStream::TransitionTo(InternalState to) {
  if (!CanTransitionTo(to)) {
    state_ = kInError;
  } else {
    state_ = to;
  }
  return state_;
}

CrasOutputStream::InternalState CrasOutputStream::state() {
  return state_;
}

}  // namespace media
