Mercurial > sdl-ios-xcode
comparison android-project/src/org/libsdl/app/SDLActivity.java @ 4965:91d0085b7560
Added the Android project and lots of info to README.android
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 06 Jan 2011 17:12:31 -0800 |
parents | |
children | d9fdff945ec9 |
comparison
equal
deleted
inserted
replaced
4964:6c645018741e | 4965:91d0085b7560 |
---|---|
1 package org.libsdl.app; | |
2 | |
3 import javax.microedition.khronos.egl.EGLConfig; | |
4 import javax.microedition.khronos.opengles.GL10; | |
5 import javax.microedition.khronos.egl.*; | |
6 | |
7 import android.app.*; | |
8 import android.content.*; | |
9 import android.view.*; | |
10 import android.os.*; | |
11 import android.util.Log; | |
12 import android.graphics.*; | |
13 import android.text.method.*; | |
14 import android.text.*; | |
15 import android.media.*; | |
16 import android.hardware.*; | |
17 import android.content.*; | |
18 | |
19 import java.lang.*; | |
20 | |
21 | |
22 /** | |
23 SDL Activity | |
24 */ | |
25 public class SDLActivity extends Activity { | |
26 | |
27 //Main components | |
28 private static SDLActivity mSingleton; | |
29 private static SDLSurface mSurface; | |
30 | |
31 //Audio | |
32 private static AudioTrack mAudioTrack; | |
33 private static boolean bAudioIsEnabled; | |
34 | |
35 //Sensors | |
36 private static boolean bAccelIsEnabled; | |
37 | |
38 //feature IDs. Must match up on the C side as well. | |
39 private static int FEATURE_AUDIO = 1; | |
40 private static int FEATURE_ACCEL = 2; | |
41 | |
42 //Load the .so | |
43 static { | |
44 System.loadLibrary("SDL"); | |
45 System.loadLibrary("main"); | |
46 } | |
47 | |
48 //Setup | |
49 protected void onCreate(Bundle savedInstanceState) { | |
50 super.onCreate(savedInstanceState); | |
51 | |
52 //So we can call stuff from static callbacks | |
53 mSingleton = this; | |
54 | |
55 //Set up the surface | |
56 mSurface = new SDLSurface(getApplication()); | |
57 setContentView(mSurface); | |
58 SurfaceHolder holder = mSurface.getHolder(); | |
59 holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); | |
60 | |
61 } | |
62 | |
63 //Audio | |
64 public static boolean initAudio(){ | |
65 | |
66 //blah. Hardcoded things are bad. FIXME when we have more sound stuff | |
67 //working properly. | |
68 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, | |
69 11025, | |
70 AudioFormat.CHANNEL_CONFIGURATION_MONO, | |
71 AudioFormat.ENCODING_PCM_8BIT, | |
72 2048, | |
73 AudioTrack.MODE_STREAM); | |
74 bAudioIsEnabled = true; | |
75 return true; | |
76 } | |
77 | |
78 //Accel | |
79 public static boolean initAccel(){ | |
80 mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true); | |
81 bAccelIsEnabled = true; | |
82 return true; | |
83 } | |
84 | |
85 public static boolean closeAccel(){ | |
86 mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false); | |
87 bAccelIsEnabled = false; | |
88 return true; | |
89 } | |
90 | |
91 | |
92 //Events | |
93 protected void onPause() { | |
94 super.onPause(); | |
95 } | |
96 | |
97 protected void onResume() { | |
98 super.onResume(); | |
99 } | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 //C functions we call | |
106 public static native void nativeInit(); | |
107 public static native void nativeQuit(); | |
108 public static native void nativeSetScreenSize(int width, int height); | |
109 public static native void onNativeKeyDown(int keycode); | |
110 public static native void onNativeKeyUp(int keycode); | |
111 public static native void onNativeTouch(int action, float x, | |
112 float y, float p); | |
113 public static native void onNativeResize(int x, int y, int format); | |
114 public static native void onNativeAccel(float x, float y, float z); | |
115 | |
116 | |
117 | |
118 //Java functions called from C | |
119 private static void createGLContext(){ | |
120 mSurface.initEGL(); | |
121 } | |
122 | |
123 public static void flipBuffers(){ | |
124 mSurface.flipEGL(); | |
125 } | |
126 | |
127 public static void updateAudio(byte [] buf){ | |
128 | |
129 if(mAudioTrack == null){ | |
130 return; | |
131 } | |
132 | |
133 mAudioTrack.write(buf, 0, buf.length); | |
134 mAudioTrack.play(); | |
135 | |
136 Log.v("SDL","Played some audio"); | |
137 } | |
138 | |
139 public static void enableFeature(int featureid, int enabled){ | |
140 Log.v("SDL","Feature " + featureid + " = " + enabled); | |
141 | |
142 //Yuck. This is all horribly inelegent. If it gets to more than a few | |
143 //'features' I'll rip this out and make something nicer, I promise :) | |
144 if(featureid == FEATURE_AUDIO){ | |
145 if(enabled == 1){ | |
146 initAudio(); | |
147 }else{ | |
148 //We don't have one of these yet... | |
149 //closeAudio(); | |
150 } | |
151 } | |
152 | |
153 else if(featureid == FEATURE_ACCEL){ | |
154 if(enabled == 1){ | |
155 initAccel(); | |
156 }else{ | |
157 closeAccel(); | |
158 } | |
159 } | |
160 } | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 } | |
169 | |
170 /** | |
171 Simple nativeInit() runnable | |
172 */ | |
173 class SDLRunner implements Runnable{ | |
174 public void run(){ | |
175 //SDLActivity.initAudio(); | |
176 | |
177 //Runs SDL_main() | |
178 SDLActivity.nativeInit(); | |
179 | |
180 Log.v("SDL","SDL thread terminated"); | |
181 } | |
182 } | |
183 | |
184 | |
185 /** | |
186 SDLSurface. This is what we draw on, so we need to know when it's created | |
187 in order to do anything useful. | |
188 | |
189 Because of this, that's where we set up the SDL thread | |
190 */ | |
191 class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, | |
192 View.OnKeyListener, View.OnTouchListener, SensorEventListener { | |
193 | |
194 //This is what SDL runs in. It invokes SDL_main(), eventually | |
195 private Thread mSDLThread; | |
196 | |
197 //EGL private objects | |
198 private EGLContext mEGLContext; | |
199 private EGLSurface mEGLSurface; | |
200 private EGLDisplay mEGLDisplay; | |
201 | |
202 //Sensors | |
203 private static SensorManager mSensorManager; | |
204 | |
205 //Startup | |
206 public SDLSurface(Context context) { | |
207 super(context); | |
208 getHolder().addCallback(this); | |
209 | |
210 setFocusable(true); | |
211 setFocusableInTouchMode(true); | |
212 requestFocus(); | |
213 setOnKeyListener(this); | |
214 setOnTouchListener(this); | |
215 | |
216 mSensorManager = (SensorManager)context.getSystemService("sensor"); | |
217 } | |
218 | |
219 //Called when we have a valid drawing surface | |
220 public void surfaceCreated(SurfaceHolder holder) { | |
221 Log.v("SDL","Surface created"); | |
222 | |
223 int width = getWidth(); | |
224 int height = getHeight(); | |
225 | |
226 //Set the width and height variables in C before we start SDL so we have | |
227 //it available on init | |
228 SDLActivity.nativeSetScreenSize(width, height); | |
229 | |
230 //Now start up the C app thread | |
231 mSDLThread = new Thread(new SDLRunner(), "SDLThread"); | |
232 mSDLThread.start(); | |
233 } | |
234 | |
235 //Called when we lose the surface | |
236 public void surfaceDestroyed(SurfaceHolder holder) { | |
237 Log.v("SDL","Surface destroyed"); | |
238 | |
239 SDLActivity.nativeQuit(); | |
240 | |
241 //Now wait for the SDL thread to quit | |
242 try{ | |
243 mSDLThread.wait(); | |
244 }catch(Exception e){ | |
245 Log.v("SDL","Problem stopping thread: " + e); | |
246 } | |
247 } | |
248 | |
249 //Called when the surface is resized | |
250 public void surfaceChanged(SurfaceHolder holder, int format, | |
251 int width, int height) { | |
252 Log.v("SDL","Surface resized"); | |
253 | |
254 SDLActivity.onNativeResize(width, height, format); | |
255 } | |
256 | |
257 //unused | |
258 public void onDraw(Canvas canvas) {} | |
259 | |
260 | |
261 //EGL functions | |
262 public boolean initEGL(){ | |
263 Log.v("SDL","Starting up"); | |
264 | |
265 try{ | |
266 | |
267 EGL10 egl = (EGL10)EGLContext.getEGL(); | |
268 | |
269 EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); | |
270 | |
271 int[] version = new int[2]; | |
272 egl.eglInitialize(dpy, version); | |
273 | |
274 int[] configSpec = { | |
275 //EGL10.EGL_DEPTH_SIZE, 16, | |
276 EGL10.EGL_NONE | |
277 }; | |
278 EGLConfig[] configs = new EGLConfig[1]; | |
279 int[] num_config = new int[1]; | |
280 egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config); | |
281 EGLConfig config = configs[0]; | |
282 | |
283 EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null); | |
284 | |
285 EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null); | |
286 | |
287 egl.eglMakeCurrent(dpy, surface, surface, ctx); | |
288 | |
289 mEGLContext = ctx; | |
290 mEGLDisplay = dpy; | |
291 mEGLSurface = surface; | |
292 | |
293 | |
294 }catch(Exception e){ | |
295 Log.v("SDL", e + ""); | |
296 for(StackTraceElement s : e.getStackTrace()){ | |
297 Log.v("SDL", s.toString()); | |
298 } | |
299 } | |
300 Log.v("SDL","Done making!"); | |
301 | |
302 return true; | |
303 } | |
304 | |
305 //EGL buffer flip | |
306 public void flipEGL(){ | |
307 try{ | |
308 | |
309 EGL10 egl = (EGL10)EGLContext.getEGL(); | |
310 GL10 gl = (GL10)mEGLContext.getGL(); | |
311 | |
312 egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null); | |
313 | |
314 //drawing here | |
315 | |
316 egl.eglWaitGL(); | |
317 | |
318 egl.eglSwapBuffers(mEGLDisplay, mEGLSurface); | |
319 | |
320 | |
321 }catch(Exception e){ | |
322 Log.v("SDL", "flipEGL(): " + e); | |
323 | |
324 for(StackTraceElement s : e.getStackTrace()){ | |
325 Log.v("SDL", s.toString()); | |
326 } | |
327 } | |
328 } | |
329 | |
330 | |
331 | |
332 //Key events | |
333 public boolean onKey(View v, int keyCode, KeyEvent event){ | |
334 | |
335 if(event.getAction() == KeyEvent.ACTION_DOWN){ | |
336 SDLActivity.onNativeKeyDown(keyCode); | |
337 return true; | |
338 } | |
339 | |
340 else if(event.getAction() == KeyEvent.ACTION_UP){ | |
341 SDLActivity.onNativeKeyUp(keyCode); | |
342 return true; | |
343 } | |
344 | |
345 return false; | |
346 } | |
347 | |
348 //Touch events | |
349 public boolean onTouch(View v, MotionEvent event){ | |
350 | |
351 int action = event.getAction(); | |
352 float x = event.getX(); | |
353 float y = event.getY(); | |
354 float p = event.getPressure(); | |
355 | |
356 //TODO: Anything else we need to pass? | |
357 SDLActivity.onNativeTouch(action, x, y, p); | |
358 return true; | |
359 } | |
360 | |
361 //Sensor events | |
362 public void enableSensor(int sensortype, boolean enabled){ | |
363 //TODO: This uses getDefaultSensor - what if we have >1 accels? | |
364 if(enabled){ | |
365 mSensorManager.registerListener(this, | |
366 mSensorManager.getDefaultSensor(sensortype), | |
367 SensorManager.SENSOR_DELAY_GAME, null); | |
368 }else{ | |
369 mSensorManager.unregisterListener(this, | |
370 mSensorManager.getDefaultSensor(sensortype)); | |
371 } | |
372 } | |
373 | |
374 public void onAccuracyChanged(Sensor sensor, int accuracy){ | |
375 //TODO | |
376 } | |
377 | |
378 public void onSensorChanged(SensorEvent event){ | |
379 if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){ | |
380 SDLActivity.onNativeAccel( event.values[0], | |
381 event.values[1], | |
382 event.values[2] ); | |
383 } | |
384 } | |
385 | |
386 | |
387 } | |
388 | |
389 |