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

#include "base/logging.h"
#include "media/audio/android/audio_manager_android.h"

namespace media {

OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
                                         const AudioParameters& params)
    : audio_manager_(audio_manager),
      callback_(NULL),
      recorder_(NULL),
      simple_buffer_queue_(NULL),
      active_queue_(0),
      buffer_size_bytes_(0),
      started_(false) {
  format_.formatType = SL_DATAFORMAT_PCM;
  format_.numChannels = static_cast<SLuint32>(params.channels());
  // Provides sampling rate in milliHertz to OpenSLES.
  format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
  format_.bitsPerSample = params.bits_per_sample();
  format_.containerSize = params.bits_per_sample();
  format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
  if (format_.numChannels == 1)
    format_.channelMask = SL_SPEAKER_FRONT_CENTER;
  else if (format_.numChannels == 2)
    format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
  else
    NOTREACHED() << "Unsupported number of channels: " << format_.numChannels;

  buffer_size_bytes_ = params.GetBytesPerBuffer();

  memset(&audio_data_, 0, sizeof(audio_data_));
}

OpenSLESInputStream::~OpenSLESInputStream() {
  DCHECK(!recorder_object_.Get());
  DCHECK(!engine_object_.Get());
  DCHECK(!recorder_);
  DCHECK(!simple_buffer_queue_);
  DCHECK(!audio_data_[0]);
}

bool OpenSLESInputStream::Open() {
  if (engine_object_.Get())
    return false;

  if (!CreateRecorder())
    return false;

  SetupAudioBuffer();

  return true;
}

void OpenSLESInputStream::Start(AudioInputCallback* callback) {
  DCHECK(callback);
  DCHECK(recorder_);
  DCHECK(simple_buffer_queue_);
  if (started_)
    return;

  // Enable the flags before streaming.
  callback_ = callback;
  active_queue_ = 0;
  started_ = true;

  SLresult err = SL_RESULT_UNKNOWN_ERROR;
  // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling.
  for (int i = 0; i < kNumOfQueuesInBuffer - 1; ++i) {
    err = (*simple_buffer_queue_)->Enqueue(
        simple_buffer_queue_,
        audio_data_[i],
        buffer_size_bytes_);
    if (SL_RESULT_SUCCESS != err) {
      HandleError(err);
      return;
    }
  }

  // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|.
  err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err)
    HandleError(err);
}

void OpenSLESInputStream::Stop() {
  if (!started_)
    return;

  // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|.
  SLresult err = (*recorder_)->SetRecordState(recorder_,
                                              SL_RECORDSTATE_STOPPED);
  if (SL_RESULT_SUCCESS != err) {
    DLOG(WARNING) << "SetRecordState() failed to set the state to stop";
  }

  // Clear the buffer queue to get rid of old data when resuming recording.
  err = (*simple_buffer_queue_)->Clear(simple_buffer_queue_);
  if (SL_RESULT_SUCCESS != err) {
    DLOG(WARNING) << "Clear() failed to clear the buffer queue";
  }

  started_ = false;
}

void OpenSLESInputStream::Close() {
  // Stop the stream if it is still recording.
  Stop();

  // Explicitly free the player objects and invalidate their associated
  // interfaces. They have to be done in the correct order.
  recorder_object_.Reset();
  engine_object_.Reset();
  simple_buffer_queue_ = NULL;
  recorder_ = NULL;

  ReleaseAudioBuffer();

  audio_manager_->ReleaseInputStream(this);
}

double OpenSLESInputStream::GetMaxVolume() {
  NOTIMPLEMENTED();
  return 0.0;
}

void OpenSLESInputStream::SetVolume(double volume) {
  NOTIMPLEMENTED();
}

double OpenSLESInputStream::GetVolume() {
  NOTIMPLEMENTED();
  return 0.0;
}

void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
  NOTIMPLEMENTED();
}

bool OpenSLESInputStream::GetAutomaticGainControl() {
  NOTIMPLEMENTED();
  return false;
}

