// Copyright (c) 2010 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.
//
// Implementation of audio output using the Linux ALSA interface.

#include <fcntl.h>
#include <stdio.h>

#include <alsa/asoundlib.h>

#include "audio_output.h"
#include "log.h"
#include "threading.h"

namespace {

bool isDeviceReady() {
  snd_ctl_card_info_t *card_info;
  snd_ctl_card_info_alloca(&card_info);

  snd_pcm_info_t *pcm_info;
  snd_pcm_info_alloca(&pcm_info);

  int valid_playback_devices = 0;
  int card_index = -1;

  while(snd_card_next(&card_index) == 0 && card_index >= 0) {
    char card_name[20];
    snprintf(card_name, sizeof(card_name), "hw:%d", card_index);
    LOG(INFO) << "Checking ALSA sound card " << card_name;

    snd_ctl_t *ctl;
    if(snd_ctl_open(&ctl, card_name, 0) < 0)
      continue;

    snd_ctl_card_info(ctl, card_info);

    int dev_index = -1;
    while (snd_ctl_pcm_next_device(ctl, &dev_index) == 0 && dev_index >= 0) {
      char device_name[30];
      snprintf(device_name, sizeof(device_name),
               "hw:%d,%d", card_index, dev_index);
      LOG(INFO) << "Checking ALSA sound device " << device_name;

      /* Obtain info about this particular device */
      snd_pcm_info_set_device(pcm_info, dev_index);
      snd_pcm_info_set_subdevice(pcm_info, 0);
      snd_pcm_info_set_stream(pcm_info, SND_PCM_STREAM_PLAYBACK);
      if (snd_ctl_pcm_info(ctl, pcm_info) >= 0) {
        LOG(INFO) << "    Valid playback device: " << device_name;
        valid_playback_devices++;
      }
    }
    snd_ctl_close(ctl);
  }

  LOG(INFO) << "Total valid playback devices: " << valid_playback_devices;
  if (valid_playback_devices == 0) {
    return false;
  }
  return true;
}

}

namespace speech_synthesis {

class LinuxAlsaAudioOutput : public AudioOutput, public Runnable {
 public:
  explicit LinuxAlsaAudioOutput(Threading* threading)
      : threading_(threading),
        provider_(NULL) {
  }

  bool Init(AudioProvider *provider) {
    if (!provider) {
      LOG(ERROR) << "An AudioProvider is required.\n";
      return false;
    }

    if (provider_) {
      return true;
    }

    if (!isDeviceReady()) {
      return false;
    }
    
    int err;
    if ((err = snd_pcm_open(&pcm_out_handle_,
                            "default",
                            SND_PCM_STREAM_PLAYBACK,
                            0)) < 0) {
      LOG(INFO) << "Can't open wave output: " << snd_strerror(err) << "\n";
      return false;
    }

    sample_rate_ = 44100;
    channel_count_ = 1;
    int soft_resample = 1;
    unsigned int latency_us = 50000;
    if ((err = snd_pcm_set_params(pcm_out_handle_,
                                  SND_PCM_FORMAT_S16_LE,
                                  SND_PCM_ACCESS_RW_INTERLEAVED,
                                  channel_count_,
                                  sample_rate_,
                                  soft_resample,
                                  latency_us)) < 0) {
      LOG(INFO) << "Can't set pcm parameters " << snd_strerror(err);
      return false;
    }

    snd_pcm_uframes_t buffer_size = 0;
    snd_pcm_uframes_t period_size = 0;
    if ((err = snd_pcm_get_params(pcm_out_handle_, &buffer_size, &period_size))
        < 0) {
      LOG(INFO) << "Can't get pcm parameters: " << snd_strerror(err);
      return false;
    }

    chunk_size_ = period_size;
    total_buffer_size_ = buffer_size;

    if ((err = snd_pcm_prepare(pcm_out_handle_)) < 0) {
      LOG(INFO) << "Can't prepare: " << snd_strerror(err) << "\n";
      return false;
    }

    keep_running_ = true;
    provider_ = provider;
    return true;
  }

  virtual ~LinuxAlsaAudioOutput() {
    StopAudio();
  }

  virtual void StartAudio() {
    thread_ = threading_->StartJoinableThread(this);
  }

  virtual void StopAudio() {
    keep_running_ = false;
    if (thread_) {
      thread_->Join();
      thread_ = NULL;
    }

    snd_pcm_close(pcm_out_handle_);
  }

  virtual int GetSampleRate() {
    return 44100;
  }

  virtual int GetChannelCount() {
    return 1;
  }

  virtual int GetChunkSize() {
    return chunk_size_;
  }

  virtual int GetTotalBufferSize() {
    return total_buffer_size_;
  }

  virtual void Run() {
    const int chunk_size = GetChunkSize();
    int16_t* chunk = new int16_t[chunk_size];

    if (!provider_) {
      LOG(ERROR) << "Error: audio output was never initialized.\n";
      return;
    }

    LOG(INFO) << "In audio thread\n";
    while (keep_running_) {
      if (!provider_->FillAudioBuffer(chunk, chunk_size)) {
        LOG(INFO) << "Could not fill audio buffer\n";
        break;
      }

      int err = snd_pcm_writei(pcm_out_handle_,
                               static_cast<void *>(chunk),
                               static_cast<snd_pcm_uframes_t>(chunk_size));
      if (err < 0) {
        LOG(INFO) << "Write error: " << err << snd_strerror(err) << "\n";
        do {
          sleep(1);
          LOG(INFO) << "Attempting to recover audio";
        } while (keep_running_ &&
                 0 != snd_pcm_recover(pcm_out_handle_, err, 0));
      }
    }

    delete[] chunk;
  }

 private:
  volatile bool keep_running_;
  Threading* threading_;
  AudioProvider* provider_;
  Thread* thread_;
  snd_pcm_t *pcm_out_handle_;
  int sample_rate_;
  int channel_count_;
  int chunk_size_;
  int total_buffer_size_;
};

AudioOutput* AudioOutput::Create(Threading* threading) {
  return new LinuxAlsaAudioOutput(threading);
}

}  // namespace speech_synthesis

