/*
 * 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.
 */

#define LOG_TAG "NBAIO"
//#define LOG_NDEBUG 0

#include <utils/Log.h>
#include <media/nbaio/NBAIO.h>

namespace android {

size_t Format_frameSize(const NBAIO_Format& format)
{
    // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
    return Format_channelCount(format) * sizeof(short);
}

int Format_frameBitShift(const NBAIO_Format& format)
{
    // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
    // sizeof(short) == 2, so frame size == 1 << channels
    return Format_channelCount(format);
    // FIXME must return -1 for non-power of 2
}

const NBAIO_Format Format_Invalid = { 0 };

enum {
    Format_SR_8000,
    Format_SR_11025,
    Format_SR_16000,
    Format_SR_22050,
    Format_SR_24000,
    Format_SR_32000,
    Format_SR_44100,
    Format_SR_48000,
    Format_SR_Mask = 7
};

enum {
    Format_C_1 = 0x08,
    Format_C_2 = 0x10,
    Format_C_Mask = 0x18
};

unsigned Format_sampleRate(const NBAIO_Format& format)
{
    if (!Format_isValid(format)) {
        return 0;
    }
    switch (format.mPacked & Format_SR_Mask) {
    case Format_SR_8000:
        return 8000;
    case Format_SR_11025:
        return 11025;
    case Format_SR_16000:
        return 16000;
    case Format_SR_22050:
        return 22050;
    case Format_SR_24000:
        return 24000;
    case Format_SR_32000:
        return 32000;
    case Format_SR_44100:
        return 44100;
    case Format_SR_48000:
        return 48000;
    default:
        return 0;
    }
}

unsigned Format_channelCount(const NBAIO_Format& format)
{
    if (!Format_isValid(format)) {
        return 0;
    }
    switch (format.mPacked & Format_C_Mask) {
    case Format_C_1:
        return 1;
    case Format_C_2:
        return 2;
    default:
        return 0;
    }
}

NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount)
{
    unsigned format;
    switch (sampleRate) {
    case 8000:
        format = Format_SR_8000;
        break;
    case 11025:
        format = Format_SR_11025;
        break;
    case 16000:
        format = Format_SR_16000;
        break;
    case 22050:
        format = Format_SR_22050;
        break;
    case 24000:
        format = Format_SR_24000;
        break;
    case 32000:
        format = Format_SR_32000;
        break;
    case 44100:
        format = Format_SR_44100;
        break;
    case 48000:
        format = Format_SR_48000;
        break;
    default:
        return Format_Invalid;
    }
    switch (channelCount) {
    case 1:
        format |= Format_C_1;
        break;
    case 2:
        format |= Format_C_2;
        break;
    default:
        return Format_Invalid;
    }
    NBAIO_Format ret;
    ret.mPacked = format;
    return ret;
}

// This is a default implementation; it is expected that subclasses will optimize this.
ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
{
    if (!mNegotiated) {
        return (ssize_t) NEGOTIATE;
    }
    static const size_t maxBlock = 32;
    size_t frameSize = Format_frameSize(mFormat);
    ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
    // double guarantees alignment for stack similar to what malloc() gives for heap
    if (block == 0 || block > maxBlock) {
        block = maxBlock;
    }
    double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
    size_t accumulator = 0;
    while (accumulator < total) {
        size_t count = total - accumulator;
        if (count > block) {
            count = block;
        }
        ssize_t ret = via(user, buffer, count);
        if (ret > 0) {
            ALOG_ASSERT((size_t) ret <= count);
            size_t maxRet = ret;
            ret = write(buffer, maxRet);
            if (ret > 0) {
                ALOG_ASSERT((size_t) ret <= maxRet);
                accumulator += ret;
                continue;
            }
        }
        return accumulator > 0 ? accumulator : ret;
    }
    return accumulator;
}

// This is a default implementation; it is expected that subclasses will optimize this.
ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
                              int64_t readPTS, size_t block)
{
    if (!mNegotiated) {
        return (ssize_t) NEGOTIATE;
    }
    static const size_t maxBlock = 32;
    size_t frameSize = Format_frameSize(mFormat);
    ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
    // double guarantees alignment for stack similar to what malloc() gives for heap
    if (block == 0 || block > maxBlock) {
        block = maxBlock;
    }
    double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
    size_t accumulator = 0;
    while (accumulator < total) {
        size_t count = total - accumulator;
        if (count > block) {
            count = block;
        }
        ssize_t ret = read(buffer, count, readPTS);
        if (ret > 0) {
            ALOG_ASSERT((size_t) ret <= count);
            size_t maxRet = ret;
            ret = via(user, buffer, maxRet, readPTS);
            if (ret > 0) {
                ALOG_ASSERT((size_t) ret <= maxRet);
                accumulator += ret;
                continue;
            }
        }
        return accumulator > 0 ? accumulator : ret;
    }
    return accumulator;
}

// Default implementation that only accepts my mFormat
ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
                                  NBAIO_Format counterOffers[], size_t& numCounterOffers)
{
    ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
            offers, numOffers, counterOffers, numCounterOffers);
    if (Format_isValid(mFormat)) {
        for (size_t i = 0; i < numOffers; ++i) {
            if (Format_isEqual(offers[i], mFormat)) {
                mNegotiated = true;
                return i;
            }
        }
        if (numCounterOffers > 0) {
            counterOffers[0] = mFormat;
        }
        numCounterOffers = 1;
    } else {
        numCounterOffers = 0;
    }
    return (ssize_t) NEGOTIATE;
}

bool Format_isValid(const NBAIO_Format& format)
{
    return format.mPacked != Format_Invalid.mPacked;
}

bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
{
    return format1.mPacked == format2.mPacked;
}

}   // namespace android
