#include #include #include #include #include #include "Renderer.h" #include "Preloader.h" #define LOG_TAG "NativeRenderer" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) // 전역 변수 Renderer* renderer = nullptr; Preloader* preloader = nullptr; JavaVM* g_vm = nullptr; jobject g_callback_obj = nullptr; jmethodID g_callback_method_id = nullptr; // JNI_OnLoad 함수 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { g_vm = vm; return JNI_VERSION_1_6; } void callNextMediaCallback() { JNIEnv* env; bool isAttached = false; // 현재 스레드가 JVM에 연결되어 있지 않다면 연결 if (g_vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { g_vm->AttachCurrentThread(&env, nullptr); isAttached = true; } if (g_callback_obj && g_callback_method_id) { env->CallVoidMethod(g_callback_obj, g_callback_method_id); } // 이전에 연결되지 않았다면 연결 해제 if (isAttached) { g_vm->DetachCurrentThread(); } } extern "C" { JNIEXPORT jboolean JNICALL Java_bums_lunatic_launcher_wall_NativeRenderer_nativeInit(JNIEnv* env, jobject) { if (!renderer) { renderer = new Renderer(); } if (!preloader) { preloader = new Preloader(); } LOGI("Native renderer and preloader initialized."); return JNI_TRUE; } JNIEXPORT void JNICALL Java_bums_lunatic_launcher_wall_NativeRenderer_nativeRender(JNIEnv* env, jobject, jobject surface) { if (!renderer || !surface) return; ANativeWindow* window = ANativeWindow_fromSurface(env, surface); if (!window) { LOGE("Could not get ANativeWindow from Surface."); return; } renderer->renderFrame(window); ANativeWindow_release(window); } JNIEXPORT void JNICALL Java_bums_lunatic_launcher_wall_NativeRenderer_nativeDestroy(JNIEnv* env, jobject) { if (renderer) { delete renderer; renderer = nullptr; } if (preloader) { delete preloader; preloader = nullptr; } if (g_callback_obj) { env->DeleteGlobalRef(g_callback_obj); g_callback_obj = nullptr; } LOGI("Native renderer destroyed and memory freed."); } JNIEXPORT void JNICALL Java_bums_lunatic_launcher_wall_NativeRenderer_nativeSetCurrentMedia(JNIEnv* env, jobject, jint fd) { if (!renderer) return; // 경로 대신 파일 디스크립터를 전달 renderer->setNextMedia(fd); } JNIEXPORT void JNICALL Java_bums_lunatic_launcher_wall_NativeRenderer_nativeStartNextPreload(JNIEnv* env, jobject, jint fd) { if (!preloader) return; // 경로 대신 파일 디스크립터를 전달 preloader->startNextPreload(fd); } JNIEXPORT void JNICALL Java_bums_lunatic_launcher_wall_NativeRenderer_nativeSetNextMediaCallback(JNIEnv* env, jobject, jobject callback) { jclass clazz = env->GetObjectClass(callback); g_callback_method_id = env->GetMethodID(clazz, "onNextMediaRequested", "()V"); g_callback_obj = env->NewGlobalRef(callback); if (!g_callback_method_id) { LOGE("Could not find onNextMediaRequested method ID."); } } }