Merge "Move JetPlayer implemention and JNI"
This commit is contained in:
@@ -169,7 +169,6 @@ cc_library_shared {
|
||||
"android_media_AudioVolumeGroups.cpp",
|
||||
"android_media_AudioVolumeGroupCallback.cpp",
|
||||
"android_media_DeviceCallback.cpp",
|
||||
"android_media_JetPlayer.cpp",
|
||||
"android_media_MediaMetricsJNI.cpp",
|
||||
"android_media_MicrophoneInfo.cpp",
|
||||
"android_media_midi.cpp",
|
||||
|
||||
@@ -113,7 +113,6 @@ extern int register_android_media_AudioProductStrategies(JNIEnv *env);
|
||||
extern int register_android_media_AudioVolumeGroups(JNIEnv *env);
|
||||
extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
|
||||
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
|
||||
extern int register_android_media_JetPlayer(JNIEnv *env);
|
||||
extern int register_android_media_ToneGenerator(JNIEnv *env);
|
||||
extern int register_android_media_midi(JNIEnv *env);
|
||||
|
||||
@@ -1589,7 +1588,6 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_media_AudioProductStrategies),
|
||||
REG_JNI(register_android_media_AudioVolumeGroups),
|
||||
REG_JNI(register_android_media_AudioVolumeGroupChangeHandler),
|
||||
REG_JNI(register_android_media_JetPlayer),
|
||||
REG_JNI(register_android_media_MicrophoneInfo),
|
||||
REG_JNI(register_android_media_RemoteDisplay),
|
||||
REG_JNI(register_android_media_ToneGenerator),
|
||||
|
||||
@@ -17,18 +17,17 @@
|
||||
package android.media;
|
||||
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.CloneNotSupportedException;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.os.Looper;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* JetPlayer provides access to JET content playback and control.
|
||||
*
|
||||
@@ -120,6 +119,9 @@ public class JetPlayer
|
||||
|
||||
private static JetPlayer singletonRef;
|
||||
|
||||
static {
|
||||
System.loadLibrary("media_jni");
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
// Used exclusively by native code
|
||||
|
||||
@@ -4,6 +4,7 @@ cc_library_shared {
|
||||
srcs: [
|
||||
"android_media_ImageWriter.cpp",
|
||||
"android_media_ImageReader.cpp",
|
||||
"android_media_JetPlayer.cpp",
|
||||
"android_media_MediaCrypto.cpp",
|
||||
"android_media_MediaCodec.cpp",
|
||||
"android_media_MediaCodecList.cpp",
|
||||
@@ -25,10 +26,12 @@ cc_library_shared {
|
||||
"android_mtp_MtpDatabase.cpp",
|
||||
"android_mtp_MtpDevice.cpp",
|
||||
"android_mtp_MtpServer.cpp",
|
||||
"JetPlayer.cpp",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libandroid_runtime",
|
||||
"libaudioclient",
|
||||
"libnativehelper",
|
||||
"libnativewindow",
|
||||
"libutils",
|
||||
@@ -53,6 +56,7 @@ cc_library_shared {
|
||||
"libandroidfw",
|
||||
"libhidlallocatorutils",
|
||||
"libhidlbase",
|
||||
"libsonivox",
|
||||
"android.hardware.cas@1.0",
|
||||
"android.hardware.cas.native@1.0",
|
||||
"android.hidl.memory@1.0",
|
||||
@@ -64,7 +68,10 @@ cc_library_shared {
|
||||
"libmediadrm_headers",
|
||||
],
|
||||
|
||||
static_libs: ["libgrallocusage"],
|
||||
static_libs: [
|
||||
"libgrallocusage",
|
||||
"libmedia_midiiowrapper",
|
||||
],
|
||||
|
||||
include_dirs: [
|
||||
"frameworks/base/core/jni",
|
||||
|
||||
471
media/jni/JetPlayer.cpp
Normal file
471
media/jni/JetPlayer.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* 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 "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),
|
||||
mIoWrapper(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);
|
||||
}
|
||||
delete mIoWrapper;
|
||||
mIoWrapper = NULL;
|
||||
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);
|
||||
|
||||
delete mIoWrapper;
|
||||
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);
|
||||
|
||||
delete mIoWrapper;
|
||||
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
|
||||
126
media/jni/JetPlayer.h
Normal file
126
media/jni/JetPlayer.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef JETPLAYER_H_
|
||||
#define JETPLAYER_H_
|
||||
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <libsonivox/jet.h>
|
||||
#include <libsonivox/eas_types.h>
|
||||
#include <media/AudioTrack.h>
|
||||
#include <media/MidiIoWrapper.h>
|
||||
|
||||
|
||||
namespace android {
|
||||
|
||||
typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie);
|
||||
|
||||
class JetPlayer {
|
||||
|
||||
public:
|
||||
|
||||
// to keep in sync with the JetPlayer class constants
|
||||
// defined in frameworks/base/media/java/android/media/JetPlayer.java
|
||||
static const int JET_EVENT = 1;
|
||||
static const int JET_USERID_UPDATE = 2;
|
||||
static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
|
||||
static const int JET_PAUSE_UPDATE = 4;
|
||||
|
||||
JetPlayer(void *javaJetPlayer,
|
||||
int maxTracks = 32,
|
||||
int trackBufferSize = 1200);
|
||||
~JetPlayer();
|
||||
int init();
|
||||
int release();
|
||||
|
||||
int loadFromFile(const char* url);
|
||||
int loadFromFD(const int fd, const long long offset, const long long length);
|
||||
int closeFile();
|
||||
int play();
|
||||
int pause();
|
||||
int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
|
||||
EAS_U32 muteFlags, EAS_U8 userID);
|
||||
int setMuteFlags(EAS_U32 muteFlags, bool sync);
|
||||
int setMuteFlag(int trackNum, bool muteFlag, bool sync);
|
||||
int triggerClip(int clipId);
|
||||
int clearQueue();
|
||||
|
||||
void setEventCallback(jetevent_callback callback);
|
||||
|
||||
int getMaxTracks() { return mMaxTracks; };
|
||||
|
||||
|
||||
private:
|
||||
int render();
|
||||
void fireUpdateOnStatusChange();
|
||||
void fireEventsFromJetQueue();
|
||||
|
||||
JetPlayer() {} // no default constructor
|
||||
void dump();
|
||||
void dumpJetStatus(S_JET_STATUS* pJetStatus);
|
||||
|
||||
jetevent_callback mEventCallback;
|
||||
|
||||
void* mJavaJetPlayerRef;
|
||||
Mutex mMutex; // mutex to sync the render and playback thread with the JET calls
|
||||
pid_t mTid;
|
||||
Condition mCondition;
|
||||
volatile bool mRender;
|
||||
bool mPaused;
|
||||
|
||||
EAS_STATE mState;
|
||||
int* mMemFailedVar;
|
||||
|
||||
int mMaxTracks; // max number of MIDI tracks, usually 32
|
||||
EAS_DATA_HANDLE mEasData;
|
||||
MidiIoWrapper* mIoWrapper;
|
||||
EAS_PCM* mAudioBuffer;// EAS renders the MIDI data into this buffer,
|
||||
sp<AudioTrack> mAudioTrack; // and we play it in this audio track
|
||||
int mTrackBufferSize;
|
||||
S_JET_STATUS mJetStatus;
|
||||
S_JET_STATUS mPreviousJetStatus;
|
||||
|
||||
class JetPlayerThread : public Thread {
|
||||
public:
|
||||
JetPlayerThread(JetPlayer *player) : mPlayer(player) {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~JetPlayerThread() {}
|
||||
|
||||
private:
|
||||
JetPlayer *mPlayer;
|
||||
|
||||
bool threadLoop() {
|
||||
int result;
|
||||
result = mPlayer->render();
|
||||
return false;
|
||||
}
|
||||
|
||||
JetPlayerThread(const JetPlayerThread &);
|
||||
JetPlayerThread &operator=(const JetPlayerThread &);
|
||||
};
|
||||
|
||||
sp<JetPlayerThread> mThread;
|
||||
|
||||
}; // end class JetPlayer
|
||||
|
||||
} // end namespace android
|
||||
|
||||
|
||||
|
||||
#endif /*JETPLAYER_H_*/
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <media/JetPlayer.h>
|
||||
#include "JetPlayer.h"
|
||||
|
||||
|
||||
using namespace android;
|
||||
@@ -1436,6 +1436,7 @@ static int register_android_media_MediaPlayer(JNIEnv *env)
|
||||
}
|
||||
extern int register_android_media_ImageReader(JNIEnv *env);
|
||||
extern int register_android_media_ImageWriter(JNIEnv *env);
|
||||
extern int register_android_media_JetPlayer(JNIEnv *env);
|
||||
extern int register_android_media_Crypto(JNIEnv *env);
|
||||
extern int register_android_media_Drm(JNIEnv *env);
|
||||
extern int register_android_media_Descrambler(JNIEnv *env);
|
||||
@@ -1475,6 +1476,11 @@ jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (register_android_media_JetPlayer(env) < 0) {
|
||||
ALOGE("ERROR: JetPlayer native registration failed");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (register_android_media_MediaPlayer(env) < 0) {
|
||||
ALOGE("ERROR: MediaPlayer native registration failed\n");
|
||||
goto bail;
|
||||
|
||||
Reference in New Issue
Block a user