/*
 * Copyright (C) 2008 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 "JetPlayer-C"

#include <utils/Log.h>
#include <media/JetPlayer.h>


namespace android
{

static const int MIX_NUM_BUFFERS = 4;
static const S_EAS_LIB_CONFIG* pLibConfig = NULL;

//-------------------------------------------------------------------------------------------------
JetPlayer::JetPlayer(void *javaJetPlayer, int maxTracks, int trackBufferSize) :
        mEventCallback(NULL),
        mJavaJetPlayerRef(javaJetPlayer),
        mTid(-1),
        mRender(false),
        mPaused(false),
        mMaxTracks(maxTracks),
        mEasData(NULL),
        mTrackBufferSize(trackBufferSize)
{
    ALOGV("JetPlayer constructor");
    mPreviousJetStatus.currentUserID = -1;
    mPreviousJetStatus.segmentRepeatCount = -1;
    mPreviousJetStatus.numQueuedSegments = -1;
    mPreviousJetStatus.paused = true;
}

//-------------------------------------------------------------------------------------------------
JetPlayer::~JetPlayer()
{
    ALOGV("~JetPlayer");
    release();

}

//-------------------------------------------------------------------------------------------------
int JetPlayer::init()
{
    //Mutex::Autolock lock(&mMutex);

    EAS_RESULT result;

    // retrieve the EAS library settings
    if (pLibConfig == NULL)
        pLibConfig = EAS_Config();
    if (pLibConfig == NULL) {
        ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
        return EAS_FAILURE;
    }

    // init the EAS library
    result = EAS_Init(&mEasData);
    if (result != EAS_SUCCESS) {
        ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
        mState = EAS_STATE_ERROR;
        return result;
    }
    // init the JET library with the default app event controller range
    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
    if (result != EAS_SUCCESS) {
        ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
        mState = EAS_STATE_ERROR;
        return result;
    }

    // create the output AudioTrack
    mAudioTrack = new AudioTrack();
    status_t status = mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
            pLibConfig->sampleRate,
            AUDIO_FORMAT_PCM_16_BIT,
            audio_channel_out_mask_from_count(pLibConfig->numChannels),
            (size_t) mTrackBufferSize,
            AUDIO_OUTPUT_FLAG_NONE);
    if (status != OK) {
        ALOGE("JetPlayer::init(): Error initializing JET library; AudioTrack error %d", status);
        mAudioTrack.clear();
        mState = EAS_STATE_ERROR;
        return EAS_FAILURE;
    }

    // create render and playback thread
    {
        Mutex::Autolock l(mMutex);
        ALOGV("JetPlayer::init(): trying to start render thread");
        mThread = new JetPlayerThread(this);
        mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
        mCondition.wait(mMutex);
    }
    if (mTid > 0) {
        // render thread started, we're ready
        ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
        mState = EAS_STATE_READY;
    } else {
        ALOGE("JetPlayer::init(): failed to start render thread.");
        mState = EAS_STATE_ERROR;
        return EAS_FAILURE;
    }

    return EAS_SUCCESS;
}

void JetPlayer::setEventCallback(jetevent_callback eventCallback)
{
    Mutex::Autolock l(mMutex);
    mEventCallback = eventCallback;
}

//-------------------------------------------------------------------------------------------------
int JetPlayer::release()
{
    ALOGV("JetPlayer::release()");
    Mutex::Autolock lock(mMutex);
    mPaused = true;
    mRender = false;
    if (mEasData) {
        JET_Pause(mEasData);
        JET_CloseFile(mEasData);
        JET_Shutdown(mEasData);
        EAS_Shutdown(mEasData);
    }
    mIoWrapper.clear();
    if (mAudioTrack != 0) {
        mAudioTrack->stop();
        mAudioTrack->flush();
        mAudioTrack.clear();
    }
    if (mAudioBuffer) {
        delete mAudioBuffer;
        mAudioBuffer = NULL;
    }
    mEasData = NULL;

    return EAS_SUCCESS;
}


//-------------------------------------------------------------------------------------------------
int JetPlayer::render() {
    EAS_RESULT result = EAS_FAILURE;
    EAS_I32 count;
    int temp;
    bool audioStarted = false;

    ALOGV("JetPlayer::render(): entering");

    // allocate render buffer
    mAudioBuffer =
        new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];

    // signal main thread that we started
    {
        Mutex::Autolock l(mMutex);
        mTid = gettid();
        ALOGV("JetPlayer::render(): render thread(%d) signal", mTid);
        mCondition.signal();
    }

    while (1) {

        mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------

        if (mEasData == NULL) {
            mMutex.unlock();
            ALOGV("JetPlayer::render(): NULL EAS data, exiting render.");
            goto threadExit;
        }

        // nothing to render, wait for client thread to wake us up
        while (!mRender)
        {
            ALOGV("JetPlayer::render(): signal wait");
            if (audioStarted) {
                mAudioTrack->pause();
                // we have to restart the playback once we start rendering again
                audioStarted = false;
            }
            mCondition.wait(mMutex);
            ALOGV("JetPlayer::render(): signal rx'd");
        }

        // render midi data into the input buffer
        int num_output = 0;
        EAS_PCM* p = mAudioBuffer;
        for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
            if (result != EAS_SUCCESS) {
                ALOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
            }
            p += count * pLibConfig->numChannels;
            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);

            // send events that were generated (if any) to the event callback
            fireEventsFromJetQueue();
        }

        // update playback state
        //ALOGV("JetPlayer::render(): updating state");
        JET_Status(mEasData, &mJetStatus);
        fireUpdateOnStatusChange();
        mPaused = mJetStatus.paused;

        mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------

        // check audio output track
        if (mAudioTrack == NULL) {
            ALOGE("JetPlayer::render(): output AudioTrack was not created");
            goto threadExit;
        }

        // Write data to the audio hardware
        //ALOGV("JetPlayer::render(): writing to audio output");
        if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
            ALOGE("JetPlayer::render(): Error in writing:%d",temp);
            return temp;
        }

        // start audio output if necessary
        if (!audioStarted) {
            ALOGV("JetPlayer::render(): starting audio playback");
            mAudioTrack->start();
            audioStarted = true;
        }

    }//while (1)

threadExit:
    if (mAudioTrack != NULL) {
        mAudioTrack->stop();
        mAudioTrack->flush();
    }
    delete [] mAudioBuffer;
    mAudioBuffer = NULL;
    mMutex.lock();
    mTid = -1;
    mCondition.signal();
    mMutex.unlock();
    return result;
}


//-------------------------------------------------------------------------------------------------
// fire up an update if any of the status fields has changed
// precondition: mMutex locked
void JetPlayer::fireUpdateOnStatusChange()
{
    if ( (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
       ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
        if (mEventCallback)  {
            mEventCallback(
                JetPlayer::JET_USERID_UPDATE,
                mJetStatus.currentUserID,
                mJetStatus.segmentRepeatCount,
                mJavaJetPlayerRef);
        }
        mPreviousJetStatus.currentUserID      = mJetStatus.currentUserID;
        mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
    }

    if (mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
        if (mEventCallback)  {
            mEventCallback(
                JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
                mJetStatus.numQueuedSegments,
                -1,
                mJavaJetPlayerRef);
        }
        mPreviousJetStatus.numQueuedSegments  = mJetStatus.numQueuedSegments;
    }

    if (mJetStatus.paused != mPreviousJetStatus.paused) {
        if (mEventCallback)  {
            mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
                mJetStatus.paused,
                -1,
                mJavaJetPlayerRef);
        }
        mPreviousJetStatus.paused = mJetStatus.paused;
    }

}


//-------------------------------------------------------------------------------------------------
// fire up all the JET events in the JET engine queue (until the queue is empty)
// precondition: mMutex locked
void JetPlayer::fireEventsFromJetQueue()
{
    if (!mEventCallback) {
        // no callback, just empty the event queue
        while (JET_GetEvent(mEasData, NULL, NULL)) { }
        return;
    }

    EAS_U32 rawEvent;
    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
        mEventCallback(
            JetPlayer::JET_EVENT,
            rawEvent,
            -1,
            mJavaJetPlayerRef);
    }
}


//-------------------------------------------------------------------------------------------------
int JetPlayer::loadFromFile(const char* path)
{
    ALOGV("JetPlayer::loadFromFile(): path=%s", path);

    Mutex::Autolock lock(mMutex);

    mIoWrapper = new MidiIoWrapper(path);

    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
    if (result != EAS_SUCCESS)
        mState = EAS_STATE_ERROR;
    else
        mState = EAS_STATE_OPEN;
    return( result );
}


//-------------------------------------------------------------------------------------------------
int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
{
    ALOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);

    Mutex::Autolock lock(mMutex);

    mIoWrapper = new MidiIoWrapper(fd, offset, length);

    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
    if (result != EAS_SUCCESS)
        mState = EAS_STATE_ERROR;
    else
        mState = EAS_STATE_OPEN;
    return( result );
}


//-------------------------------------------------------------------------------------------------
int JetPlayer::closeFile()
{
    Mutex::Autolock lock(mMutex);
    return JET_CloseFile(mEasData);
}


//-------------------------------------------------------------------------------------------------
int JetPlayer::play()
{
    ALOGV("JetPlayer::play(): entering");
    Mutex::Autolock lock(mMutex);

    EAS_RESULT result = JET_Play(mEasData);

    mPaused = false;
    mRender = true;

    JET_Status(mEasData, &mJetStatus);
    this->dumpJetStatus(&mJetStatus);

    fireUpdateOnStatusChange();

    // wake up render thread
    ALOGV("JetPlayer::play(): wakeup render thread");
    mCondition.signal();

    return result;
}

//-------------------------------------------------------------------------------------------------
int JetPlayer::pause()
{
    Mutex::Autolock lock(mMutex);
    mPaused = true;
    EAS_RESULT result = JET_Pause(mEasData);

    mRender = false;

    JET_Status(mEasData, &mJetStatus);
    this->dumpJetStatus(&mJetStatus);
    fireUpdateOnStatusChange();


    return result;
}


//-------------------------------------------------------------------------------------------------
int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
        EAS_U32 muteFlags, EAS_U8 userID)
{
    ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
        segmentNum, libNum, repeatCount, transpose);
    Mutex::Autolock lock(mMutex);
    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags,
            userID);
}

//-------------------------------------------------------------------------------------------------
int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
{
    Mutex::Autolock lock(mMutex);
    return JET_SetMuteFlags(mEasData, muteFlags, sync);
}

//-------------------------------------------------------------------------------------------------
int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
{
    Mutex::Autolock lock(mMutex);
    return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
}

//-------------------------------------------------------------------------------------------------
int JetPlayer::triggerClip(int clipId)
{
    ALOGV("JetPlayer::triggerClip clipId=%d", clipId);
    Mutex::Autolock lock(mMutex);
    return JET_TriggerClip(mEasData, clipId);
}

//-------------------------------------------------------------------------------------------------
int JetPlayer::clearQueue()
{
    ALOGV("JetPlayer::clearQueue");
    Mutex::Autolock lock(mMutex);
    return JET_Clear_Queue(mEasData);
}

//-------------------------------------------------------------------------------------------------
void JetPlayer::dump()
{
}

void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
{
    if (pJetStatus!=NULL)
        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d "
                "paused=%d",
                pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
                pJetStatus->numQueuedSegments, pJetStatus->paused);
    else
        ALOGE(">> JET player status is NULL");
}


} // end namespace android