bool OpenSLESInputStream::CreateRecorder() {
  // Initializes the engine object with specific option. After working with the
  // object, we need to free the object and its resources.
  SLEngineOption option[] = {
    { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) }
  };
  SLresult err = slCreateEngine(engine_object_.Receive(),
                                1,
                                option,
                                0,
                                NULL,
                                NULL);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err)
    return false;

  // Realize the SL engine object in synchronous mode.
  err = engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err)
    return false;

  // Get the SL engine interface which is implicit.
  SLEngineItf engine;
  err = engine_object_->GetInterface(
      engine_object_.Get(), SL_IID_ENGINE, &engine);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err)
    return false;

  // Audio source configuration.
  SLDataLocator_IODevice mic_locator = {
    SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
    SL_DEFAULTDEVICEID_AUDIOINPUT, NULL
  };
  SLDataSource audio_source = { &mic_locator, NULL };

  // Audio sink configuration.
  SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
    SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // Locator type.
    static_cast<SLuint32>(kNumOfQueuesInBuffer)  // Number of buffers.
  };
  SLDataSink audio_sink = { &buffer_queue, &format_ };

  // Create an audio recorder.
  const SLuint32 number_of_interfaces = 1;
  const SLInterfaceID interface_id[number_of_interfaces] = {
    SL_IID_ANDROIDSIMPLEBUFFERQUEUE
  };
  const SLboolean interface_required[number_of_interfaces] = {
    SL_BOOLEAN_TRUE
  };
  err = (*engine)->CreateAudioRecorder(engine,
                                       recorder_object_.Receive(),
                                       &audio_source,
                                       &audio_sink,
                                       number_of_interfaces,
                                       interface_id,
                                       interface_required);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err) {
    DLOG(ERROR) << "CreateAudioRecorder failed with error code " << err;
    return false;
  }

  // Realize the recorder object in synchronous mode.
  err = recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err) {
    DLOG(ERROR) << "Recprder Realize() failed with error code " << err;
    return false;
  }

  // Get an implicit recorder interface.
  err = recorder_object_->GetInterface(recorder_object_.Get(),
                                       SL_IID_RECORD,
                                       &recorder_);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err)
    return false;

  // Get the simple buffer queue interface.
  err = recorder_object_->GetInterface(recorder_object_.Get(),
                                       SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                                       &simple_buffer_queue_);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);
  if (SL_RESULT_SUCCESS != err)
    return false;

  // Register the input callback for the simple buffer queue.
  // This callback will be called when receiving new data from the device.
  err = (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_,
                                                  SimpleBufferQueueCallback,
                                                  this);
  DCHECK_EQ(SL_RESULT_SUCCESS, err);

  return (SL_RESULT_SUCCESS == err);
}

void OpenSLESInputStream::SimpleBufferQueueCallback(
    SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) {
  OpenSLESInputStream* stream =
      reinterpret_cast<OpenSLESInputStream*>(instance);
  stream->ReadBufferQueue();
}

void OpenSLESInputStream::ReadBufferQueue() {
  if (!started_)
    return;

  // Get the enqueued buffer from the soundcard.
  SLresult err = (*simple_buffer_queue_)->Enqueue(
      simple_buffer_queue_,
      audio_data_[active_queue_],
      buffer_size_bytes_);
  if (SL_RESULT_SUCCESS != err)
    HandleError(err);

  // TODO(xians): Get an accurate delay estimation.
  callback_->OnData(this,
                    audio_data_[active_queue_],
                    buffer_size_bytes_,
                    buffer_size_bytes_,
                    0.0);

  active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer;
}

void OpenSLESInputStream::SetupAudioBuffer() {
  DCHECK(!audio_data_[0]);
  for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
    audio_data_[i] = new uint8[buffer_size_bytes_];
  }
}

void OpenSLESInputStream::ReleaseAudioBuffer() {
  if (audio_data_[0]) {
    for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
      delete [] audio_data_[i];
      audio_data_[i] = NULL;
    }
  }
}

void OpenSLESInputStream::HandleError(SLresult error) {
  DLOG(FATAL) << "OpenSLES error " << error;
  if (callback_)
    callback_->OnError(this, error);
}

}  // namespace media
