android/testproject/jni/app-android.cpp
author Paul Hunkin <paul@bieh.net>
Sat, 14 Aug 2010 12:35:21 +1200
changeset 4724 d86332c0fb9b
parent 4723 74da47b2f5b7
child 4726 9076cdb027af
permissions -rw-r--r--
Working on the sound system
     1 /*******************************************************************************
     2                                Headers
     3 *******************************************************************************/
     4 #include <jni.h>
     5 #include <sys/time.h>
     6 #include <time.h>
     7 #include <android/log.h>
     8 #include <stdint.h>
     9 
    10 #include <stdio.h>
    11 #include <stdlib.h>
    12 #include <math.h>
    13 
    14 #include <pthread.h>
    15 
    16 #include "importgl.h"
    17 #include "egl.h"
    18 
    19 /*******************************************************************************
    20                                Globals
    21 *******************************************************************************/
    22 static long _getTime(void){
    23 	struct timeval  now;
    24 	gettimeofday(&now, NULL);
    25 	return (long)(now.tv_sec*1000 + now.tv_usec/1000);
    26 }
    27 
    28 JNIEnv* mEnv = NULL;
    29 JNIEnv* mAudioThreadEnv = NULL; //See the note below for why this is necessary
    30 JavaVM* mVM = NULL;
    31 
    32 //Main activity
    33 jclass mActivityInstance;
    34 
    35 //method signatures
    36 jmethodID midCreateGLContext;
    37 jmethodID midFlipBuffers;
    38 jmethodID midEnableFeature;
    39 jmethodID midUpdateAudio;
    40 
    41 extern "C" int SDL_main();
    42 extern "C" int Android_OnKeyDown(int keycode);
    43 extern "C" int Android_OnKeyUp(int keycode);
    44 extern "C" void Android_SetScreenResolution(int width, int height);
    45 extern "C" void Android_OnResize(int width, int height, int format);
    46 extern "C" int SDL_SendQuit();
    47 extern "C" void Android_EnableFeature(int featureid, bool enabled);
    48 
    49 //If we're not the active app, don't try to render
    50 bool bRenderingEnabled = false;
    51 
    52 //Feature IDs
    53 static const int FEATURE_AUDIO = 1;
    54 static const int FEATURE_ACCEL = 2;
    55 
    56 //Accelerometer data storage
    57 float fLastAccelerometer[3];
    58 
    59 
    60 /*******************************************************************************
    61                  Functions called by JNI
    62 *******************************************************************************/	
    63 
    64 //Library init
    65 extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved){
    66 
    67     JNIEnv* env = NULL;
    68     jint result = -1;
    69 
    70     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    71         return result;
    72     }
    73 
    74     mEnv = env;
    75 
    76     __android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: OnLoad");
    77 
    78     jclass cls = mEnv->FindClass ("org/libsdl/android/SDLActivity"); 
    79     mActivityInstance = cls;
    80     midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V");
    81     midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V");
    82     midEnableFeature = mEnv->GetStaticMethodID(cls,"enableFeature","(II)V");
    83     midUpdateAudio = mEnv->GetStaticMethodID(cls,"updateAudio","([B)V");
    84 
    85     if(!midCreateGLContext || !midFlipBuffers || !midEnableFeature ||
    86         !midUpdateAudio){
    87         __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Bad mids\n");
    88     }else{
    89         __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Good mids\n");
    90     }
    91     
    92     return JNI_VERSION_1_4;
    93 }
    94 
    95 //Start up the SDL app
    96 extern "C" void Java_org_libsdl_android_SDLActivity_nativeInit( JNIEnv* env, 
    97                                                                 jobject obj ){ 
    98                                                                    
    99 	__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Native Init");
   100 
   101 	mEnv = env;
   102 	bRenderingEnabled = true;
   103 
   104 	Android_EnableFeature(FEATURE_ACCEL, true);
   105 
   106     SDL_main();
   107 }
   108 
   109 //Keydown
   110 extern "C" void Java_org_libsdl_android_SDLActivity_onNativeKeyDown(JNIEnv* env, 
   111                jobject obj, jint keycode){
   112     
   113     int r = Android_OnKeyDown(keycode);
   114     __android_log_print(ANDROID_LOG_INFO, "SDL", 
   115                         "SDL: native key down %d, %d\n", keycode, r);
   116                         
   117 }
   118 
   119 //Keyup
   120 extern "C" void Java_org_libsdl_android_SDLActivity_onNativeKeyUp(JNIEnv* env, 
   121                jobject obj, jint keycode){
   122     
   123     int r = Android_OnKeyUp(keycode);
   124     __android_log_print(ANDROID_LOG_INFO, "SDL", 
   125                         "SDL: native key up %d, %d\n", keycode, r);
   126                         
   127 }
   128 
   129 //Touch
   130 extern "C" void Java_org_libsdl_android_SDLActivity_onNativeTouch(JNIEnv* env, 
   131                jobject obj, jint action, jfloat x, jfloat y, jfloat p){
   132 
   133     __android_log_print(ANDROID_LOG_INFO, "SDL", 
   134                         "SDL: native touch event %d @ %f/%f, pressure %f\n", 
   135                         action, x, y, p);
   136 
   137     //TODO: Pass this off to the SDL multitouch stuff
   138                         
   139 }
   140 
   141 //Quit
   142 extern "C" void Java_org_libsdl_android_SDLActivity_nativeQuit( JNIEnv*  env, 
   143                                                                 jobject obj ){    
   144 
   145     //Stop rendering as we're no longer in the foreground
   146 	bRenderingEnabled = false;
   147 
   148     //Inject a SDL_QUIT event
   149     int r = SDL_SendQuit();
   150 
   151     __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Native quit %d", r);        
   152 }
   153 
   154 //Screen size
   155 extern "C" void Java_org_libsdl_android_SDLActivity_nativeSetScreenSize(
   156                 JNIEnv*  env, jobject obj, jint width, jint height){
   157 
   158     __android_log_print(ANDROID_LOG_INFO, "SDL", 
   159                         "SDL: Set screen size on init: %d/%d\n", width, height);
   160     Android_SetScreenResolution(width, height);
   161                         
   162 }
   163 
   164 //Resize
   165 extern "C" void Java_org_libsdl_android_SDLActivity_onNativeResize(
   166                                         JNIEnv*  env, jobject obj, jint width, 
   167                                         jint height, jint format){
   168     Android_OnResize(width, height, format);
   169 }
   170 
   171 extern "C" void Java_org_libsdl_android_SDLActivity_onNativeAccel(
   172                                         JNIEnv*  env, jobject obj,
   173                                         jfloat x, jfloat y, jfloat z){
   174     fLastAccelerometer[0] = x;
   175     fLastAccelerometer[1] = y;
   176     fLastAccelerometer[2] = z;   
   177 }
   178 
   179 
   180 
   181 /*******************************************************************************
   182              Functions called by SDL into Java
   183 *******************************************************************************/
   184 extern "C" void Android_CreateContext(){
   185 	__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: sdl_create_context()\n");
   186 
   187 	bRenderingEnabled = true;
   188 
   189     mEnv->CallStaticVoidMethod(mActivityInstance, midCreateGLContext ); 
   190 }
   191 
   192 extern "C" void Android_Render(){
   193 
   194     if(!bRenderingEnabled){
   195         return;
   196     }
   197 
   198     //When we get here, we've accumulated a full frame    
   199     mEnv->CallStaticVoidMethod(mActivityInstance, midFlipBuffers ); 
   200 }
   201 
   202 extern "C" void Android_EnableFeature(int featureid, bool enabled){
   203 
   204     mEnv->CallStaticVoidMethod(mActivityInstance, midEnableFeature, 
   205                                 featureid, (int)enabled); 
   206 }
   207 
   208 extern "C" void Android_UpdateAudioBuffer(unsigned char *buf, int len){
   209 
   210     //Annoyingly we can't just call into Java from any thread. Because the audio
   211     //callback is dispatched from the SDL audio thread (that wasn't made from
   212     //java, we have to do some magic here to let the JVM know about the thread.
   213     //Because everything it touches on the Java side is static anyway, it's 
   214     //not a big deal, just annoying.
   215     if(!mAudioThreadEnv){
   216         __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Need to set up audio thread env\n");
   217 
   218         mJVM->AttachCurrentThread(&mAudioThreadEnv, NULL);
   219 
   220         __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: ok\n");
   221     }
   222     
   223     jbyteArray arr = mAudioThreadEnv->NewByteArray(len);
   224 
   225     //blah. We probably should rework this so we avoid the copy. 
   226     mAudioThreadEnv->SetByteArrayRegion(arr, 0, len, (jbyte *)buf);
   227     
   228     __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: copied\n");
   229 
   230     mAudioThreadEnv->CallStaticVoidMethod(  mActivityInstance, 
   231                                             midUpdateAudio, arr );
   232 
   233     __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: invoked\n");
   234     
   235 }
   236