fixed 924: make cocosdenshion thread safe for preloading

This commit is contained in:
minggo 2011-12-22 15:06:00 +08:00
parent db1ead3cd4
commit 3a3dcf736b
1 changed files with 214 additions and 128 deletions

View File

@ -3,13 +3,19 @@
#define LOG_TAG "libSimpleAudioEngine" #define LOG_TAG "libSimpleAudioEngine"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxActivity"
typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
extern "C" extern "C"
{ {
static JavaVM *gJavaVM = 0; static JavaVM *gJavaVM = 0;
static jclass classOfCocos2dxActivity = 0;
static JNIEnv *env = 0;
jint JNI_OnLoad(JavaVM *vm, void *reserved) jint JNI_OnLoad(JavaVM *vm, void *reserved)
{ {
@ -19,321 +25,401 @@ extern "C"
} }
// get env and cache it // get env and cache it
static void getJNIEnv(void) static JNIEnv* getJNIEnv(void)
{ {
if (! env) JNIEnv *env = 0;
{
// get jni environment
if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
{
LOGD("Failed to get the environment using GetEnv()");
}
if (gJavaVM->AttachCurrentThread(&env, 0) < 0) // get jni environment
{ if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
LOGD("Failed to get the environment using AttachCurrentThread()"); {
} LOGD("Failed to get the environment using GetEnv()");
} }
if (gJavaVM->AttachCurrentThread(&env, 0) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
}
return env;
} }
// get class and make it a global reference, release it at endJni(). // get class and make it a global reference, release it at endJni().
static void getClass(void) static jclass getClassID(JNIEnv *pEnv)
{ {
if (! classOfCocos2dxActivity) jclass ret = pEnv->FindClass(CLASS_NAME);
{
getJNIEnv();
jclass tmpClass = 0;
tmpClass = env->FindClass("org/cocos2dx/lib/Cocos2dxActivity");
if (! tmpClass)
{
LOGD("Failed to find class of org/cocos2dx/lib/Cocos2dxActivity");
}
// make it a global reference
classOfCocos2dxActivity = (jclass)env->NewGlobalRef(tmpClass);
env->DeleteLocalRef(tmpClass);
if (! classOfCocos2dxActivity)
{
LOGD("Failed to new global class of org/cocos2dx/lib/Cocos2dxActivity");
}
}
}
static jmethodID getMethodID(const char *methodName, const char *paramCode)
{
jmethodID ret = 0;
getClass();
if (env != 0 && classOfCocos2dxActivity != 0)
{
ret = env->GetStaticMethodID(classOfCocos2dxActivity, methodName, paramCode);
}
if (! ret) if (! ret)
{ {
LOGD("get method id of %s error", methodName); LOGD("Failed to find class of %s", CLASS_NAME);
} }
return ret; return ret;
} }
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode)
{
jmethodID methodID = 0;
JNIEnv *pEnv = 0;
bool bRet = false;
do
{
pEnv = getJNIEnv();
if (! pEnv)
{
break;
}
jclass classID = getClassID(pEnv);
methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode);
if (! methodID)
{
LOGD("Failed to find static method id of %s", methodName);
break;
}
methodinfo.classID = classID;
methodinfo.env = pEnv;
methodinfo.methodID = methodID;
bRet = true;
} while (0);
return bRet;
}
void preloadBackgroundMusicJNI(const char *path) void preloadBackgroundMusicJNI(const char *path)
{ {
// void playBackgroundMusic(String,boolean) // void playBackgroundMusic(String,boolean)
jmethodID preloadBackgroundMusicMethodID = getMethodID("preloadBackgroundMusic", "(Ljava/lang/String;)V"); JniMethodInfo methodInfo;
if (preloadBackgroundMusicMethodID) if (! getStaticMethodInfo(methodInfo, "preloadBackgroundMusic", "(Ljava/lang/String;)V"))
{ {
jstring stringArg = env->NewStringUTF(path); return;
env->CallStaticVoidMethod(classOfCocos2dxActivity, preloadBackgroundMusicMethodID, stringArg);
env->DeleteLocalRef(stringArg);
} }
jstring stringArg = methodInfo.env->NewStringUTF(path);
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void playBackgroundMusicJNI(const char *path, bool isLoop) void playBackgroundMusicJNI(const char *path, bool isLoop)
{ {
// void playBackgroundMusic(String,boolean) // void playBackgroundMusic(String,boolean)
jmethodID playBackgroundMusicMethodID = getMethodID("playBackgroundMusic", "(Ljava/lang/String;Z)V");
if (playBackgroundMusicMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "playBackgroundMusic", "(Ljava/lang/String;Z)V"))
{ {
jstring stringArg = env->NewStringUTF(path); return;
env->CallStaticVoidMethod(classOfCocos2dxActivity, playBackgroundMusicMethodID, stringArg, isLoop);
env->DeleteLocalRef(stringArg);
} }
jstring stringArg = methodInfo.env->NewStringUTF(path);
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg, isLoop);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void stopBackgroundMusicJNI() void stopBackgroundMusicJNI()
{ {
// void stopBackgroundMusic() // void stopBackgroundMusic()
jmethodID stopBackgroundMusicMethodID = getMethodID("stopBackgroundMusic", "()V");
if (stopBackgroundMusicMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "stopBackgroundMusic", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, stopBackgroundMusicMethodID); return;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void pauseBackgroundMusicJNI() void pauseBackgroundMusicJNI()
{ {
// void pauseBackgroundMusic() // void pauseBackgroundMusic()
jmethodID pauseBackgroundMusicMethodID = getMethodID("pauseBackgroundMusic", "()V");
if (pauseBackgroundMusicMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "pauseBackgroundMusic", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, pauseBackgroundMusicMethodID); return;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void resumeBackgroundMusicJNI() void resumeBackgroundMusicJNI()
{ {
// void resumeBackgroundMusic() // void resumeBackgroundMusic()
jmethodID resumeBackgroundMusicMethodID = getMethodID("resumeBackgroundMusic", "()V");
if (resumeBackgroundMusicMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "resumeBackgroundMusic", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, resumeBackgroundMusicMethodID); return;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void rewindBackgroundMusicJNI() void rewindBackgroundMusicJNI()
{ {
// void rewindBackgroundMusic() // void rewindBackgroundMusic()
jmethodID rewindBackgroundMusicMethodID = getMethodID("rewindBackgroundMusic", "()V");
if (rewindBackgroundMusicMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "rewindBackgroundMusic", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, rewindBackgroundMusicMethodID); return;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
bool isBackgroundMusicPlayingJNI() bool isBackgroundMusicPlayingJNI()
{ {
// boolean rewindBackgroundMusic() // boolean rewindBackgroundMusic()
jmethodID isBackgroundMusicPlayingMethodID = getMethodID("isBackgroundMusicPlaying", "()Z");
JniMethodInfo methodInfo;
jboolean ret = false; jboolean ret = false;
if (isBackgroundMusicPlayingMethodID) if (! getStaticMethodInfo(methodInfo, "isBackgroundMusicPlaying", "()Z"))
{ {
ret = env->CallStaticBooleanMethod(classOfCocos2dxActivity, isBackgroundMusicPlayingMethodID); return ret;
} }
ret = methodInfo.env->CallStaticBooleanMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
return ret; return ret;
} }
float getBackgroundMusicVolumeJNI() float getBackgroundMusicVolumeJNI()
{ {
// float getBackgroundMusicVolume() // float getBackgroundMusicVolume()
jmethodID getBackgroundMusicVolumeID = getMethodID("getBackgroundMusicVolume", "()F");
jfloat ret = 0.0;
if (getBackgroundMusicVolumeID) JniMethodInfo methodInfo;
jfloat ret = -1.0;
if (! getStaticMethodInfo(methodInfo, "getBackgroundMusicVolume", "()F"))
{ {
ret = env->CallStaticFloatMethod(classOfCocos2dxActivity, getBackgroundMusicVolumeID); return ret;
} }
ret = methodInfo.env->CallStaticFloatMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
return ret; return ret;
} }
void setBackgroundMusicVolumeJNI(float volume) void setBackgroundMusicVolumeJNI(float volume)
{ {
// void setBackgroundMusicVolume() // void setBackgroundMusicVolume()
jmethodID setBackgroundMusicVolumeMethodID = getMethodID("setBackgroundMusicVolume", "(F)V");
if (setBackgroundMusicVolumeMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "setBackgroundMusicVolume", "(F)V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, setBackgroundMusicVolumeMethodID, volume); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, volume);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
unsigned int playEffectJNI(const char* path, bool bLoop) unsigned int playEffectJNI(const char* path, bool bLoop)
{ {
// int playEffect(String)
JniMethodInfo methodInfo;
int ret = 0; int ret = 0;
// int playEffect(String) if (! getStaticMethodInfo(methodInfo, "playEffect", "(Ljava/lang/String;Z)I"))
jmethodID playEffectMethodID = getMethodID("playEffect", "(Ljava/lang/String;Z)I");
if (playEffectMethodID)
{ {
jstring stringArg = env->NewStringUTF(path); return ret;
ret = env->CallStaticIntMethod(classOfCocos2dxActivity, playEffectMethodID, stringArg, bLoop);
env->DeleteLocalRef(stringArg);
} }
jstring stringArg = methodInfo.env->NewStringUTF(path);
ret = methodInfo.env->CallStaticIntMethod(methodInfo.classID, methodInfo.methodID, stringArg, bLoop);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
return (unsigned int)ret; return (unsigned int)ret;
} }
void stopEffectJNI(unsigned int nSoundId) void stopEffectJNI(unsigned int nSoundId)
{ {
// void stopEffect(int) // void stopEffect(int)
jmethodID stopEffectMethodID = getMethodID("stopEffect", "(I)V");
if (stopEffectMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "stopEffect", "(I)V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, stopEffectMethodID, (int)nSoundId); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, (int)nSoundId);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void endJNI() void endJNI()
{ {
// void end() // void end()
jmethodID endMethodID = getMethodID("end", "()V");
if (endMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "end", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, endMethodID); return ;
} }
// release classOfCocos2dxActivity methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
env->DeleteGlobalRef(classOfCocos2dxActivity); methodInfo.env->DeleteLocalRef(methodInfo.classID);
classOfCocos2dxActivity = 0;
} }
float getEffectsVolumeJNI() float getEffectsVolumeJNI()
{ {
// float getEffectsVolume() // float getEffectsVolume()
jmethodID getEffectsVolumeMethodID = getMethodID("getEffectsVolume", "()F");
JniMethodInfo methodInfo;
jfloat ret = -1.0; jfloat ret = -1.0;
if (getEffectsVolumeMethodID) if (! getStaticMethodInfo(methodInfo, "getEffectsVolume", "()F"))
{ {
ret = env->CallStaticFloatMethod(classOfCocos2dxActivity, getEffectsVolumeMethodID); return ret;
} }
ret = methodInfo.env->CallStaticFloatMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
return ret; return ret;
} }
void setEffectsVolumeJNI(float volume) void setEffectsVolumeJNI(float volume)
{ {
// void setEffectsVolume(float) // void setEffectsVolume(float)
jmethodID setEffectsVolumeMethodID = getMethodID("setEffectsVolume", "(F)V"); JniMethodInfo methodInfo;
if (setEffectsVolumeMethodID) if (! getStaticMethodInfo(methodInfo, "setEffectsVolume", "(F)V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, setEffectsVolumeMethodID, volume); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, volume);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void preloadEffectJNI(const char *path) void preloadEffectJNI(const char *path)
{ {
// void preloadEffect(String) // void preloadEffect(String)
jmethodID preloadEffectMethodID = getMethodID("preloadEffect", "(Ljava/lang/String;)V");
if (preloadEffectMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "preloadEffect", "(Ljava/lang/String;)V"))
{ {
jstring stringArg = env->NewStringUTF(path); return ;
env->CallStaticVoidMethod(classOfCocos2dxActivity, preloadEffectMethodID, stringArg);
env->DeleteLocalRef(stringArg);
} }
jstring stringArg = methodInfo.env->NewStringUTF(path);
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void unloadEffectJNI(const char* path) void unloadEffectJNI(const char* path)
{ {
// void unloadEffect(String) // void unloadEffect(String)
jmethodID unloadEffectMethodID = getMethodID("unloadEffect", "(Ljava/lang/String;)V");
if (unloadEffectMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "unloadEffect", "(Ljava/lang/String;)V"))
{ {
jstring stringArg = env->NewStringUTF(path); return ;
env->CallStaticVoidMethod(classOfCocos2dxActivity, unloadEffectMethodID, stringArg);
env->DeleteLocalRef(stringArg);
} }
jstring stringArg = methodInfo.env->NewStringUTF(path);
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void pauseEffectJNI(unsigned int nSoundId) void pauseEffectJNI(unsigned int nSoundId)
{ {
// void pauseEffect(int) // void pauseEffect(int)
jmethodID pauseEffectMethodID = getMethodID("pauseEffect", "(I)V");
if (pauseEffectMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "pauseEffect", "(I)V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, pauseEffectMethodID, (int)nSoundId); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, (int)nSoundId);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void pauseAllEffectsJNI() void pauseAllEffectsJNI()
{ {
// void pauseAllEffects() // void pauseAllEffects()
jmethodID pauseAllEffectsMethodID = getMethodID("pauseAllEffects", "()V");
if (pauseAllEffectsMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "pauseAllEffects", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, pauseAllEffectsMethodID); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void resumeEffectJNI(unsigned int nSoundId) void resumeEffectJNI(unsigned int nSoundId)
{ {
// void resumeEffect(int) // void resumeEffect(int)
jmethodID resumeEffectMethodID = getMethodID("resumeEffect", "(I)V");
if (resumeEffectMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "resumeEffect", "(I)V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, resumeEffectMethodID, (int)nSoundId); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, (int)nSoundId);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void resumeAllEffectsJNI() void resumeAllEffectsJNI()
{ {
// void resumeAllEffects() // void resumeAllEffects()
jmethodID resumeAllEffectsMethodID = getMethodID("resumeAllEffects", "()V");
if (resumeAllEffectsMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "resumeAllEffects", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, resumeAllEffectsMethodID); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
void stopAllEffectsJNI() void stopAllEffectsJNI()
{ {
// void stopAllEffects() // void stopAllEffects()
jmethodID stopAllEffectsMethodID = getMethodID("stopAllEffects", "()V");
if (stopAllEffectsMethodID) JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "stopAllEffects", "()V"))
{ {
env->CallStaticVoidMethod(classOfCocos2dxActivity, stopAllEffectsMethodID); return ;
} }
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
} }
} }