/*
 * Copyright (C) 2012 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.
 */

// TODO remove all the headers upto asound.h after removing pcm_drain hack
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <limits.h>
#include <linux/ioctl.h>
#define __force
#define __bitwise
#define __user
#include <sound/asound.h>

#include <string.h>
#include <tinyalsa/asoundlib.h>

#include "audio/AudioHardware.h"
#include "audio/Buffer.h"
#include "Log.h"

#include "audio/AudioPlaybackLocal.h"


AudioPlaybackLocal::AudioPlaybackLocal(int hwId)
    : mHwId(hwId),
      mPcmHandle(NULL)
{
    LOGV("AudioPlaybackLocal %x", (unsigned long)this);
}

AudioPlaybackLocal::~AudioPlaybackLocal()
{
    LOGV("~AudioPlaybackLocal %x", (unsigned long)this);
    releaseHw();
}

bool AudioPlaybackLocal::doPrepare(AudioHardware::SamplingRate samplingRate, int samplesInOneGo)
{
    releaseHw();

    struct pcm_config config;

    memset(&config, 0, sizeof(config));
    config.channels = 2;
    config.rate = samplingRate;
    config.period_size = 1024;
    config.period_count = 64;
    config.format = PCM_FORMAT_S16_LE;
    config.start_threshold = 0;
    config.stop_threshold =  0;
    config.silence_threshold = 0;

    mPcmHandle = pcm_open(mHwId, 0, PCM_OUT, &config);
    if (!mPcmHandle || !pcm_is_ready(mPcmHandle)) {
       LOGE("Unable to open PCM device(%d) (%s)\n", mHwId, pcm_get_error(mPcmHandle));
       return false;
    }

    mSamples = samplesInOneGo;
    mSizes = samplesInOneGo * 4; // stereo, 16bit

    return true;
}

bool AudioPlaybackLocal::doPlaybackOrRecord(android::sp<Buffer>& buffer)
{
    if (buffer->amountToHandle() < (size_t)mSizes) {
        mSizes = buffer->amountToHandle();
    }
    if (pcm_write(mPcmHandle, buffer->getUnhanledData(), mSizes)) {
        LOGE("AudioPlaybackLocal error %s", pcm_get_error(mPcmHandle));
        return false;
    }
    buffer->increaseHandled(mSizes);
    LOGV("AudioPlaybackLocal::doPlaybackOrRecord %d", buffer->amountHandled());
    return true;
}

void AudioPlaybackLocal::doStop()
{
    // TODO: remove when pcm_stop does pcm_drain
    // hack to have snd_pcm_drain equivalent
    struct pcm_ {
        int fd;
    };
    pcm_* pcm = (pcm_*)mPcmHandle;
    ioctl(pcm->fd, SNDRV_PCM_IOCTL_DRAIN);
    pcm_stop(mPcmHandle);
}

void AudioPlaybackLocal::releaseHw()
{
    if (mPcmHandle != NULL) {
        LOGV("releaseHw %x", (unsigned long)this);
        doStop();
        pcm_close(mPcmHandle);
        mPcmHandle = NULL;
    }
}
