MidiFile.cpp revision 64760240f931714858a59c1579f07264d7182ba2
189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/* MidiFile.cpp
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2007, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "MidiFile"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include "utils/Log.h"
2189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <stdio.h>
2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <assert.h>
2489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <limits.h>
2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <unistd.h>
2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <fcntl.h>
2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sched.h>
2889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/threads.h>
2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <libsonivox/eas_reverb.h>
3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/types.h>
3189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/stat.h>
3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3364760240f931714858a59c1579f07264d7182ba2Dima Zavin#include <system/audio.h>
34fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin
3589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include "MidiFile.h"
3689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#ifdef HAVE_GETTID
3889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic pid_t myTid() { return gettid(); }
3989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#else
4089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic pid_t myTid() { return getpid(); }
4189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#endif
4289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ----------------------------------------------------------------------------
4489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
4689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ----------------------------------------------------------------------------
4889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// The midi engine buffers are a bit small (128 frames), so we batch them up
5089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic const int NUM_BUFFERS = 4;
5189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// TODO: Determine appropriate return codes
5389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic status_t ERROR_NOT_OPEN = -1;
5489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic status_t ERROR_OPEN_FAILED = -2;
5589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic status_t ERROR_EAS_FAILURE = -3;
5689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic status_t ERROR_ALLOCATE_FAILED = -4;
5789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatic const S_EAS_LIB_CONFIG* pLibConfig = NULL;
5989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMidiFile::MidiFile() :
6189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
6289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
63fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    mStreamType(AUDIO_STREAM_MUSIC), mLoop(false), mExit(false),
6489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPaused(false), mRender(false), mTid(-1)
6589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("constructor");
6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.path = NULL;
6989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.fd = -1;
7089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.offset = 0;
7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.length = 0;
7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // get the library configuration and do sanity check
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (pLibConfig == NULL)
7589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        pLibConfig = EAS_Config();
7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("EAS library/header mismatch");
7889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        goto Failed;
7989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // initialize EAS library
8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (EAS_Init(&mEasData) != EAS_SUCCESS) {
8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("EAS_Init failed");
8489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        goto Failed;
8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
8689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // select reverb preset and enable
8889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
8989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
9089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // create playback thread
9289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    {
9389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        Mutex::Autolock l(mMutex);
94577ba8a1ae29cd2ca3b6103ae51530111d3e9b22Dave Sparks        createThreadEtc(renderThread, this, "midithread", ANDROID_PRIORITY_AUDIO);
9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCondition.wait(mMutex);
9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGV("thread started");
9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // indicate success
10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mTid > 0) {
10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGV(" render thread(%d) started", mTid);
10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mState = EAS_STATE_READY;
10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
10489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectFailed:
10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return;
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
10889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::initCheck()
11089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
11189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE;
11289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
11389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMidiFile::~MidiFile() {
11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile destructor");
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    release();
11889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1202db8455d8f4468a637109d31f319ce02d9d743ecAndreas Huberstatus_t MidiFile::setDataSource(
1212db8455d8f4468a637109d31f319ce02d9d743ecAndreas Huber        const char* path, const KeyedVector<String8, String8> *) {
12289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::setDataSource url=%s", path);
12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
12489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
12589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // file still open?
12689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mEasHandle) {
12789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        reset_nosync();
12889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
12989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
13089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // open file and set paused state
13189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.path = strdup(path);
13289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.fd = -1;
13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.offset = 0;
13489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.length = 0;
13589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
13689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (result == EAS_SUCCESS) {
13789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        updateState();
13889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
13989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
14089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (result != EAS_SUCCESS) {
14189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("EAS_OpenFile failed: [%d]", (int)result);
14289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mState = EAS_STATE_ERROR;
14389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_OPEN_FAILED;
14489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
14589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
14689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mState = EAS_STATE_OPEN;
14789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPlayTime = 0;
14889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
14989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
15089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
15189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
15289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
15389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::setDataSource fd=%d", fd);
15489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
15589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
15689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // file still open?
15789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mEasHandle) {
15889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        reset_nosync();
15989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
16189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // open file and set paused state
16289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.fd = dup(fd);
16389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.offset = offset;
16489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.length = length;
16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
16689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    updateState();
16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
16889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (result != EAS_SUCCESS) {
16989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("EAS_OpenFile failed: [%d]", (int)result);
17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mState = EAS_STATE_ERROR;
17189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_OPEN_FAILED;
17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
17489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mState = EAS_STATE_OPEN;
17589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPlayTime = 0;
17689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
17789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
17889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::prepare()
18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::prepare");
18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle) {
18489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_NOT_OPEN;
18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_RESULT result;
18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("EAS_Prepare failed: [%ld]", result);
18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_EAS_FAILURE;
19089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
19189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    updateState();
19289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
19389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::prepareAsync()
19689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
19789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::prepareAsync");
19889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    status_t ret = prepare();
19989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
20089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // don't hold lock during callback
20189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (ret == NO_ERROR) {
20289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sendEvent(MEDIA_PREPARED);
20389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else {
20489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
20589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
20689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return ret;
20789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
20889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
20989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::start()
21089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
21189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::start");
21289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
21389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle) {
21489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_NOT_OPEN;
21589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
21689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
21789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // resuming after pause?
21889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mPaused) {
21989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
22089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ERROR_EAS_FAILURE;
22189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
22289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mPaused = false;
22389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        updateState();
22489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
22589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
22689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mRender = true;
22789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
22889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // wake up render thread
22989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("  wakeup render thread");
23089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mCondition.signal();
23189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
23289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
23389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
23489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::stop()
23589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
23689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::stop");
23789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
23889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle) {
23989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_NOT_OPEN;
24089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
24189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mPaused && (mState != EAS_STATE_STOPPED)) {
24289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
24389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (result != EAS_SUCCESS) {
24489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            LOGE("EAS_Pause returned error %ld", result);
24589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ERROR_EAS_FAILURE;
24689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPaused = false;
24989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::seekTo(int position)
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
25489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::seekTo %d", position);
25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // hold lock during EAS calls
25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    {
25789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        Mutex::Autolock lock(mMutex);
25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (!mEasHandle) {
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ERROR_NOT_OPEN;
26089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_RESULT result;
26289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
26389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                != EAS_SUCCESS)
26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        {
26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            LOGE("EAS_Locate returned %ld", result);
26689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ERROR_EAS_FAILURE;
26789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
26889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
26989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    sendEvent(MEDIA_SEEK_COMPLETE);
27189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
27389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
27489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::pause()
27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
27689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::pause");
27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
27889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle) {
27989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_NOT_OPEN;
28089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
28189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
28289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
28389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_EAS_FAILURE;
28489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
28589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPaused = true;
28689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
28789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
28889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
28989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool MidiFile::isPlaying()
29089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
29189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::isPlaying, mState=%d", int(mState));
29289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle || mPaused) return false;
29389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return (mState == EAS_STATE_PLAY);
29489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
29589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
29689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::getCurrentPosition(int* position)
29789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
29889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::getCurrentPosition");
29989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle) {
30089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("getCurrentPosition(): file not open");
30189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_NOT_OPEN;
30289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
30389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mPlayTime < 0) {
30489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
30589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_EAS_FAILURE;
30689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
30789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *position = mPlayTime;
30889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
30989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
31089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
31189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::getDuration(int* duration)
31289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
31389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
31489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::getDuration");
31589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    {
31689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        Mutex::Autolock lock(mMutex);
31789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (!mEasHandle) return ERROR_NOT_OPEN;
31889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        *duration = mDuration;
31989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
32089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
32189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // if no duration cached, get the duration
32289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // don't need a lock here because we spin up a new engine
32389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (*duration < 0) {
32489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_I32 temp;
32589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_DATA_HANDLE easData = NULL;
32689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_HANDLE easHandle = NULL;
32789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_RESULT result = EAS_Init(&easData);
32889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (result == EAS_SUCCESS) {
32989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
33089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
33189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (result == EAS_SUCCESS) {
33289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            result = EAS_Prepare(easData, easHandle);
33389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
33489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (result == EAS_SUCCESS) {
33589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            result = EAS_ParseMetaData(easData, easHandle, &temp);
33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (easHandle) {
33889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            EAS_CloseFile(easData, easHandle);
33989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
34089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (easData) {
34189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            EAS_Shutdown(easData);
34289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
34389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (result != EAS_SUCCESS) {
34589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ERROR_EAS_FAILURE;
34689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
34789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
34889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // cache successful result
34989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mDuration = *duration = int(temp);
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
35189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
35389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
35489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::release()
35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
35789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::release");
35889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock l(mMutex);
35989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    reset_nosync();
36089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // wait for render thread to exit
36289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mExit = true;
36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mCondition.signal();
36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // wait for thread to exit
36689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mAudioBuffer) {
36789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCondition.wait(mMutex);
36889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
36989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // release resources
37189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mEasData) {
37289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_Shutdown(mEasData);
37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mEasData = NULL;
37489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
37689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::reset()
37989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
38089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::reset");
38189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
38289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return reset_nosync();
38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// call only with mutex held
38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::reset_nosync()
38789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::reset_nosync");
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // close file
39089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mEasHandle) {
39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_CloseFile(mEasData, mEasHandle);
39289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mEasHandle = NULL;
39389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
39489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mFileLocator.path) {
39589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        free((void*)mFileLocator.path);
39689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mFileLocator.path = NULL;
39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
39889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mFileLocator.fd >= 0) {
39989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        close(mFileLocator.fd);
40089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.fd = -1;
40289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.offset = 0;
40389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFileLocator.length = 0;
40489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPlayTime = -1;
40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mDuration = -1;
40789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mLoop = false;
40889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mPaused = false;
40989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mRender = false;
41089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
41189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
41289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
41389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::setLooping(int loop)
41489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
41589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::setLooping");
41689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Mutex::Autolock lock(mMutex);
41789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mEasHandle) {
41889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_NOT_OPEN;
41989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
42089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    loop = loop ? -1 : 0;
42189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
42289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_EAS_FAILURE;
42389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
42489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
42589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
42689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
42789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MidiFile::createOutputTrack() {
428fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) {
42989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("mAudioSink open failed");
43089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return ERROR_OPEN_FAILED;
43189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
43289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
43389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
43489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
43589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectint MidiFile::renderThread(void* p) {
43689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
43789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return ((MidiFile*)p)->render();
43889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
43989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
44089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectint MidiFile::render() {
44189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_RESULT result = EAS_FAILURE;
44289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    EAS_I32 count;
44389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int temp;
44489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    bool audioStarted = false;
44589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
44689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    LOGV("MidiFile::render");
44789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
44889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // allocate render buffer
44989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
45089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!mAudioBuffer) {
45189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGE("mAudioBuffer allocate failed");
45289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        goto threadExit;
45389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
45489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
45589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // signal main thread that we started
45689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    {
45789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        Mutex::Autolock l(mMutex);
45889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mTid = myTid();
45989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        LOGV("render thread(%d) signal", mTid);
46089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCondition.signal();
46189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
46289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
46389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    while (1) {
46489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mMutex.lock();
46589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
46689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // nothing to render, wait for client thread to wake us up
46789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        while (!mRender && !mExit)
46889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        {
46989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            LOGV("MidiFile::render - signal wait");
47089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mCondition.wait(mMutex);
47189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            LOGV("MidiFile::render - signal rx'd");
47289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
47389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mExit) {
47489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mMutex.unlock();
47589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            break;
47689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
47789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
47889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // render midi data into the input buffer
47989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        //LOGV("MidiFile::render - rendering audio");
48089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int num_output = 0;
48189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_PCM* p = mAudioBuffer;
48289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        for (int i = 0; i < NUM_BUFFERS; i++) {
48389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
48489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (result != EAS_SUCCESS) {
48589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                LOGE("EAS_Render returned %ld", result);
48689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
48789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            p += count * pLibConfig->numChannels;
48889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
48989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
49089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
49189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // update playback state and position
49289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // LOGV("MidiFile::render - updating state");
49389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
49489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        EAS_State(mEasData, mEasHandle, &mState);
49589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mMutex.unlock();
49689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
49789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // create audio output track if necessary
49889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (!mAudioSink->ready()) {
49989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            LOGV("MidiFile::render - create output track");
50089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (createOutputTrack() != NO_ERROR)
50189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                goto threadExit;
50289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
50389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
50489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Write data to the audio hardware
50589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // LOGV("MidiFile::render - writing to audio output");
50689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
50789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            LOGE("Error in writing:%d",temp);
50889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return temp;
50989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
51089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
51189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // start audio output if necessary
51289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (!audioStarted) {
51389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            //LOGV("MidiFile::render - starting audio");
51489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mAudioSink->start();
51589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            audioStarted = true;
51689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
51789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
51889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // still playing?
51989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
52089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                (mState == EAS_STATE_PAUSED))
52189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        {
52289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            switch(mState) {
52389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            case EAS_STATE_STOPPED:
52489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            {
52589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                LOGV("MidiFile::render - stopped");
52689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                sendEvent(MEDIA_PLAYBACK_COMPLETE);
52789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
52889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
52989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            case EAS_STATE_ERROR:
53089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            {
53189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                LOGE("MidiFile::render - error");
53289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
53389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
53489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
53589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            case EAS_STATE_PAUSED:
53689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                LOGV("MidiFile::render - paused");
53789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
53889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            default:
53989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
54089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
54189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mAudioSink->stop();
54289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            audioStarted = false;
54389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mRender = false;
54489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
54589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
54689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
54789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectthreadExit:
54889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mAudioSink.clear();
54989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mAudioBuffer) {
55089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        delete [] mAudioBuffer;
55189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mAudioBuffer = NULL;
55289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
55389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMutex.lock();
55489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mTid = -1;
55589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mCondition.signal();
55689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMutex.unlock();
55789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return result;
55889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
55989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
56089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} // end namespace android
561