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