twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

android.c (6045B)


      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build android
      6 
      7 #include <android/log.h>
      8 #include <dlfcn.h>
      9 #include <errno.h>
     10 #include <fcntl.h>
     11 #include <stdint.h>
     12 #include <string.h>
     13 #include "_cgo_export.h"
     14 
     15 #define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "Go", __VA_ARGS__)
     16 #define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__)
     17 
     18 static jclass current_class;
     19 
     20 static jclass find_class(JNIEnv *env, const char *class_name) {
     21 	jclass clazz = (*env)->FindClass(env, class_name);
     22 	if (clazz == NULL) {
     23 		(*env)->ExceptionClear(env);
     24 		LOG_FATAL("cannot find %s", class_name);
     25 		return NULL;
     26 	}
     27 	return clazz;
     28 }
     29 
     30 static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
     31 	jmethodID m = (*env)->GetMethodID(env, clazz, name, sig);
     32 	if (m == 0) {
     33 		(*env)->ExceptionClear(env);
     34 		LOG_FATAL("cannot find method %s %s", name, sig);
     35 		return 0;
     36 	}
     37 	return m;
     38 }
     39 
     40 static jmethodID find_static_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
     41 	jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig);
     42 	if (m == 0) {
     43 		(*env)->ExceptionClear(env);
     44 		LOG_FATAL("cannot find method %s %s", name, sig);
     45 		return 0;
     46 	}
     47 	return m;
     48 }
     49 
     50 static jmethodID key_rune_method;
     51 
     52 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
     53 	JNIEnv* env;
     54 	if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
     55 		return -1;
     56 	}
     57 
     58 	return JNI_VERSION_1_6;
     59 }
     60 
     61 static int main_running = 0;
     62 
     63 // Entry point from our subclassed NativeActivity.
     64 //
     65 // By here, the Go runtime has been initialized (as we are running in
     66 // -buildmode=c-shared) but the first time it is called, Go's main.main
     67 // hasn't been called yet.
     68 //
     69 // The Activity may be created and destroyed multiple times throughout
     70 // the life of a single process. Each time, onCreate is called.
     71 void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) {
     72 	if (!main_running) {
     73 		JNIEnv* env = activity->env;
     74 
     75 		// Note that activity->clazz is mis-named.
     76 		current_class = (*env)->GetObjectClass(env, activity->clazz);
     77 		current_class = (*env)->NewGlobalRef(env, current_class);
     78 		key_rune_method = find_static_method(env, current_class, "getRune", "(III)I");
     79 
     80 		setCurrentContext(activity->vm, (*env)->NewGlobalRef(env, activity->clazz));
     81 
     82 		// Set TMPDIR.
     83 		jmethodID gettmpdir = find_method(env, current_class, "getTmpdir", "()Ljava/lang/String;");
     84 		jstring jpath = (jstring)(*env)->CallObjectMethod(env, activity->clazz, gettmpdir, NULL);
     85 		const char* tmpdir = (*env)->GetStringUTFChars(env, jpath, NULL);
     86 		if (setenv("TMPDIR", tmpdir, 1) != 0) {
     87 			LOG_INFO("setenv(\"TMPDIR\", \"%s\", 1) failed: %d", tmpdir, errno);
     88 		}
     89 		(*env)->ReleaseStringUTFChars(env, jpath, tmpdir);
     90 
     91 		// Call the Go main.main.
     92 		uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main");
     93 		if (!mainPC) {
     94 			LOG_FATAL("missing main.main");
     95 		}
     96 		callMain(mainPC);
     97 		main_running = 1;
     98 	}
     99 
    100 	// These functions match the methods on Activity, described at
    101 	// http://developer.android.com/reference/android/app/Activity.html
    102 	//
    103 	// Note that onNativeWindowResized is not called on resize. Avoid it.
    104 	// https://code.google.com/p/android/issues/detail?id=180645
    105 	activity->callbacks->onStart = onStart;
    106 	activity->callbacks->onResume = onResume;
    107 	activity->callbacks->onSaveInstanceState = onSaveInstanceState;
    108 	activity->callbacks->onPause = onPause;
    109 	activity->callbacks->onStop = onStop;
    110 	activity->callbacks->onDestroy = onDestroy;
    111 	activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
    112 	activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
    113 	activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
    114 	activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
    115 	activity->callbacks->onInputQueueCreated = onInputQueueCreated;
    116 	activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
    117 	activity->callbacks->onConfigurationChanged = onConfigurationChanged;
    118 	activity->callbacks->onLowMemory = onLowMemory;
    119 
    120 	onCreate(activity);
    121 }
    122 
    123 // TODO(crawshaw): Test configuration on more devices.
    124 static const EGLint RGB_888[] = {
    125 	EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    126 	EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    127 	EGL_BLUE_SIZE, 8,
    128 	EGL_GREEN_SIZE, 8,
    129 	EGL_RED_SIZE, 8,
    130 	EGL_DEPTH_SIZE, 16,
    131 	EGL_CONFIG_CAVEAT, EGL_NONE,
    132 	EGL_NONE
    133 };
    134 
    135 EGLDisplay display = NULL;
    136 EGLSurface surface = NULL;
    137 
    138 static char* initEGLDisplay() {
    139 	display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    140 	if (!eglInitialize(display, 0, 0)) {
    141 		return "EGL initialize failed";
    142 	}
    143 	return NULL;
    144 }
    145 
    146 char* createEGLSurface(ANativeWindow* window) {
    147 	char* err;
    148 	EGLint numConfigs, format;
    149 	EGLConfig config;
    150 	EGLContext context;
    151 
    152 	if (display == 0) {
    153 		if ((err = initEGLDisplay()) != NULL) {
    154 			return err;
    155 		}
    156 	}
    157 
    158 	if (!eglChooseConfig(display, RGB_888, &config, 1, &numConfigs)) {
    159 		return "EGL choose RGB_888 config failed";
    160 	}
    161 	if (numConfigs <= 0) {
    162 		return "EGL no config found";
    163 	}
    164 
    165 	eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
    166 	if (ANativeWindow_setBuffersGeometry(window, 0, 0, format) != 0) {
    167 		return "EGL set buffers geometry failed";
    168 	}
    169 
    170 	surface = eglCreateWindowSurface(display, config, window, NULL);
    171 	if (surface == EGL_NO_SURFACE) {
    172 		return "EGL create surface failed";
    173 	}
    174 
    175 	const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    176 	context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
    177 
    178 	if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
    179 		return "eglMakeCurrent failed";
    180 	}
    181 	return NULL;
    182 }
    183 
    184 char* destroyEGLSurface() {
    185 	if (!eglDestroySurface(display, surface)) {
    186 		return "EGL destroy surface failed";
    187 	}
    188 	return NULL;
    189 }
    190 
    191 int32_t getKeyRune(JNIEnv* env, AInputEvent* e) {
    192 	return (int32_t)(*env)->CallStaticIntMethod(
    193 		env,
    194 		current_class,
    195 		key_rune_method,
    196 		AInputEvent_getDeviceId(e),
    197 		AKeyEvent_getKeyCode(e),
    198 		AKeyEvent_getMetaState(e)
    199 	);
    200 }