/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "bt_btif_avrcp_audio_track"

#include "btif_avrcp_audio_track.h"

#include <base/logging.h>
#include <media/AudioTrack.h>
#include <utils/StrongPointer.h>

#include "bt_target.h"
#include "osi/include/log.h"

using namespace android;

typedef struct { android::sp<android::AudioTrack> track; } BtifAvrcpAudioTrack;

#if (DUMP_PCM_DATA == TRUE)
FILE* outputPcmSampleFile;
char outputFilename[50] = "/data/misc/bluedroid/output_sample.pcm";
#endif

void* BtifAvrcpAudioTrackCreate(int trackFreq, int channelType) {
  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btCreateTrack freq %d  channel %d ",
              __func__, trackFreq, channelType);
  sp<android::AudioTrack> track = new android::AudioTrack(
      AUDIO_STREAM_MUSIC, trackFreq, AUDIO_FORMAT_PCM_16_BIT, channelType,
      (size_t)0 /*frameCount*/, (audio_output_flags_t)AUDIO_OUTPUT_FLAG_FAST,
      NULL /*callback_t*/, NULL /*void* user*/, 0 /*notificationFrames*/,
      AUDIO_SESSION_ALLOCATE, android::AudioTrack::TRANSFER_SYNC);
  CHECK(track != NULL);

  BtifAvrcpAudioTrack* trackHolder = new BtifAvrcpAudioTrack;
  CHECK(trackHolder != NULL);
  trackHolder->track = track;

  if (trackHolder->track->initCheck() != 0) {
    return nullptr;
  }

#if (DUMP_PCM_DATA == TRUE)
  outputPcmSampleFile = fopen(outputFilename, "ab");
#endif
  trackHolder->track->setVolume(1, 1);
  return (void*)trackHolder;
}

void BtifAvrcpAudioTrackStart(void* handle) {
  if (handle == NULL) {
    LOG_ERROR(LOG_TAG, "%s: handle is null!", __func__);
    return;
  }
  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
  CHECK(trackHolder != NULL);
  CHECK(trackHolder->track != NULL);
  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
  trackHolder->track->start();
}

void BtifAvrcpAudioTrackStop(void* handle) {
  if (handle == NULL) {
    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
    return;
  }
  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
  if (trackHolder != NULL && trackHolder->track != NULL) {
    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
    trackHolder->track->stop();
  }
}

void BtifAvrcpAudioTrackDelete(void* handle) {
  if (handle == NULL) {
    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
    return;
  }
  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
  if (trackHolder != NULL && trackHolder->track != NULL) {
    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
    delete trackHolder;
  }

#if (DUMP_PCM_DATA == TRUE)
  if (outputPcmSampleFile) {
    fclose(outputPcmSampleFile);
  }
  outputPcmSampleFile = NULL;
#endif
}

void BtifAvrcpAudioTrackPause(void* handle) {
  if (handle == NULL) {
    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
    return;
  }
  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
  if (trackHolder != NULL && trackHolder->track != NULL) {
    LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btStartTrack", __func__);
    trackHolder->track->pause();
    trackHolder->track->flush();
  }
}

void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {
  if (handle == NULL) {
    LOG_DEBUG(LOG_TAG, "%s handle is null.", __func__);
    return;
  }
  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
  if (trackHolder != NULL && trackHolder->track != NULL) {
    LOG_VERBOSE(LOG_TAG, "%s set gain %f", __func__, gain);
    trackHolder->track->setVolume(gain);
  }
}

int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer,
                                 int bufferlen) {
  BtifAvrcpAudioTrack* trackHolder = static_cast<BtifAvrcpAudioTrack*>(handle);
  CHECK(trackHolder != NULL);
  CHECK(trackHolder->track != NULL);
  int retval = -1;
#if (DUMP_PCM_DATA == TRUE)
  if (outputPcmSampleFile) {
    fwrite((audioBuffer), 1, (size_t)bufferlen, outputPcmSampleFile);
  }
#endif
  retval = trackHolder->track->write(audioBuffer, (size_t)bufferlen);
  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btWriteData len = %d ret = %d", __func__,
              bufferlen, retval);
  return retval;
}
