#include #include #include #include #include #include #include #include extern "C" { #include } #include "log.h" #include "jni_utils.h" #include "event.h" #define ARRAYLEN(a) (sizeof(a)/sizeof(a[0])) extern "C" { jni_func(void, create, jobject appctx); jni_func(void, init); jni_func(void, destroy); jni_func(void, command, jobjectArray jarray); }; JavaVM *g_vm; mpv_handle *g_mpv; std::atomic g_event_thread_request_exit(false); static pthread_t event_thread_id; static void prepare_environment(JNIEnv *env, jobject appctx) { setlocale(LC_NUMERIC, "C"); if (!env->GetJavaVM(&g_vm) && g_vm) av_jni_set_java_vm(g_vm, NULL); jobject global_appctx = env->NewGlobalRef(appctx); if (global_appctx) av_jni_set_android_app_ctx(global_appctx, NULL); init_methods_cache(env); } jni_func(void, create, jobject appctx) { prepare_environment(env, appctx); if (g_mpv) die("mpv is already initialized"); g_mpv = mpv_create(); if (!g_mpv) die("context init failed"); // use terminal log level but request verbose messages // this way --msg-level can be used to adjust later mpv_request_log_messages(g_mpv, "terminal-default"); mpv_set_option_string(g_mpv, "msg-level", "all=v"); } jni_func(void, init) { if (!g_mpv) die("mpv is not created"); if (mpv_initialize(g_mpv) < 0) die("mpv init failed"); g_event_thread_request_exit = false; if (pthread_create(&event_thread_id, NULL, event_thread, NULL) != 0) die("thread create failed"); pthread_setname_np(event_thread_id, "event_thread"); } jni_func(void, destroy) { if (!g_mpv) { ALOGV("mpv destroy called but it's already destroyed"); return; } // poke event thread and wait for it to exit g_event_thread_request_exit = true; mpv_wakeup(g_mpv); pthread_join(event_thread_id, NULL); mpv_terminate_destroy(g_mpv); g_mpv = NULL; } jni_func(void, command, jobjectArray jarray) { CHECK_MPV_INIT(); const char *arguments[128] = {0}; int len = env->GetArrayLength(jarray); if (len >= ARRAYLEN(arguments)) die("too many command arguments"); for (int i = 0; i < len; ++i) arguments[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(jarray, i), NULL); mpv_command(g_mpv, arguments); for (int i = 0; i < len; ++i) env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(jarray, i), arguments[i]); }