android/project/jni/android-support.cpp
author Paul Hunkin <paul@bieh.net>
Tue, 17 Aug 2010 15:35:56 +1200
changeset 4726 9076cdb027af
child 4953 4f40b11e1045
permissions -rw-r--r--
Cleanups.

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