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