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 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"
{
static JavaVM *gJavaVM = 0;
static jclass classOfCocos2dxActivity = 0;
static JNIEnv *env = 0;
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
@ -19,321 +25,401 @@ extern "C"
}
// get env and cache it
static void getJNIEnv(void)
static JNIEnv* getJNIEnv(void)
{
if (! env)
{
// get jni environment
if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
{
LOGD("Failed to get the environment using GetEnv()");
}
JNIEnv *env = 0;
if (gJavaVM->AttachCurrentThread(&env, 0) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
}
// 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)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
}
return env;
}
// get class and make it a global reference, release it at endJni().
static void getClass(void)
static jclass getClassID(JNIEnv *pEnv)
{
if (! classOfCocos2dxActivity)
{
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);
}
jclass ret = pEnv->FindClass(CLASS_NAME);
if (! ret)
{
LOGD("get method id of %s error", methodName);
LOGD("Failed to find class of %s", CLASS_NAME);
}
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 playBackgroundMusic(String,boolean)
jmethodID preloadBackgroundMusicMethodID = getMethodID("preloadBackgroundMusic", "(Ljava/lang/String;)V");
JniMethodInfo methodInfo;
if (preloadBackgroundMusicMethodID)
{
jstring stringArg = env->NewStringUTF(path);
env->CallStaticVoidMethod(classOfCocos2dxActivity, preloadBackgroundMusicMethodID, stringArg);
env->DeleteLocalRef(stringArg);
if (! getStaticMethodInfo(methodInfo, "preloadBackgroundMusic", "(Ljava/lang/String;)V"))
{
return;
}
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 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);
env->CallStaticVoidMethod(classOfCocos2dxActivity, playBackgroundMusicMethodID, stringArg, isLoop);
env->DeleteLocalRef(stringArg);
return;
}
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 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 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 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 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()
{
// boolean rewindBackgroundMusic()
jmethodID isBackgroundMusicPlayingMethodID = getMethodID("isBackgroundMusicPlaying", "()Z");
JniMethodInfo methodInfo;
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;
}
float getBackgroundMusicVolumeJNI()
{
// 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;
}
void setBackgroundMusicVolumeJNI(float volume)
{
// 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)
{
// int playEffect(String)
JniMethodInfo methodInfo;
int ret = 0;
// int playEffect(String)
jmethodID playEffectMethodID = getMethodID("playEffect", "(Ljava/lang/String;Z)I");
if (playEffectMethodID)
if (! getStaticMethodInfo(methodInfo, "playEffect", "(Ljava/lang/String;Z)I"))
{
jstring stringArg = env->NewStringUTF(path);
ret = env->CallStaticIntMethod(classOfCocos2dxActivity, playEffectMethodID, stringArg, bLoop);
env->DeleteLocalRef(stringArg);
return ret;
}
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;
}
void stopEffectJNI(unsigned int nSoundId)
{
// 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 end()
jmethodID endMethodID = getMethodID("end", "()V");
if (endMethodID)
JniMethodInfo methodInfo;
if (! getStaticMethodInfo(methodInfo, "end", "()V"))
{
env->CallStaticVoidMethod(classOfCocos2dxActivity, endMethodID);
return ;
}
// release classOfCocos2dxActivity
env->DeleteGlobalRef(classOfCocos2dxActivity);
classOfCocos2dxActivity = 0;
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
float getEffectsVolumeJNI()
{
// float getEffectsVolume()
jmethodID getEffectsVolumeMethodID = getMethodID("getEffectsVolume", "()F");
JniMethodInfo methodInfo;
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;
}
void setEffectsVolumeJNI(float volume)
{
// 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 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);
env->CallStaticVoidMethod(classOfCocos2dxActivity, preloadEffectMethodID, stringArg);
env->DeleteLocalRef(stringArg);
return ;
}
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 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);
env->CallStaticVoidMethod(classOfCocos2dxActivity, unloadEffectMethodID, stringArg);
env->DeleteLocalRef(stringArg);
return ;
}
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 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 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 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 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 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);
}
}