// Copyright 2018 The Chromium OS 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_perception/cras_client_impl.h"

#include <syslog.h>

namespace {
// Max number of devices to probe.
const size_t MAX_IODEVS = 10;

// Max number of nodes to probe.
const size_t MAX_IONODES = 20;

// Callback when getting a new audio frame.
int OnAudioSamples(struct cras_client* client,
                   cras_stream_id_t stream_id,
                   uint8_t* captured_samples,
                   uint8_t* playback_samples,
                   unsigned int num_samples,
                   const struct timespec* captured_time,
                   const struct timespec* playback_time,
                   void* user_arg) {
  mri::CrasClientImpl* cras_client = (mri::CrasClientImpl*)user_arg;
  cras_client->ProcessAudioSamples(captured_samples, num_samples);
  return num_samples;
}

// Callback when getting audio capture error.
int OnAudioCaptureError(struct cras_client* client,
                        cras_stream_id_t stream_id,
                        int err,
                        void* arg) {
  syslog(LOG_ERR, "Audio capture error with code: %d.", err);
  return err;
}

}  // namespace

namespace mri {

CrasClientImpl::~CrasClientImpl() {
  Disconnect();
}

bool CrasClientImpl::Connect() {
  if (IsConnected()) {
    syslog(LOG_WARNING, "Client is already connected to CrAS server.");
    return true;
  }

  // Create and connect a client to the CrAS server. cras_helper_create_connect
  // returns 0 on success, or a negative error code on failure.
  int rc = cras_helper_create_connect(&client_);
  if (rc < 0) {
    syslog(LOG_ERR, "Failed to connect to CrAS server with error code: %d.",
           rc);
    DestroyClient();
    return false;
  }

  return true;
}

void CrasClientImpl::Disconnect() {
  StopAudioCapture();
  DestroyParams();
  DestroyClient();
}

bool CrasClientImpl::IsConnected() const {
  return client_ != nullptr;
}

bool CrasClientImpl::SetParams(const std::string& device_name,
                               unsigned int num_channels,
                               unsigned int block_size,
                               unsigned int frame_rate,
                               snd_pcm_format_t format) {
  DestroyParams();

  audio_format_ = cras_audio_format_create(format, frame_rate, num_channels);
  if (!audio_format_) {
    syslog(LOG_ERR, "Failed to create CrAS audio format.");
    DestroyParams();
    return false;
  }

  audio_capture_params_ = cras_client_unified_params_create(
      CRAS_STREAM_INPUT, block_size, CRAS_STREAM_TYPE_DEFAULT, 0, this,
      OnAudioSamples, OnAudioCaptureError, audio_format_);
  if (!audio_capture_params_) {
    syslog(LOG_ERR, "Failed to create CrAS audio capture format.");
    DestroyParams();
    return false;
  }

  device_name_ = device_name;
  return true;
}

bool CrasClientImpl::StartAudioCapture() {
  if (!IsConnected()) {
    return false;
  }

  if (HasAudioCaptureStarted()) {
    return true;
  }

  struct cras_iodev_info devs[MAX_IODEVS];
  struct cras_ionode_info nodes[MAX_IONODES];
  size_t num_devs = MAX_IODEVS;
  size_t num_nodes = MAX_IONODES;

  // Get the current list of input devices. Return 0 on success, -EINVAL if the
  // client isn't valid or isn't running.
  int rc = cras_client_get_input_devices(client_, devs, nodes, &num_devs,
                                         &num_nodes);
  if (rc != 0) {
    syslog(LOG_ERR, "Failed to query audio input devices.");
    return false;
  }

  // Search for the device that matches the given name.
  int dev_idx = NO_DEVICE;
  bool found_matched_device = false;
  for (int i = 0; !device_name_.empty() && i < num_devs; i++) {
    if (std::string(devs[i].name).find(device_name_) != std::string::npos) {
      dev_idx = devs[i].idx;
      syslog(LOG_INFO, "Found audio device: ID=%u, name=%s.", devs[i].idx,
             devs[i].name);
      found_matched_device = true;
      break;
    }
  }

  if (!device_name_.empty() && !found_matched_device) {
    syslog(LOG_ERR, "Failed to find matched audio input device: %s.",
           device_name_.c_str());
    return false;
  }

  // Create a pinned stream. Return 0 on success, or negative error code on
  // failure.
  cras_stream_id_t stream_id;
  rc = cras_client_add_pinned_stream(client_, dev_idx, &stream_id,
                                     audio_capture_params_);
  if (rc != 0) {
    syslog(LOG_ERR, "Failed to add pinned stream with error code: %d.", rc);
    return false;
  }

  has_audio_capture_started_ = true;
  return true;
}

void CrasClientImpl::StopAudioCapture() {
  if (IsConnected() && HasAudioCaptureStarted()) {
    cras_client_rm_stream(client_, stream_id_);
    has_audio_capture_started_ = false;
  }
}

bool CrasClientImpl::HasAudioCaptureStarted() const {
  return has_audio_capture_started_;
}

void CrasClientImpl::ProcessAudioSamples(const uint8_t* samples,
                                         unsigned int num_frames) {
  if (!audio_input_handler_) {
    return;
  }

  const int bytes_per_frame = cras_client_format_bytes_per_frame(audio_format_);
  const int total_bytes = bytes_per_frame * num_frames;
  audio_input_handler_(samples, total_bytes);
}

void CrasClientImpl::DestroyParams() {
  if (audio_format_) {
    cras_audio_format_destroy(audio_format_);
    audio_format_ = nullptr;
  }

  if (audio_capture_params_) {
    cras_client_stream_params_destroy(audio_capture_params_);
    audio_capture_params_ = nullptr;
  }
}

void CrasClientImpl::DestroyClient() {
  if (client_) {
    cras_client_destroy(client_);
    client_ = nullptr;
  }
}

}  // namespace mri
