diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
commit | cce8bd12da6d8419a8770e4552a51ec297c250c2 (patch) | |
tree | 04f90a5380030b06b7c7c99b9972ef0f147621ec /media/libmedia/JetPlayer.cpp | |
parent | 7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8 (diff) | |
download | frameworks_av-cce8bd12da6d8419a8770e4552a51ec297c250c2.zip frameworks_av-cce8bd12da6d8419a8770e4552a51ec297c250c2.tar.gz frameworks_av-cce8bd12da6d8419a8770e4552a51ec297c250c2.tar.bz2 |
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'media/libmedia/JetPlayer.cpp')
-rw-r--r-- | media/libmedia/JetPlayer.cpp | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp new file mode 100644 index 0000000..f0edf88 --- /dev/null +++ b/media/libmedia/JetPlayer.cpp @@ -0,0 +1,428 @@ +/* + * 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 <utils/threads.h> + +#include <media/JetPlayer.h> + + +#ifdef HAVE_GETTID +static pid_t myTid() { return gettid(); } +#else +static pid_t myTid() { return getpid(); } +#endif + + +namespace android +{ + +static const int MIX_NUM_BUFFERS = 4; +static const S_EAS_LIB_CONFIG* pLibConfig = NULL; + +//------------------------------------------------------------------------------------------------- +JetPlayer::JetPlayer(jobject javaJetPlayer, int maxTracks, int trackBufferSize) : + mEventCallback(NULL), + mJavaJetPlayerRef(javaJetPlayer), + mTid(-1), + mRender(false), + mPaused(false), + mMaxTracks(maxTracks), + mEasData(NULL), + mEasJetFileLoc(NULL), + mAudioTrack(NULL), + mTrackBufferSize(trackBufferSize) +{ + LOGV("JetPlayer constructor"); + mPreviousJetStatus.currentUserID = -1; + mPreviousJetStatus.segmentRepeatCount = -1; + mPreviousJetStatus.numQueuedSegments = -1; + mPreviousJetStatus.paused = true; +} + +//------------------------------------------------------------------------------------------------- +JetPlayer::~JetPlayer() +{ + LOGV("~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) { + LOGE("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) { + LOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting."); + mState = EAS_STATE_ERROR; + return result; + } + // init the JET library + result = JET_Init(mEasData, NULL, 0); + if( result != EAS_SUCCESS) { + LOGE("JetPlayer::init(): Error initializing JET library, aborting."); + mState = EAS_STATE_ERROR; + return result; + } + + // create the output AudioTrack + mAudioTrack = new AudioTrack(); + mAudioTrack->set(AudioTrack::MUSIC, //TODO parametrize this + pLibConfig->sampleRate, + 1, // format = PCM 16bits per sample, + pLibConfig->numChannels, + mTrackBufferSize, + 0); + + // create render and playback thread + { + Mutex::Autolock l(mMutex); + LOGV("JetPlayer::init(): trying to start render thread"); + createThreadEtc(renderThread, this, "jetRenderThread", ANDROID_PRIORITY_AUDIO); + mCondition.wait(mMutex); + } + if (mTid > 0) { + // render thread started, we're ready + LOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid); + mState = EAS_STATE_READY; + } else { + LOGE("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() +{ + LOGV("JetPlayer::release()"); + Mutex::Autolock lock(mMutex); + mPaused = true; + mRender = false; + if (mEasData) { + JET_Pause(mEasData); + JET_CloseFile(mEasData); + JET_Shutdown(mEasData); + EAS_Shutdown(mEasData); + } + if (mEasJetFileLoc) { + free(mEasJetFileLoc); + mEasJetFileLoc = NULL; + } + if (mAudioTrack) { + mAudioTrack->stop(); + mAudioTrack->flush(); + delete mAudioTrack; + mAudioTrack = NULL; + } + if (mAudioBuffer) { + delete mAudioBuffer; + mAudioBuffer = NULL; + } + mEasData = NULL; + + return EAS_SUCCESS; +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::renderThread(void* p) { + + return ((JetPlayer*)p)->render(); +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::render() { + EAS_RESULT result = EAS_FAILURE; + EAS_I32 count; + int temp; + bool audioStarted = false; + + LOGV("JetPlayer::render(): entering"); + + // allocate render buffer + mAudioBuffer = + new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS]; + if (!mAudioBuffer) { + LOGE("JetPlayer::render(): mAudioBuffer allocate failed"); + goto threadExit; + } + + // signal main thread that we started + { + Mutex::Autolock l(mMutex); + mTid = myTid(); + LOGV("JetPlayer::render(): render thread(%d) signal", mTid); + mCondition.signal(); + } + + while (1) { + mMutex.lock(); // [[[[[[[[ LOCK --------------------------------------- + + // nothing to render, wait for client thread to wake us up + while (!mRender) + { + LOGV("JetPlayer::render(): signal wait"); + mCondition.wait(mMutex); + LOGV("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) { + LOGE("JetPlayer::render(): EAS_Render returned error %ld", result); + } + p += count * pLibConfig->numChannels; + num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); + } + + // update playback state + //LOGV("JetPlayer::render(): updating state"); + JET_Status(mEasData, &mJetStatus); + fireEventOnStatusChange(); + mPaused = mJetStatus.paused; + + mMutex.unlock(); // UNLOCK ]]]]]]]] ----------------------------------- + + // check audio output track + if (mAudioTrack == NULL) { + LOGE("JetPlayer::render(): output AudioTrack was not created"); + goto threadExit; + } + + // Write data to the audio hardware + //LOGV("JetPlayer::render(): writing to audio output"); + if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) { + LOGE("JetPlayer::render(): Error in writing:%d",temp); + return temp; + } + + // start audio output if necessary + if (!audioStarted) { + LOGV("JetPlayer::render(): starting audio playback"); + mAudioTrack->start(); + audioStarted = true; + } + + }//while (1) + +threadExit: + mAudioTrack->flush(); + if (mAudioBuffer) { + delete [] mAudioBuffer; + mAudioBuffer = NULL; + } + mMutex.lock(); + mTid = -1; + mCondition.signal(); + mMutex.unlock(); + return result; +} + + +//------------------------------------------------------------------------------------------------- +// fire up an event if any of the status fields has changed +// precondition: mMutex locked +void JetPlayer::fireEventOnStatusChange() +{ + 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; + } + +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::openFile(const char* path) +{ + LOGV("JetPlayer::openFile(): path=%s", path); + + Mutex::Autolock lock(mMutex); + + mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); + memset(mJetFilePath, 0, 256); + strncpy(mJetFilePath, path, strlen(path)); + mEasJetFileLoc->path = mJetFilePath; + + mEasJetFileLoc->fd = 0; + mEasJetFileLoc->length = 0; + mEasJetFileLoc->offset = 0; + + EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); + 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() +{ + LOGV("JetPlayer::play(): entering"); + Mutex::Autolock lock(mMutex); + + EAS_RESULT result = JET_Play(mEasData); + + mPaused = false; + mRender = true; + + JET_Status(mEasData, &mJetStatus); + this->dumpJetStatus(&mJetStatus); + + fireEventOnStatusChange(); + + // wake up render thread + LOGV("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); + fireEventOnStatusChange(); + + + return result; +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose, + EAS_U32 muteFlags, EAS_U8 userID) +{ + LOGV("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) +{ + LOGV("JetPlayer::triggerClip clipId=%d", clipId); + Mutex::Autolock lock(mMutex); + return JET_TriggerClip(mEasData, clipId); +} + +//------------------------------------------------------------------------------------------------- +void JetPlayer::dump() +{ + LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path); +} + +void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus) +{ + if(pJetStatus!=NULL) + LOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d paused=%d", + pJetStatus->currentUserID, pJetStatus->segmentRepeatCount, + pJetStatus->numQueuedSegments, pJetStatus->paused); + else + LOGE(">> JET player status is NULL"); +} + + +} // end namespace android + |