ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

jni.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #if defined(__ANDROID__)
00024 
00025 // Allow use of stuff in <time.h> and abort()
00026 #define FORBIDDEN_SYMBOL_EXCEPTION_time_h
00027 #define FORBIDDEN_SYMBOL_EXCEPTION_abort
00028 
00029 // Disable printf override in common/forbidden.h to avoid
00030 // clashes with log.h from the Android SDK.
00031 // That header file uses
00032 //   __attribute__ ((format(printf, 3, 4)))
00033 // which gets messed up by our override mechanism; this could
00034 // be avoided by either changing the Android SDK to use the equally
00035 // legal and valid
00036 //   __attribute__ ((format(printf, 3, 4)))
00037 // or by refining our printf override to use a varadic macro
00038 // (which then wouldn't be portable, though).
00039 // Anyway, for now we just disable the printf override globally
00040 // for the Android port
00041 #define FORBIDDEN_SYMBOL_EXCEPTION_printf
00042 
00043 #include "base/main.h"
00044 #include "base/version.h"
00045 #include "common/config-manager.h"
00046 #include "common/error.h"
00047 #include "common/textconsole.h"
00048 #include "common/translation.h"
00049 #include "engines/engine.h"
00050 
00051 #include "backends/platform/android/android.h"
00052 #include "backends/platform/android/asset-archive.h"
00053 #include "backends/platform/android/jni.h"
00054 
00055 __attribute__ ((visibility("default")))
00056 jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
00057     return JNI::onLoad(vm);
00058 }
00059 
00060 JavaVM *JNI::_vm = 0;
00061 jobject JNI::_jobj = 0;
00062 jobject JNI::_jobj_audio_track = 0;
00063 jobject JNI::_jobj_egl = 0;
00064 jobject JNI::_jobj_egl_display = 0;
00065 jobject JNI::_jobj_egl_surface = 0;
00066 
00067 Common::Archive *JNI::_asset_archive = 0;
00068 OSystem_Android *JNI::_system = 0;
00069 
00070 bool JNI::pause = false;
00071 sem_t JNI::pause_sem = { 0 };
00072 
00073 int JNI::surface_changeid = 0;
00074 int JNI::egl_surface_width = 0;
00075 int JNI::egl_surface_height = 0;
00076 bool JNI::_ready_for_events = 0;
00077 
00078 jmethodID JNI::_MID_getDPI = 0;
00079 jmethodID JNI::_MID_displayMessageOnOSD = 0;
00080 jmethodID JNI::_MID_openUrl = 0;
00081 jmethodID JNI::_MID_hasTextInClipboard = 0;
00082 jmethodID JNI::_MID_getTextFromClipboard = 0;
00083 jmethodID JNI::_MID_setTextInClipboard = 0;
00084 jmethodID JNI::_MID_isConnectionLimited = 0;
00085 jmethodID JNI::_MID_setWindowCaption = 0;
00086 jmethodID JNI::_MID_showVirtualKeyboard = 0;
00087 jmethodID JNI::_MID_getSysArchives = 0;
00088 jmethodID JNI::_MID_initSurface = 0;
00089 jmethodID JNI::_MID_deinitSurface = 0;
00090 
00091 jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0;
00092 
00093 jmethodID JNI::_MID_AudioTrack_flush = 0;
00094 jmethodID JNI::_MID_AudioTrack_pause = 0;
00095 jmethodID JNI::_MID_AudioTrack_play = 0;
00096 jmethodID JNI::_MID_AudioTrack_stop = 0;
00097 jmethodID JNI::_MID_AudioTrack_write = 0;
00098 
00099 const JNINativeMethod JNI::_natives[] = {
00100     { "create", "(Landroid/content/res/AssetManager;"
00101                 "Ljavax/microedition/khronos/egl/EGL10;"
00102                 "Ljavax/microedition/khronos/egl/EGLDisplay;"
00103                 "Landroid/media/AudioTrack;II)V",
00104         (void *)JNI::create },
00105     { "destroy", "()V",
00106         (void *)JNI::destroy },
00107     { "setSurface", "(II)V",
00108         (void *)JNI::setSurface },
00109     { "main", "([Ljava/lang/String;)I",
00110         (void *)JNI::main },
00111     { "pushEvent", "(IIIIIII)V",
00112         (void *)JNI::pushEvent },
00113     { "enableZoning", "(Z)V",
00114         (void *)JNI::enableZoning },
00115     { "setPause", "(Z)V",
00116         (void *)JNI::setPause },
00117     { "getCurrentCharset", "()Ljava/lang/String;",
00118         (void *)JNI::getCurrentCharset }
00119 };
00120 
00121 JNI::JNI() {
00122 }
00123 
00124 JNI::~JNI() {
00125 }
00126 
00127 jint JNI::onLoad(JavaVM *vm) {
00128     _vm = vm;
00129 
00130     JNIEnv *env;
00131 
00132     if (_vm->GetEnv((void **)&env, JNI_VERSION_1_2))
00133         return JNI_ERR;
00134 
00135     jclass cls = env->FindClass("org/residualvm/residualvm/ResidualVM");
00136     if (cls == 0)
00137         return JNI_ERR;
00138 
00139     if (env->RegisterNatives(cls, _natives, ARRAYSIZE(_natives)) < 0)
00140         return JNI_ERR;
00141 
00142     return JNI_VERSION_1_2;
00143 }
00144 
00145 JNIEnv *JNI::getEnv() {
00146     JNIEnv *env = 0;
00147 
00148     jint res = _vm->GetEnv((void **)&env, JNI_VERSION_1_2);
00149 
00150     if (res != JNI_OK) {
00151         LOGE("GetEnv() failed: %d", res);
00152         abort();
00153     }
00154 
00155     return env;
00156 }
00157 
00158 void JNI::attachThread() {
00159     JNIEnv *env = 0;
00160 
00161     jint res = _vm->AttachCurrentThread(&env, 0);
00162 
00163     if (res != JNI_OK) {
00164         LOGE("AttachCurrentThread() failed: %d", res);
00165         abort();
00166     }
00167 }
00168 
00169 void JNI::detachThread() {
00170     jint res = _vm->DetachCurrentThread();
00171 
00172     if (res != JNI_OK) {
00173         LOGE("DetachCurrentThread() failed: %d", res);
00174         abort();
00175     }
00176 }
00177 
00178 void JNI::setReadyForEvents(bool ready) {
00179     _ready_for_events = ready;
00180 }
00181 
00182 void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
00183     jclass cls = env->FindClass(name);
00184 
00185     // if cls is 0, an exception has already been thrown
00186     if (cls != 0)
00187         env->ThrowNew(cls, msg);
00188 
00189     env->DeleteLocalRef(cls);
00190 }
00191 
00192 void JNI::throwRuntimeException(JNIEnv *env, const char *msg) {
00193     throwByName(env, "java/lang/RuntimeException", msg);
00194 }
00195 
00196 // calls to the dark side
00197 
00198 void JNI::getDPI(float *values) {
00199     values[0] = 0.0;
00200     values[1] = 0.0;
00201 
00202     JNIEnv *env = JNI::getEnv();
00203 
00204     jfloatArray array = env->NewFloatArray(2);
00205 
00206     env->CallVoidMethod(_jobj, _MID_getDPI, array);
00207 
00208     if (env->ExceptionCheck()) {
00209         LOGE("Failed to get DPIs");
00210 
00211         env->ExceptionDescribe();
00212         env->ExceptionClear();
00213     } else {
00214         jfloat *res = env->GetFloatArrayElements(array, 0);
00215 
00216         if (res) {
00217             values[0] = res[0];
00218             values[1] = res[1];
00219 
00220             env->ReleaseFloatArrayElements(array, res, 0);
00221         }
00222     }
00223 
00224     env->DeleteLocalRef(array);
00225 }
00226 
00227 void JNI::displayMessageOnOSD(const char *msg) {
00228     JNIEnv *env = JNI::getEnv();
00229     jstring java_msg = env->NewStringUTF(msg);
00230 
00231     env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
00232 
00233     if (env->ExceptionCheck()) {
00234         LOGE("Failed to display OSD message");
00235 
00236         env->ExceptionDescribe();
00237         env->ExceptionClear();
00238     }
00239 
00240     env->DeleteLocalRef(java_msg);
00241 }
00242 
00243 bool JNI::openUrl(const char *url) {
00244     bool success = true;
00245     JNIEnv *env = JNI::getEnv();
00246     jstring javaUrl = env->NewStringUTF(url);
00247 
00248     env->CallVoidMethod(_jobj, _MID_openUrl, javaUrl);
00249 
00250     if (env->ExceptionCheck()) {
00251         LOGE("Failed to open URL");
00252 
00253         env->ExceptionDescribe();
00254         env->ExceptionClear();
00255         success = false;
00256     }
00257 
00258     env->DeleteLocalRef(javaUrl);
00259     return success;
00260 }
00261 
00262 bool JNI::hasTextInClipboard() {
00263     bool hasText = false;
00264     JNIEnv *env = JNI::getEnv();
00265     hasText = env->CallBooleanMethod(_jobj, _MID_hasTextInClipboard);
00266 
00267     if (env->ExceptionCheck()) {
00268         LOGE("Failed to check the contents of the clipboard");
00269 
00270         env->ExceptionDescribe();
00271         env->ExceptionClear();
00272         hasText = true;
00273     }
00274 
00275     return hasText;
00276 }
00277 
00278 Common::String JNI::getTextFromClipboard() {
00279     JNIEnv *env = JNI::getEnv();
00280 
00281     jbyteArray javaText = (jbyteArray)env->CallObjectMethod(_jobj, _MID_getTextFromClipboard);
00282 
00283     if (env->ExceptionCheck()) {
00284         LOGE("Failed to retrieve text from the clipboard");
00285 
00286         env->ExceptionDescribe();
00287         env->ExceptionClear();
00288 
00289         return Common::String();
00290     }
00291 
00292     int len = env->GetArrayLength(javaText);
00293     char* buf = new char[len];
00294     env->GetByteArrayRegion(javaText, 0, len, reinterpret_cast<jbyte*>(buf));
00295     Common::String text(buf, len);
00296     delete[] buf;
00297 
00298     return text;
00299 }
00300 
00301 bool JNI::setTextInClipboard(const Common::String &text) {
00302     bool success = true;
00303     JNIEnv *env = JNI::getEnv();
00304 
00305     jbyteArray javaText = env->NewByteArray(text.size());
00306     env->SetByteArrayRegion(javaText, 0, text.size(), reinterpret_cast<const jbyte*>(text.c_str()));
00307 
00308     success = env->CallBooleanMethod(_jobj, _MID_setTextInClipboard, javaText);
00309 
00310     if (env->ExceptionCheck()) {
00311         LOGE("Failed to add text to the clipboard");
00312 
00313         env->ExceptionDescribe();
00314         env->ExceptionClear();
00315         success = false;
00316     }
00317 
00318     env->DeleteLocalRef(javaText);
00319     return success;
00320 }
00321 
00322 bool JNI::isConnectionLimited() {
00323     bool limited = false;
00324     JNIEnv *env = JNI::getEnv();
00325     limited = env->CallBooleanMethod(_jobj, _MID_isConnectionLimited);
00326 
00327     if (env->ExceptionCheck()) {
00328         LOGE("Failed to check whether connection's limited");
00329 
00330         env->ExceptionDescribe();
00331         env->ExceptionClear();
00332         limited = true;
00333     }
00334 
00335     return limited;
00336 }
00337 
00338 void JNI::setWindowCaption(const char *caption) {
00339     JNIEnv *env = JNI::getEnv();
00340     jstring java_caption = env->NewStringUTF(caption);
00341 
00342     env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption);
00343 
00344     if (env->ExceptionCheck()) {
00345         LOGE("Failed to set window caption");
00346 
00347         env->ExceptionDescribe();
00348         env->ExceptionClear();
00349     }
00350 
00351     env->DeleteLocalRef(java_caption);
00352 }
00353 
00354 void JNI::showVirtualKeyboard(bool enable) {
00355     JNIEnv *env = JNI::getEnv();
00356 
00357     env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable);
00358 
00359     if (env->ExceptionCheck()) {
00360         LOGE("Error trying to show virtual keyboard");
00361 
00362         env->ExceptionDescribe();
00363         env->ExceptionClear();
00364     }
00365 }
00366 
00367 void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
00368     JNIEnv *env = JNI::getEnv();
00369 
00370     s.add("ASSET", _asset_archive, priority, false);
00371 
00372     jobjectArray array =
00373         (jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives);
00374 
00375     if (env->ExceptionCheck()) {
00376         LOGE("Error finding system archive path");
00377 
00378         env->ExceptionDescribe();
00379         env->ExceptionClear();
00380 
00381         return;
00382     }
00383 
00384     jsize size = env->GetArrayLength(array);
00385     for (jsize i = 0; i < size; ++i) {
00386         jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
00387         const char *path = env->GetStringUTFChars(path_obj, 0);
00388 
00389         if (path != 0) {
00390             s.addDirectory(path, path, priority);
00391             env->ReleaseStringUTFChars(path_obj, path);
00392         }
00393 
00394         env->DeleteLocalRef(path_obj);
00395     }
00396 }
00397 
00398 bool JNI::initSurface() {
00399     JNIEnv *env = JNI::getEnv();
00400 
00401     jobject obj = env->CallObjectMethod(_jobj, _MID_initSurface);
00402 
00403     if (!obj || env->ExceptionCheck()) {
00404         LOGE("initSurface failed");
00405 
00406         env->ExceptionDescribe();
00407         env->ExceptionClear();
00408 
00409         return false;
00410     }
00411 
00412     _jobj_egl_surface = env->NewGlobalRef(obj);
00413 
00414     return true;
00415 }
00416 
00417 void JNI::deinitSurface() {
00418     JNIEnv *env = JNI::getEnv();
00419 
00420     env->CallVoidMethod(_jobj, _MID_deinitSurface);
00421 
00422     if (env->ExceptionCheck()) {
00423         LOGE("deinitSurface failed");
00424 
00425         env->ExceptionDescribe();
00426         env->ExceptionClear();
00427     }
00428 
00429     env->DeleteGlobalRef(_jobj_egl_surface);
00430     _jobj_egl_surface = 0;
00431 }
00432 
00433 void JNI::setAudioPause() {
00434     JNIEnv *env = JNI::getEnv();
00435 
00436     env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_flush);
00437 
00438     if (env->ExceptionCheck()) {
00439         LOGE("Error flushing AudioTrack");
00440 
00441         env->ExceptionDescribe();
00442         env->ExceptionClear();
00443     }
00444 
00445     env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause);
00446 
00447     if (env->ExceptionCheck()) {
00448         LOGE("Error setting AudioTrack: pause");
00449 
00450         env->ExceptionDescribe();
00451         env->ExceptionClear();
00452     }
00453 }
00454 
00455 void JNI::setAudioPlay() {
00456     JNIEnv *env = JNI::getEnv();
00457 
00458     env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_play);
00459 
00460     if (env->ExceptionCheck()) {
00461         LOGE("Error setting AudioTrack: play");
00462 
00463         env->ExceptionDescribe();
00464         env->ExceptionClear();
00465     }
00466 }
00467 
00468 void JNI::setAudioStop() {
00469     JNIEnv *env = JNI::getEnv();
00470 
00471     env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_stop);
00472 
00473     if (env->ExceptionCheck()) {
00474         LOGE("Error setting AudioTrack: stop");
00475 
00476         env->ExceptionDescribe();
00477         env->ExceptionClear();
00478     }
00479 }
00480 
00481 // natives for the dark side
00482 
00483 void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
00484                 jobject egl, jobject egl_display,
00485                 jobject at, jint audio_sample_rate, jint audio_buffer_size) {
00486     LOGI("%s", gScummVMFullVersion);
00487 
00488     assert(!_system);
00489 
00490     pause = false;
00491     // initial value of zero!
00492     sem_init(&pause_sem, 0, 0);
00493 
00494     _asset_archive = new AndroidAssetArchive(asset_manager);
00495     assert(_asset_archive);
00496 
00497     _system = new OSystem_Android(audio_sample_rate, audio_buffer_size);
00498     assert(_system);
00499 
00500     // weak global ref to allow class to be unloaded
00501     // ... except dalvik implements NewWeakGlobalRef only on froyo
00502     //_jobj = env->NewWeakGlobalRef(self);
00503 
00504     _jobj = env->NewGlobalRef(self);
00505 
00506     jclass cls = env->GetObjectClass(_jobj);
00507 
00508 #define FIND_METHOD(prefix, name, signature) do {                           \
00509         _MID_ ## prefix ## name = env->GetMethodID(cls, #name, signature);  \
00510         if (_MID_ ## prefix ## name == 0)                                   \
00511             return;                                                         \
00512     } while (0)
00513 
00514     FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V");
00515     FIND_METHOD(, getDPI, "([F)V");
00516     FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
00517     FIND_METHOD(, openUrl, "(Ljava/lang/String;)V");
00518     FIND_METHOD(, hasTextInClipboard, "()Z");
00519     FIND_METHOD(, getTextFromClipboard, "()[B");
00520     FIND_METHOD(, setTextInClipboard, "([B)Z");
00521     FIND_METHOD(, isConnectionLimited, "()Z");
00522     FIND_METHOD(, showVirtualKeyboard, "(Z)V");
00523     FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
00524     FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
00525     FIND_METHOD(, deinitSurface, "()V");
00526 
00527     _jobj_egl = env->NewGlobalRef(egl);
00528     _jobj_egl_display = env->NewGlobalRef(egl_display);
00529 
00530     cls = env->GetObjectClass(_jobj_egl);
00531 
00532     FIND_METHOD(EGL10_, eglSwapBuffers,
00533                 "(Ljavax/microedition/khronos/egl/EGLDisplay;"
00534                 "Ljavax/microedition/khronos/egl/EGLSurface;)Z");
00535 
00536     _jobj_audio_track = env->NewGlobalRef(at);
00537 
00538     cls = env->GetObjectClass(_jobj_audio_track);
00539 
00540     FIND_METHOD(AudioTrack_, flush, "()V");
00541     FIND_METHOD(AudioTrack_, pause, "()V");
00542     FIND_METHOD(AudioTrack_, play, "()V");
00543     FIND_METHOD(AudioTrack_, stop, "()V");
00544     FIND_METHOD(AudioTrack_, write, "([BII)I");
00545 
00546 #undef FIND_METHOD
00547 
00548     g_system = _system;
00549 }
00550 
00551 void JNI::destroy(JNIEnv *env, jobject self) {
00552     delete _asset_archive;
00553     _asset_archive = 0;
00554 
00555     delete _system;
00556     g_system = 0;
00557     _system = 0;
00558 
00559     sem_destroy(&pause_sem);
00560 
00561     // see above
00562     //JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
00563 
00564     JNI::getEnv()->DeleteGlobalRef(_jobj_egl_display);
00565     JNI::getEnv()->DeleteGlobalRef(_jobj_egl);
00566     JNI::getEnv()->DeleteGlobalRef(_jobj_audio_track);
00567     JNI::getEnv()->DeleteGlobalRef(_jobj);
00568 }
00569 
00570 void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height) {
00571     egl_surface_width = width;
00572     egl_surface_height = height;
00573     surface_changeid++;
00574 }
00575 
00576 jint JNI::main(JNIEnv *env, jobject self, jobjectArray args) {
00577     assert(_system);
00578 
00579     const int MAX_NARGS = 32;
00580     int res = -1;
00581 
00582     int argc = env->GetArrayLength(args);
00583     if (argc > MAX_NARGS) {
00584         throwByName(env, "java/lang/IllegalArgumentException",
00585                     "too many arguments");
00586         return 0;
00587     }
00588 
00589     char *argv[MAX_NARGS];
00590 
00591     // note use in cleanup loop below
00592     int nargs;
00593 
00594     for (nargs = 0; nargs < argc; ++nargs) {
00595         jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
00596 
00597         if (arg == 0) {
00598             argv[nargs] = 0;
00599         } else {
00600             const char *cstr = env->GetStringUTFChars(arg, 0);
00601 
00602             argv[nargs] = const_cast<char *>(cstr);
00603 
00604             // exception already thrown?
00605             if (cstr == 0)
00606                 goto cleanup;
00607         }
00608 
00609         env->DeleteLocalRef(arg);
00610     }
00611 
00612     LOGI("Entering scummvm_main with %d args", argc);
00613 
00614     res = scummvm_main(argc, argv);
00615 
00616     LOGI("scummvm_main exited with code %d", res);
00617 
00618     _system->quit();
00619 
00620 cleanup:
00621     nargs--;
00622 
00623     for (int i = 0; i < nargs; ++i) {
00624         if (argv[i] == 0)
00625             continue;
00626 
00627         jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
00628 
00629         // Exception already thrown?
00630         if (arg == 0)
00631             return res;
00632 
00633         env->ReleaseStringUTFChars(arg, argv[i]);
00634         env->DeleteLocalRef(arg);
00635     }
00636 
00637     return res;
00638 }
00639 
00640 void JNI::pushEvent(JNIEnv *env, jobject self, int type, int arg1, int arg2,
00641                     int arg3, int arg4, int arg5, int arg6) {
00642     // drop events until we're ready and after we quit
00643     if (!_ready_for_events) {
00644         LOGW("dropping event");
00645         return;
00646     }
00647 
00648     assert(_system);
00649 
00650     _system->pushEvent(type, arg1, arg2, arg3, arg4, arg5, arg6);
00651 }
00652 
00653 void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
00654     assert(_system);
00655 
00656     _system->enableZoning(enable);
00657 }
00658 
00659 void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
00660     if (!_system)
00661         return;
00662 
00663     if (g_engine) {
00664         LOGD("pauseEngine: %d", value);
00665 
00666         g_engine->pauseEngine(value);
00667 
00668         if (value &&
00669                 g_engine->hasFeature(Engine::kSupportsSavingDuringRuntime) &&
00670                 g_engine->canSaveGameStateCurrently())
00671             g_engine->saveGameState(0, "Android parachute");
00672     }
00673 
00674     pause = value;
00675 
00676     if (!pause) {
00677         // wake up all threads
00678         for (uint i = 0; i < 3; ++i)
00679             sem_post(&pause_sem);
00680     }
00681 }
00682 
00683 jstring JNI::getCurrentCharset(JNIEnv *env, jobject self) {
00684 #ifdef USE_TRANSLATION
00685     if (TransMan.getCurrentCharset() != "ASCII") {
00686         return env->NewStringUTF(TransMan.getCurrentCharset().c_str());
00687     }
00688 #endif
00689     return env->NewStringUTF("ISO-8859-1");
00690 }
00691 
00692 #endif


Generated on Sat May 18 2019 05:01:06 for ResidualVM by doxygen 1.7.1
curved edge   curved edge