packages feed

reflex-dom-0.4: cbits/MainWidget.c

#include <jni.h>
#include <assert.h>
#include <stdlib.h>
#include <android/log.h>
#include <HaskellActivity.h>
#include "MainWidget.h"

jobject Reflex_Dom_Android_MainWidget_start(jobject activity, const char *url, const JSaddleCallbacks *jsaddleCallbacks) {
  assert(activity);
  assert(url);

  JNIEnv *env;
  jint attachResult = (*HaskellActivity_jvm)->AttachCurrentThread(HaskellActivity_jvm, &env, NULL);
  assert(attachResult == JNI_OK);

  jclass cls = (*env)->FindClass(env, "org/reflexfrp/reflexdom/MainWidget");
  assert(cls);
  jmethodID startMainWidget = (*env)->GetStaticMethodID(env, cls, "startMainWidget", "(Lsystems/obsidian/HaskellActivity;Ljava/lang/String;JLjava/lang/String;)Ljava/lang/Object;");
  assert(startMainWidget);

  jstring jurl = (*env)->NewStringUTF(env, url);
  assert(jurl);
  jstring initialJS = (*env)->NewStringUTF(env, jsaddleCallbacks->jsaddleJsData);
  jobject result = (*env)->CallStaticObjectMethod(env, cls, startMainWidget, activity, jurl, (jlong)jsaddleCallbacks, initialJS);
  (*env)->DeleteLocalRef(env, initialJS);
  if((*env)->ExceptionOccurred(env)) {
    __android_log_write(ANDROID_LOG_DEBUG, "MainWidget", "startMainWidget exception");
    (*env)->ExceptionDescribe(env);
  }
  return (*env)->NewGlobalRef(env, result);
}

void Reflex_Dom_Android_MainWidget_runJS(jobject jsExecutor, const char* js, size_t js_len) {
  JNIEnv *env;
  jint attachResult = (*HaskellActivity_jvm)->AttachCurrentThread(HaskellActivity_jvm, &env, NULL);
  assert (attachResult == JNI_OK);

  (*env)->PushLocalFrame(env, 5);

  //TODO: Don't search for this method every time
  jclass cls = (*env)->GetObjectClass(env, jsExecutor);
  assert(cls);
  jmethodID evaluateJavascript = (*env)->GetMethodID(env, cls, "evaluateJavascript", "([B)V");
  assert(evaluateJavascript);
  jbyteArray js_str = (*env)->NewByteArray(env, js_len);
  (*env)->SetByteArrayRegion(env, js_str, 0, js_len, (const jbyte*)js);
  (*env)->CallVoidMethod(env, jsExecutor, evaluateJavascript, js_str, 0);
  if((*env)->ExceptionOccurred(env)) {
    __android_log_write(ANDROID_LOG_DEBUG, "MainWidget", "runJS exception");
    (*env)->ExceptionDescribe(env);
  }

  (*env)->PopLocalFrame(env, 0);
}

JNIEXPORT void JNICALL Java_org_reflexfrp_reflexdom_MainWidget_00024JSaddleCallbacks_startProcessing (JNIEnv *env, jobject thisObj, jlong callbacksLong) {
  const JSaddleCallbacks *callbacks = (const JSaddleCallbacks *)callbacksLong;
  (*(callbacks->jsaddleStart))();
  return;
}

JNIEXPORT void JNICALL Java_org_reflexfrp_reflexdom_MainWidget_00024JSaddleCallbacks_processMessage (JNIEnv *env, jobject thisObj, jlong callbacksLong, jbyteArray msg) {
  const JSaddleCallbacks *callbacks = (const JSaddleCallbacks *)callbacksLong;

  jbyte *msg_str = (*env)->GetByteArrayElements(env, msg, NULL);
  jsize msg_str_len = (*env)->GetArrayLength(env, msg);
  (*(callbacks->jsaddleResult))(msg_str, msg_str_len);
  (*env)->ReleaseByteArrayElements(env, msg, msg_str, JNI_ABORT);
  return;
}

JNIEXPORT jbyteArray JNICALL Java_org_reflexfrp_reflexdom_MainWidget_00024JSaddleCallbacks_processSyncMessage (JNIEnv *env, jobject thisObj, jlong callbacksLong, jbyteArray msg) {
  const JSaddleCallbacks *callbacks = (const JSaddleCallbacks *)callbacksLong;

  char const *next_str;
  size_t next_str_len;

  jbyte *msg_str = (*env)->GetByteArrayElements(env, msg, NULL);
  jsize msg_str_len = (*env)->GetArrayLength(env, msg);
  (*(callbacks->jsaddleSyncResult))(msg_str, msg_str_len, &next_str, &next_str_len);
  (*env)->ReleaseByteArrayElements(env, msg, msg_str, JNI_ABORT);

  jbyteArray next_jstr = (*env)->NewByteArray(env, next_str_len);
  (*env)->SetByteArrayRegion(env, next_jstr, 0, next_str_len, next_str);

  free(next_str);

  return next_jstr;
}