diff --git a/alienblaster/ChangeAppSettings.sh b/alienblaster/ChangeAppSettings.sh index 55ccfceea..e35e4c276 100755 --- a/alienblaster/ChangeAppSettings.sh +++ b/alienblaster/ChangeAppSettings.sh @@ -69,13 +69,13 @@ for F in project/src/*.java; do mv -f $F.1 $F done -echo Patching project/src/DemoActivity.java -cat project/src/DemoActivity.java | \ +echo Patching project/src/Globals.java +cat project/src/Globals.java | \ sed "s/public static String ApplicationName = .*;/public static String ApplicationName = \"$AppShortName\";/" | \ sed "s^public static String DataDownloadUrl = \".*\";^public static String DataDownloadUrl = \"$AppDataDownloadUrl1\";^" | \ sed "s/public static boolean DownloadToSdcard = .*;/public static boolean DownloadToSdcard = $DownloadToSdcard1;/" > \ - project/src/DemoActivity.java.1 -mv -f project/src/DemoActivity.java.1 project/src/DemoActivity.java + project/src/Globals.java.1 +mv -f project/src/Globals.java.1 project/src/Globals.java echo Patching project/jni/Android.mk cat project/jni/Android.mk | \ diff --git a/alienblaster/project/jni/sdl/src/video/android/SDL_androidinput.c b/alienblaster/project/jni/sdl/src/video/android/SDL_androidinput.c new file mode 100644 index 000000000..3ac98d5e1 --- /dev/null +++ b/alienblaster/project/jni/sdl/src/video/android/SDL_androidinput.c @@ -0,0 +1,292 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "SDL_thread.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_androidvideo.h" + +#include +#include +#include +#include +#include +#include +#include // for memset() + + +static SDLKey keymap[KEYCODE_LAST+1]; + +/* JNI-C++ wrapper stuff */ + +#ifndef SDL_JAVA_PACKAGE_PATH +#error You have to define SDL_JAVA_PACKAGE_PATH to your package path with dots replaced with underscores, for example "com_example_SanAngeles" +#endif +#define JAVA_EXPORT_NAME2(name,package) Java_##package##_##name +#define JAVA_EXPORT_NAME1(name,package) JAVA_EXPORT_NAME2(name,package) +#define JAVA_EXPORT_NAME(name) JAVA_EXPORT_NAME1(name,SDL_JAVA_PACKAGE_PATH) + + +extern void +JAVA_EXPORT_NAME(AccelerometerReader_nativeAccelerometer) ( JNIEnv* env, jobject thiz, jfloat accX, jfloat accY, jfloat accZ ) +{ + // TODO: use accelerometer as joystick +} + +enum MOUSE_ACTION { MOUSE_DOWN = 0, MOUSE_UP=1, MOUSE_MOVE=2 }; + +extern void +JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMouse) ( JNIEnv* env, jobject thiz, jint x, jint y, jint action ) +{ + //__android_log_print(ANDROID_LOG_INFO, "libSDL", "mouse event %i at (%03i, %03i)", action, x, y); + if( action == MOUSE_DOWN || action == MOUSE_UP ) + SDL_PrivateMouseButton( (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, 1, x, y ); + if( action == MOUSE_MOVE ) + SDL_PrivateMouseMotion(0, 0, x, y); +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Sanity check */ + if ( scancode >= SDL_arraysize(keymap) ) + scancode = KEYCODE_UNKNOWN; + + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } + return(keysym); +} + + +void +JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeKey) ( JNIEnv* env, jobject thiz, jint key, jint action ) +{ + //__android_log_print(ANDROID_LOG_INFO, "libSDL", "key event %i %s", key, action ? "down" : "up"); + SDL_keysym keysym; + if( ! processAndroidTrackballKeyDelays(key, action) ) + SDL_PrivateKeyboard( action ? SDL_PRESSED : SDL_RELEASED, TranslateKey(key, &keysym) ); +} + + +void ANDROID_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the DirectFB key translation table */ + for (i=0; i 0 ) + { + AndroidTrackballKeyDelays[idx] --; + if( AndroidTrackballKeyDelays[idx] == 0 ) + SDL_PrivateKeyboard( SDL_RELEASED, TranslateKey(KeysMapping[idx], &keysym) ); + } + } + } + else + { + idx = -1; + // Too lazy to do switch or function + if( key == KEYCODE_DPAD_UP ) + idx = 0; + else if( key == KEYCODE_DPAD_DOWN ) + idx = 1; + else if( key == KEYCODE_DPAD_LEFT ) + idx = 2; + else if( key == KEYCODE_DPAD_RIGHT ) + idx = 3; + if( idx >= 0 ) + { + if( action && AndroidTrackballKeyDelays[idx] == 0 ) + { + // User pressed key for the first time + idx2 = (idx + 2) % 4; // Opposite key for current key - if it's still pressing, release it + if( AndroidTrackballKeyDelays[idx2] > 0 ) + { + AndroidTrackballKeyDelays[idx2] = 0; + SDL_PrivateKeyboard( SDL_RELEASED, TranslateKey(KeysMapping[idx2], &keysym) ); + } + SDL_PrivateKeyboard( SDL_PRESSED, TranslateKey(key, &keysym) ); + } + else if( !action && AndroidTrackballKeyDelays[idx] == 0 ) + { + // User released key - make a delay, do not send release event + AndroidTrackballKeyDelays[idx] = SDL_TRACKBALL_KEYUP_DELAY; + } + else if( action && AndroidTrackballKeyDelays[idx] > 0 ) + { + // User pressed key another time - add some more time for key to be pressed + AndroidTrackballKeyDelays[idx] += SDL_TRACKBALL_KEYUP_DELAY; + if( AndroidTrackballKeyDelays[idx] < SDL_TRACKBALL_KEYUP_DELAY * 4 ) + AndroidTrackballKeyDelays[idx] = SDL_TRACKBALL_KEYUP_DELAY * 4; + } + return 1; + } + } + return 0; + + #endif +} diff --git a/alienblaster/project/jni/sdl/src/video/android/SDL_androidvideo.c b/alienblaster/project/jni/sdl/src/video/android/SDL_androidvideo.c index 668b547d3..d474ed4f7 100644 --- a/alienblaster/project/jni/sdl/src/video/android/SDL_androidvideo.c +++ b/alienblaster/project/jni/sdl/src/video/android/SDL_androidvideo.c @@ -21,21 +21,6 @@ */ #include "SDL_config.h" -/* Dummy SDL video driver implementation; this is just enough to make an - * SDL-based application THINK it's got a working video driver, for - * applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it, - * and also for use as a collection of stubs when porting SDL to a new - * platform for which you haven't yet written a valid video driver. - * - * This is also a great way to determine bottlenecks: if you think that SDL - * is a performance problem for a given platform, enable this driver, and - * then see if your application runs faster without video overhead. - * - * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion - * of this was cut-and-pasted from Stephane Peter's work in the AAlib - * SDL video driver. Renamed to "ANDROID" by Sam Lantinga. - */ - #include "SDL_video.h" #include "SDL_mouse.h" #include "SDL_mutex.h" @@ -139,7 +124,8 @@ static SDLKey keymap[KEYCODE_LAST+1]; static int CallJavaSwapBuffers(); static void SdlGlRenderInit(); -static int processAndroidTrackballKeyDelays( int key, int action ); +extern int processAndroidTrackballKeyDelays( int key, int action ); // Defined in androidinput.c + /* ANDROID driver bootstrap functions */ @@ -451,54 +437,6 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeDone) ( JNIEnv* env, jobject thiz ) __android_log_print(ANDROID_LOG_INFO, "libSDL", "quit OK"); } -extern void -JAVA_EXPORT_NAME(AccelerometerReader_nativeAccelerometer) ( JNIEnv* env, jobject thiz, jfloat accX, jfloat accY, jfloat accZ ) -{ - // TODO: use accelerometer as joystick -} - -enum MOUSE_ACTION { MOUSE_DOWN = 0, MOUSE_UP=1, MOUSE_MOVE=2 }; - -extern void -JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMouse) ( JNIEnv* env, jobject thiz, jint x, jint y, jint action ) -{ - //__android_log_print(ANDROID_LOG_INFO, "libSDL", "mouse event %i at (%03i, %03i)", action, x, y); - if( action == MOUSE_DOWN || action == MOUSE_UP ) - SDL_PrivateMouseButton( (action == MOUSE_DOWN) ? SDL_PRESSED : SDL_RELEASED, 1, x, y ); - if( action == MOUSE_MOVE ) - SDL_PrivateMouseMotion(0, 0, x, y); -} - -static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) -{ - /* Sanity check */ - if ( scancode >= SDL_arraysize(keymap) ) - scancode = KEYCODE_UNKNOWN; - - /* Set the keysym information */ - keysym->scancode = scancode; - keysym->sym = keymap[scancode]; - keysym->mod = KMOD_NONE; - - /* If UNICODE is on, get the UNICODE value for the key */ - keysym->unicode = 0; - if ( SDL_TranslateUNICODE ) { - /* Populate the unicode field with the ASCII value */ - keysym->unicode = scancode; - } - return(keysym); -} - - -void -JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeKey) ( JNIEnv* env, jobject thiz, jint key, jint action ) -{ - //__android_log_print(ANDROID_LOG_INFO, "libSDL", "key event %i %s", key, action ? "down" : "up"); - SDL_keysym keysym; - if( ! processAndroidTrackballKeyDelays(key, action) ) - SDL_PrivateKeyboard( action ? SDL_PRESSED : SDL_RELEASED, TranslateKey(key, &keysym) ); -} - void SdlGlRenderInit() { // Set up an array of values to use as the sprite vertices. @@ -629,193 +567,3 @@ int CallJavaSwapBuffers() { return (*JavaEnv)->CallIntMethod( JavaEnv, JavaRenderer, JavaSwapBuffers ); } - -void ANDROID_InitOSKeymap(_THIS) -{ - int i; - - /* Initialize the DirectFB key translation table */ - for (i=0; i 0 ) - { - AndroidTrackballKeyDelays[idx] --; - if( AndroidTrackballKeyDelays[idx] == 0 ) - SDL_PrivateKeyboard( SDL_RELEASED, TranslateKey(KeysMapping[idx], &keysym) ); - } - } - } - else - { - idx = -1; - // Too lazy to do switch or function - if( key == KEYCODE_DPAD_UP ) - idx = 0; - else if( key == KEYCODE_DPAD_DOWN ) - idx = 1; - else if( key == KEYCODE_DPAD_LEFT ) - idx = 2; - else if( key == KEYCODE_DPAD_RIGHT ) - idx = 3; - if( idx >= 0 ) - { - if( action && AndroidTrackballKeyDelays[idx] == 0 ) - { - // User pressed key for the first time - idx2 = (idx + 2) % 4; // Opposite key for current key - if it's still pressing, release it - if( AndroidTrackballKeyDelays[idx2] > 0 ) - { - AndroidTrackballKeyDelays[idx2] = 0; - SDL_PrivateKeyboard( SDL_RELEASED, TranslateKey(KeysMapping[idx2], &keysym) ); - } - SDL_PrivateKeyboard( SDL_PRESSED, TranslateKey(key, &keysym) ); - } - else if( !action && AndroidTrackballKeyDelays[idx] == 0 ) - { - // User released key - make a delay, do not send release event - AndroidTrackballKeyDelays[idx] = SDL_TRACKBALL_KEYUP_DELAY; - } - else if( action && AndroidTrackballKeyDelays[idx] > 0 ) - { - // User pressed key another time - add some more time for key to be pressed - AndroidTrackballKeyDelays[idx] += SDL_TRACKBALL_KEYUP_DELAY; - if( AndroidTrackballKeyDelays[idx] < SDL_TRACKBALL_KEYUP_DELAY * 4 ) - AndroidTrackballKeyDelays[idx] = SDL_TRACKBALL_KEYUP_DELAY * 4; - } - return 1; - } - } - return 0; - - #endif -} diff --git a/alienblaster/project/src/Accelerometer.java b/alienblaster/project/src/Accelerometer.java new file mode 100644 index 000000000..dedf110ed --- /dev/null +++ b/alienblaster/project/src/Accelerometer.java @@ -0,0 +1,79 @@ +// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount +package de.schwardtnet.alienblaster; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.KeyEvent; +import android.view.Window; +import android.view.WindowManager; +import android.os.Vibrator; +import android.hardware.SensorManager; +import android.hardware.SensorListener; + +import android.widget.TextView; + + +// Accelerometer code partially ripped from http://karanar.net/ +class AccelerometerReader implements SensorListener { + + private long timekeeper; + + private float [] v; + + private SensorManager _manager = null; + + public AccelerometerReader(Activity context) { + v = new float[3]; + _manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + if( _manager != null ) + { + timekeeper = android.os.SystemClock.uptimeMillis(); + int mask = 0; + //mask |= SensorManager.SENSOR_ORIENTATION; + mask |= SensorManager.SENSOR_ACCELEROMETER; + _manager.registerListener(this, mask, SensorManager.SENSOR_DELAY_GAME); + } + } + + public synchronized void stop() { + if( _manager != null ) + { + _manager.unregisterListener(this); + } + } + + public synchronized void onSensorChanged(int sensor, float[] values) { + //if (android.os.SystemClock.uptimeMillis() < timekeeper + 20) return; + timekeeper = android.os.SystemClock.uptimeMillis(); + + if (sensor == SensorManager.SENSOR_ACCELEROMETER) { + if( values.length >= 1 ) + v[0] = values[0]; + if( values.length >= 2 ) + v[1] = values[1]; + if( values.length >= 3 ) + v[2] = values[2]; + nativeAccelerometer(v[0], v[1], v[2]); + } + + } + + public synchronized void onAccuracyChanged(int i, int i1) { + /* @todo implement method */ + } + + public synchronized float[] readAccelerometer() + { + float [] ret = new float[3]; + ret[0] = v[0]; + ret[1] = v[1]; + ret[2] = v[2]; + return ret; + }; + + private native void nativeAccelerometer(float accX, float accY, float accZ); +} + + diff --git a/alienblaster/project/src/Audio.java b/alienblaster/project/src/Audio.java new file mode 100644 index 000000000..fc7a0fa3e --- /dev/null +++ b/alienblaster/project/src/Audio.java @@ -0,0 +1,95 @@ +// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount +package de.schwardtnet.alienblaster; + + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.KeyEvent; +import android.view.Window; +import android.view.WindowManager; +import android.media.AudioTrack; +import android.media.AudioManager; +import android.media.AudioFormat; +import java.io.*; +import java.nio.ByteBuffer; + + +class AudioThread extends Thread { + + private Activity mParent; + private AudioTrack mAudio; + private byte[] mAudioBuffer; + private ByteBuffer mAudioBufferNative; + + public AudioThread(Activity parent) + { + mParent = parent; + mAudio = null; + mAudioBuffer = null; + this.setPriority(Thread.MAX_PRIORITY); + this.start(); + } + + @Override + public void run() + { + while( !isInterrupted() ) + { + if( mAudio == null ) + { + int[] initParams = nativeAudioInit(); + if( initParams == null ) + { + try { + sleep(200); + } catch( java.lang.InterruptedException e ) { }; + } + else + { + int rate = initParams[0]; + int channels = initParams[1]; + channels = ( channels == 1 ) ? AudioFormat.CHANNEL_CONFIGURATION_MONO : + AudioFormat.CHANNEL_CONFIGURATION_STEREO; + int encoding = initParams[2]; + encoding = ( encoding == 1 ) ? AudioFormat.ENCODING_PCM_16BIT : + AudioFormat.ENCODING_PCM_8BIT; + int bufSize = AudioTrack.getMinBufferSize( rate, channels, encoding ); + if( initParams[3] > bufSize ) + bufSize = initParams[3]; + mAudioBuffer = new byte[bufSize]; + nativeAudioInit2(mAudioBuffer); + mAudio = new AudioTrack(AudioManager.STREAM_MUSIC, + rate, + channels, + encoding, + bufSize, + AudioTrack.MODE_STREAM ); + mAudio.play(); + } + } + else + { + int len = nativeAudioBufferLock(); + if( len > 0 ) + mAudio.write( mAudioBuffer, 0, len ); + if( len < 0 ) + break; + nativeAudioBufferUnlock(); + } + } + if( mAudio != null ) + { + mAudio.stop(); + mAudio.release(); + mAudio = null; + } + } + + private native int[] nativeAudioInit(); + private native int nativeAudioInit2(byte[] buf); + private native int nativeAudioBufferLock(); + private native int nativeAudioBufferUnlock(); +} + diff --git a/alienblaster/project/src/DataDownloader.java b/alienblaster/project/src/DataDownloader.java new file mode 100644 index 000000000..dbdfa13e2 --- /dev/null +++ b/alienblaster/project/src/DataDownloader.java @@ -0,0 +1,225 @@ +// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount +package de.schwardtnet.alienblaster; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.KeyEvent; +import android.view.Window; +import android.view.WindowManager; + +import android.widget.TextView; +import org.apache.http.client.methods.*; +import org.apache.http.*; +import org.apache.http.impl.*; +import org.apache.http.impl.client.*; +import java.util.zip.*; +import java.io.*; + + + +class DataDownloader extends Thread +{ + class StatusWriter + { + private TextView Status; + private MainActivity Parent; + + public StatusWriter( TextView _Status, MainActivity _Parent ) + { + Status = _Status; + Parent = _Parent; + } + + public void setText(final String str) + { + class Callback implements Runnable + { + public TextView Status; + public String text; + public void run() + { + Status.setText(text); + } + } + Callback cb = new Callback(); + cb.text = new String(str); + cb.Status = Status; + Parent.runOnUiThread(cb); + } + + } + public DataDownloader( MainActivity _Parent, TextView _Status ) + { + Parent = _Parent; + DownloadComplete = false; + Status = new StatusWriter( _Status, _Parent ); + Status.setText( "Connecting to " + Globals.DataDownloadUrl ); + this.start(); + } + + @Override + public void run() + { + + String path = getOutFilePath("DownloadFinished.flag"); + InputStream checkFile = null; + try { + checkFile = new FileInputStream( path ); + } catch( FileNotFoundException e ) { + } catch( SecurityException e ) { }; + if( checkFile != null ) + { + Status.setText( "No need to download" ); + DownloadComplete = true; + initParent(); + return; + } + checkFile = null; + + // Create output directory + if( Globals.DownloadToSdcard ) + { + try { + (new File( "/sdcard/" + Globals.ApplicationName )).mkdirs(); + } catch( SecurityException e ) { }; + } + else + { + try { + FileOutputStream dummy = Parent.openFileOutput( "dummy", Parent.MODE_WORLD_READABLE ); + dummy.write(0); + dummy.flush(); + } catch( FileNotFoundException e ) { + } catch( java.io.IOException e ) {}; + } + + HttpGet request = new HttpGet(Globals.DataDownloadUrl); + request.addHeader("Accept", "*/*"); + HttpResponse response = null; + try { + DefaultHttpClient client = new DefaultHttpClient(); + client.getParams().setBooleanParameter("http.protocol.handle-redirects", true); + response = client.execute(request); + } catch (IOException e) { } ; + if( response == null ) + { + Status.setText( "Error connecting to " + Globals.DataDownloadUrl ); + return; + } + + Status.setText( "Downloading data from " + Globals.DataDownloadUrl ); + + ZipInputStream zip = null; + try { + zip = new ZipInputStream(response.getEntity().getContent()); + } catch( java.io.IOException e ) { + Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); + return; + } + + byte[] buf = new byte[1024]; + + ZipEntry entry = null; + + while(true) + { + entry = null; + try { + entry = zip.getNextEntry(); + } catch( java.io.IOException e ) { + Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); + return; + } + if( entry == null ) + break; + if( entry.isDirectory() ) + { + try { + (new File( getOutFilePath(entry.getName()) )).mkdirs(); + } catch( SecurityException e ) { }; + continue; + } + + OutputStream out = null; + path = getOutFilePath(entry.getName()); + + try { + out = new FileOutputStream( path ); + } catch( FileNotFoundException e ) { + } catch( SecurityException e ) { }; + if( out == null ) + { + Status.setText( "Error writing to " + path ); + return; + } + + Status.setText( "Writing file " + path ); + + try { + int len; + while ((len = zip.read(buf)) > 0) + { + out.write(buf, 0, len); + } + out.flush(); + } catch( java.io.IOException e ) { + Status.setText( "Error writing file " + path ); + return; + } + + } + + OutputStream out = null; + path = getOutFilePath("DownloadFinished.flag"); + try { + out = new FileOutputStream( path ); + out.write(0); + out.flush(); + } catch( FileNotFoundException e ) { + } catch( SecurityException e ) { + } catch( java.io.IOException e ) { + Status.setText( "Error writing file " + path ); + return; + }; + + if( out == null ) + { + Status.setText( "Error writing to " + path ); + return; + } + + Status.setText( "Finished" ); + DownloadComplete = true; + + initParent(); + }; + + private void initParent() + { + class Callback implements Runnable + { + public MainActivity Parent; + public void run() + { + Parent.initSDL(); + } + } + Callback cb = new Callback(); + cb.Parent = Parent; + Parent.runOnUiThread(cb); + } + + private String getOutFilePath(final String filename) + { + if( Globals.DownloadToSdcard ) + return "/sdcard/" + Globals.ApplicationName + "/" + filename; + return Parent.getFilesDir().getAbsolutePath() + "/" + filename; + }; + + public boolean DownloadComplete; + public StatusWriter Status; + private MainActivity Parent; +} + diff --git a/alienblaster/project/src/DemoActivity.java b/alienblaster/project/src/DemoActivity.java deleted file mode 100644 index d9236a709..000000000 --- a/alienblaster/project/src/DemoActivity.java +++ /dev/null @@ -1,606 +0,0 @@ -// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount -package de.schwardtnet.alienblaster; - -import javax.microedition.khronos.opengles.GL10; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; - -import android.app.Activity; -import android.content.Context; -import android.opengl.GLSurfaceView; -import android.os.Bundle; -import android.view.MotionEvent; -import android.view.KeyEvent; -import android.view.Window; -import android.view.WindowManager; -import android.media.AudioTrack; -import android.media.AudioManager; -import android.media.AudioFormat; -import android.os.PowerManager; -import android.os.Vibrator; -import android.hardware.SensorManager; -import android.hardware.SensorListener; - -import android.widget.TextView; -import org.apache.http.client.methods.*; -import org.apache.http.*; -import org.apache.http.impl.*; -import org.apache.http.impl.client.*; -import java.util.zip.*; -import java.io.*; -import java.nio.ByteBuffer; - - -class Globals { - // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount - public static String ApplicationName = "AlienBlaster"; - - // Should be zip file - // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount - public static String DataDownloadUrl = "http://sites.google.com/site/xpelyax/Home/alienblaster110_data.zip?attredirects=0%26d=1"; // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount - - // Set DownloadToSdcard to true if your app data is bigger than 5 megabytes. - // It will download app data to /sdcard/alienblaster then, - // otherwise it will download it to /data/data/de.schwardtnet.alienblaster/files - - // set this dir in jni/Android.mk in SDL_CURDIR_PATH - // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount - public static boolean DownloadToSdcard = false; -} - -class LoadLibrary { - public LoadLibrary() {} - static { - System.loadLibrary("tremor"); - System.loadLibrary("sdl"); - System.loadLibrary("sdl_mixer"); - System.loadLibrary("sdl_image"); - System.loadLibrary("application"); - System.loadLibrary("sdl_main"); - } -} - - -// Accelerometer code partially ripped from http://karanar.net/ -class AccelerometerReader implements SensorListener { - - private long timekeeper; - - private float [] v; - - private SensorManager _manager = null; - - public AccelerometerReader(Activity context) { - v = new float[3]; - _manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - if( _manager != null ) - { - timekeeper = android.os.SystemClock.uptimeMillis(); - int mask = 0; - //mask |= SensorManager.SENSOR_ORIENTATION; - mask |= SensorManager.SENSOR_ACCELEROMETER; - _manager.registerListener(this, mask, SensorManager.SENSOR_DELAY_GAME); - } - } - - public synchronized void stop() { - if( _manager != null ) - { - _manager.unregisterListener(this); - } - } - - public synchronized void onSensorChanged(int sensor, float[] values) { - //if (android.os.SystemClock.uptimeMillis() < timekeeper + 20) return; - timekeeper = android.os.SystemClock.uptimeMillis(); - - if (sensor == SensorManager.SENSOR_ACCELEROMETER) { - if( values.length >= 1 ) - v[0] = values[0]; - if( values.length >= 2 ) - v[1] = values[1]; - if( values.length >= 3 ) - v[2] = values[2]; - nativeAccelerometer(v[0], v[1], v[2]); - } - - } - - public synchronized void onAccuracyChanged(int i, int i1) { - /* @todo implement method */ - } - - public synchronized float[] readAccelerometer() - { - float [] ret = new float[3]; - ret[0] = v[0]; - ret[1] = v[1]; - ret[2] = v[2]; - return ret; - }; - - private native void nativeAccelerometer(float accX, float accY, float accZ); -} - - - -class DemoRenderer extends GLSurfaceView_SDL.Renderer { - - public DemoRenderer(Activity _context) - { - context = _context; - } - - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - // nativeInit(); - } - - public void onSurfaceChanged(GL10 gl, int w, int h) { - //gl.glViewport(0, 0, w, h); - nativeResize(w, h); - } - - public void onDrawFrame(GL10 gl) { - - nativeInitJavaCallbacks(); - - nativeInit(); // Calls main() and never returns, hehe - we'll call eglSwapBuffers() from native code - - } - - public int swapBuffers() // Called from native code, returns 1 on success, 0 when GL context lost (user put app to background) - { - return super.SwapBuffers() ? 1 : 0; - } - - public void exitApp() { - nativeDone(); - }; - - private native void nativeInitJavaCallbacks(); - private native void nativeInit(); - private native void nativeResize(int w, int h); - private native void nativeDone(); - - private Activity context = null; - - private EGL10 mEgl = null; - private EGLDisplay mEglDisplay = null; - private EGLSurface mEglSurface = null; - private EGLContext mEglContext = null; - private int skipFrames = 0; - -} - -class DemoGLSurfaceView extends GLSurfaceView_SDL { - public DemoGLSurfaceView(Activity context) { - super(context); - mParent = context; - accelerometer = new AccelerometerReader(context); - mRenderer = new DemoRenderer(context); - setRenderer(mRenderer); - } - - @Override - public boolean onTouchEvent(final MotionEvent event) - { - // TODO: add multitouch support (added in Android 2.0 SDK) - int action = -1; - if( event.getAction() == MotionEvent.ACTION_DOWN ) - action = 0; - if( event.getAction() == MotionEvent.ACTION_UP ) - action = 1; - if( event.getAction() == MotionEvent.ACTION_MOVE ) - action = 2; - if ( action >= 0 ) { - nativeMouse( (int)event.getX(), (int)event.getY(), action ); - } - return true; - } - - public void exitApp() { - mRenderer.exitApp(); - accelerometer.stop(); - accelerometer = null; - }; - - @Override - public boolean onKeyDown(int keyCode, final KeyEvent event) { - nativeKey( keyCode, 1 ); - return true; - } - - @Override - public boolean onKeyUp(int keyCode, final KeyEvent event) { - nativeKey( keyCode, 0 ); - return true; - } - - DemoRenderer mRenderer; - Activity mParent; - AccelerometerReader accelerometer = null; - - public native void nativeMouse( int x, int y, int action ); - public native void nativeKey( int keyCode, int down ); -} - -class AudioThread extends Thread { - - private Activity mParent; - private AudioTrack mAudio; - private byte[] mAudioBuffer; - private ByteBuffer mAudioBufferNative; - - public AudioThread(Activity parent) - { - mParent = parent; - mAudio = null; - mAudioBuffer = null; - this.setPriority(Thread.MAX_PRIORITY); - this.start(); - } - - @Override - public void run() - { - while( !isInterrupted() ) - { - if( mAudio == null ) - { - int[] initParams = nativeAudioInit(); - if( initParams == null ) - { - try { - sleep(200); - } catch( java.lang.InterruptedException e ) { }; - } - else - { - int rate = initParams[0]; - int channels = initParams[1]; - channels = ( channels == 1 ) ? AudioFormat.CHANNEL_CONFIGURATION_MONO : - AudioFormat.CHANNEL_CONFIGURATION_STEREO; - int encoding = initParams[2]; - encoding = ( encoding == 1 ) ? AudioFormat.ENCODING_PCM_16BIT : - AudioFormat.ENCODING_PCM_8BIT; - int bufSize = AudioTrack.getMinBufferSize( rate, channels, encoding ); - if( initParams[3] > bufSize ) - bufSize = initParams[3]; - mAudioBuffer = new byte[bufSize]; - nativeAudioInit2(mAudioBuffer); - mAudio = new AudioTrack(AudioManager.STREAM_MUSIC, - rate, - channels, - encoding, - bufSize, - AudioTrack.MODE_STREAM ); - mAudio.play(); - } - } - else - { - int len = nativeAudioBufferLock(); - if( len > 0 ) - mAudio.write( mAudioBuffer, 0, len ); - if( len < 0 ) - break; - nativeAudioBufferUnlock(); - } - } - if( mAudio != null ) - { - mAudio.stop(); - mAudio.release(); - mAudio = null; - } - } - - private native int[] nativeAudioInit(); - private native int nativeAudioInit2(byte[] buf); - private native int nativeAudioBufferLock(); - private native int nativeAudioBufferUnlock(); -} - - -public class DemoActivity extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // fullscreen mode - requestWindowFeature(Window.FEATURE_NO_TITLE); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - - TextView tv = new TextView(this); - tv.setText("Initializing"); - setContentView(tv); - downloader = new DataDownloader(this, tv); - } - - public void initSDL() - { - mLoadLibraryStub = new LoadLibrary(); - mAudioThread = new AudioThread(this); - mGLView = new DemoGLSurfaceView(this); - setContentView(mGLView); - // Receive keyboard events - mGLView.setFocusableInTouchMode(true); - mGLView.setFocusable(true); - mGLView.requestFocus(); - PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, Globals.ApplicationName); - wakeLock.acquire(); - } - - @Override - protected void onPause() { - // TODO: if application pauses it's screen is messed up - if( wakeLock != null ) - wakeLock.release(); - super.onPause(); - if( mGLView != null ) - mGLView.onPause(); - } - - @Override - protected void onResume() { - if( wakeLock != null ) - wakeLock.acquire(); - super.onResume(); - if( mGLView != null ) - mGLView.onResume(); - } - - @Override - protected void onStop() - { - if( wakeLock != null ) - wakeLock.release(); - if( mAudioThread != null ) - { - mAudioThread.interrupt(); - try { - mAudioThread.join(); - } catch( java.lang.InterruptedException e ) { }; - } - if( mGLView != null ) - mGLView.exitApp(); - super.onStop(); - finish(); - } - - @Override - public boolean onKeyDown(int keyCode, final KeyEvent event) { - // Overrides Back key to use in our app - if( mGLView != null ) - mGLView.nativeKey( keyCode, 1 ); - if( keyCode == KeyEvent.KEYCODE_BACK && !downloader.DownloadComplete ) - onStop(); - return true; - } - - @Override - public boolean onKeyUp(int keyCode, final KeyEvent event) { - if( mGLView != null ) - mGLView.nativeKey( keyCode, 0 ); - return true; - } - - private DemoGLSurfaceView mGLView = null; - private LoadLibrary mLoadLibraryStub = null; - private AudioThread mAudioThread = null; - private PowerManager.WakeLock wakeLock = null; - private DataDownloader downloader = null; - - - -class DataDownloader extends Thread -{ - class StatusWriter - { - private TextView Status; - private DemoActivity Parent; - - public StatusWriter( TextView _Status, DemoActivity _Parent ) - { - Status = _Status; - Parent = _Parent; - } - - public void setText(final String str) - { - class Callback implements Runnable - { - public TextView Status; - public String text; - public void run() - { - Status.setText(text); - } - } - Callback cb = new Callback(); - cb.text = new String(str); - cb.Status = Status; - Parent.runOnUiThread(cb); - } - - } - public DataDownloader( DemoActivity _Parent, TextView _Status ) - { - Parent = _Parent; - DownloadComplete = false; - Status = new StatusWriter( _Status, _Parent ); - Status.setText( "Connecting to " + Globals.DataDownloadUrl ); - this.start(); - } - - @Override - public void run() - { - - String path = getOutFilePath("DownloadFinished.flag"); - InputStream checkFile = null; - try { - checkFile = new FileInputStream( path ); - } catch( FileNotFoundException e ) { - } catch( SecurityException e ) { }; - if( checkFile != null ) - { - Status.setText( "No need to download" ); - DownloadComplete = true; - initParent(); - return; - } - checkFile = null; - - // Create output directory - if( Globals.DownloadToSdcard ) - { - try { - (new File( "/sdcard/" + Globals.ApplicationName )).mkdirs(); - } catch( SecurityException e ) { }; - } - else - { - try { - FileOutputStream dummy = Parent.openFileOutput( "dummy", Parent.MODE_WORLD_READABLE ); - dummy.write(0); - dummy.flush(); - } catch( FileNotFoundException e ) { - } catch( java.io.IOException e ) {}; - } - - HttpGet request = new HttpGet(Globals.DataDownloadUrl); - request.addHeader("Accept", "*/*"); - HttpResponse response = null; - try { - DefaultHttpClient client = new DefaultHttpClient(); - client.getParams().setBooleanParameter("http.protocol.handle-redirects", true); - response = client.execute(request); - } catch (IOException e) { } ; - if( response == null ) - { - Status.setText( "Error connecting to " + Globals.DataDownloadUrl ); - return; - } - - Status.setText( "Downloading data from " + Globals.DataDownloadUrl ); - - ZipInputStream zip = null; - try { - zip = new ZipInputStream(response.getEntity().getContent()); - } catch( java.io.IOException e ) { - Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); - return; - } - - byte[] buf = new byte[1024]; - - ZipEntry entry = null; - - while(true) - { - entry = null; - try { - entry = zip.getNextEntry(); - } catch( java.io.IOException e ) { - Status.setText( "Error downloading data from " + Globals.DataDownloadUrl ); - return; - } - if( entry == null ) - break; - if( entry.isDirectory() ) - { - try { - (new File( getOutFilePath(entry.getName()) )).mkdirs(); - } catch( SecurityException e ) { }; - continue; - } - - OutputStream out = null; - path = getOutFilePath(entry.getName()); - - try { - out = new FileOutputStream( path ); - } catch( FileNotFoundException e ) { - } catch( SecurityException e ) { }; - if( out == null ) - { - Status.setText( "Error writing to " + path ); - return; - } - - Status.setText( "Writing file " + path ); - - try { - int len; - while ((len = zip.read(buf)) > 0) - { - out.write(buf, 0, len); - } - out.flush(); - } catch( java.io.IOException e ) { - Status.setText( "Error writing file " + path ); - return; - } - - } - - OutputStream out = null; - path = getOutFilePath("DownloadFinished.flag"); - try { - out = new FileOutputStream( path ); - out.write(0); - out.flush(); - } catch( FileNotFoundException e ) { - } catch( SecurityException e ) { - } catch( java.io.IOException e ) { - Status.setText( "Error writing file " + path ); - return; - }; - - if( out == null ) - { - Status.setText( "Error writing to " + path ); - return; - } - - Status.setText( "Finished" ); - DownloadComplete = true; - - initParent(); - }; - - private void initParent() - { - class Callback implements Runnable - { - public DemoActivity Parent; - public void run() - { - Parent.initSDL(); - } - } - Callback cb = new Callback(); - cb.Parent = Parent; - Parent.runOnUiThread(cb); - } - - private String getOutFilePath(final String filename) - { - if( Globals.DownloadToSdcard ) - return "/sdcard/" + Globals.ApplicationName + "/" + filename; - return Parent.getFilesDir().getAbsolutePath() + "/" + filename; - }; - - public boolean DownloadComplete; - public StatusWriter Status; - private DemoActivity Parent; -} - -} diff --git a/alienblaster/project/src/Globals.java b/alienblaster/project/src/Globals.java new file mode 100644 index 000000000..66780bebc --- /dev/null +++ b/alienblaster/project/src/Globals.java @@ -0,0 +1,33 @@ +// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount +package de.schwardtnet.alienblaster; + +import android.app.Activity; +import android.content.Context; + +class Globals { + // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount + public static String ApplicationName = "AlienBlaster"; + + // Should be zip file + // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount + public static String DataDownloadUrl = "http://sites.google.com/site/xpelyax/Home/alienblaster110_data.zip?attredirects=0%26d=1"; // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount + + // Set DownloadToSdcard to true if your app data is bigger than 5 megabytes. + // It will download app data to /sdcard/alienblaster then, + // otherwise it will download it to /data/data/de.schwardtnet.alienblaster/files - + // set this dir in jni/Android.mk in SDL_CURDIR_PATH + // This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount + public static boolean DownloadToSdcard = false; +} + +class LoadLibrary { + public LoadLibrary() {} + static { + System.loadLibrary("tremor"); + System.loadLibrary("sdl"); + System.loadLibrary("sdl_mixer"); + System.loadLibrary("sdl_image"); + System.loadLibrary("application"); + System.loadLibrary("sdl_main"); + } +} diff --git a/alienblaster/project/src/MainActivity.java b/alienblaster/project/src/MainActivity.java new file mode 100644 index 000000000..9edd95c69 --- /dev/null +++ b/alienblaster/project/src/MainActivity.java @@ -0,0 +1,106 @@ +// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount +package de.schwardtnet.alienblaster; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.KeyEvent; +import android.view.Window; +import android.view.WindowManager; +import android.os.PowerManager; +import android.widget.TextView; + + +public class MainActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // fullscreen mode + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + + TextView tv = new TextView(this); + tv.setText("Initializing"); + setContentView(tv); + downloader = new DataDownloader(this, tv); + } + + public void initSDL() + { + mLoadLibraryStub = new LoadLibrary(); + mAudioThread = new AudioThread(this); + mGLView = new DemoGLSurfaceView(this); + setContentView(mGLView); + // Receive keyboard events + mGLView.setFocusableInTouchMode(true); + mGLView.setFocusable(true); + mGLView.requestFocus(); + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, Globals.ApplicationName); + wakeLock.acquire(); + } + + @Override + protected void onPause() { + // TODO: if application pauses it's screen is messed up + if( wakeLock != null ) + wakeLock.release(); + super.onPause(); + if( mGLView != null ) + mGLView.onPause(); + } + + @Override + protected void onResume() { + if( wakeLock != null ) + wakeLock.acquire(); + super.onResume(); + if( mGLView != null ) + mGLView.onResume(); + } + + @Override + protected void onStop() + { + if( wakeLock != null ) + wakeLock.release(); + if( mAudioThread != null ) + { + mAudioThread.interrupt(); + try { + mAudioThread.join(); + } catch( java.lang.InterruptedException e ) { }; + } + if( mGLView != null ) + mGLView.exitApp(); + super.onStop(); + finish(); + } + + @Override + public boolean onKeyDown(int keyCode, final KeyEvent event) { + // Overrides Back key to use in our app + if( mGLView != null ) + mGLView.nativeKey( keyCode, 1 ); + if( keyCode == KeyEvent.KEYCODE_BACK && !downloader.DownloadComplete ) + onStop(); + return true; + } + + @Override + public boolean onKeyUp(int keyCode, final KeyEvent event) { + if( mGLView != null ) + mGLView.nativeKey( keyCode, 0 ); + return true; + } + + private DemoGLSurfaceView mGLView = null; + private LoadLibrary mLoadLibraryStub = null; + private AudioThread mAudioThread = null; + private PowerManager.WakeLock wakeLock = null; + private DataDownloader downloader = null; + +} diff --git a/alienblaster/project/src/Video.java b/alienblaster/project/src/Video.java new file mode 100644 index 000000000..2b1d5b473 --- /dev/null +++ b/alienblaster/project/src/Video.java @@ -0,0 +1,124 @@ +// This string is autogenerated by ChangeAppSettings.sh, do not change spaces amount +package de.schwardtnet.alienblaster; + +import javax.microedition.khronos.opengles.GL10; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.KeyEvent; +import android.view.Window; +import android.view.WindowManager; + +import android.widget.TextView; + + +class DemoRenderer extends GLSurfaceView_SDL.Renderer { + + public DemoRenderer(Activity _context) + { + context = _context; + } + + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + // nativeInit(); + } + + public void onSurfaceChanged(GL10 gl, int w, int h) { + //gl.glViewport(0, 0, w, h); + nativeResize(w, h); + } + + public void onDrawFrame(GL10 gl) { + + nativeInitJavaCallbacks(); + + nativeInit(); // Calls main() and never returns, hehe - we'll call eglSwapBuffers() from native code + + } + + public int swapBuffers() // Called from native code, returns 1 on success, 0 when GL context lost (user put app to background) + { + return super.SwapBuffers() ? 1 : 0; + } + + public void exitApp() { + nativeDone(); + }; + + private native void nativeInitJavaCallbacks(); + private native void nativeInit(); + private native void nativeResize(int w, int h); + private native void nativeDone(); + + private Activity context = null; + + private EGL10 mEgl = null; + private EGLDisplay mEglDisplay = null; + private EGLSurface mEglSurface = null; + private EGLContext mEglContext = null; + private int skipFrames = 0; + +} + +class DemoGLSurfaceView extends GLSurfaceView_SDL { + public DemoGLSurfaceView(Activity context) { + super(context); + mParent = context; + accelerometer = new AccelerometerReader(context); + mRenderer = new DemoRenderer(context); + setRenderer(mRenderer); + } + + @Override + public boolean onTouchEvent(final MotionEvent event) + { + // TODO: add multitouch support (added in Android 2.0 SDK) + int action = -1; + if( event.getAction() == MotionEvent.ACTION_DOWN ) + action = 0; + if( event.getAction() == MotionEvent.ACTION_UP ) + action = 1; + if( event.getAction() == MotionEvent.ACTION_MOVE ) + action = 2; + if ( action >= 0 ) { + nativeMouse( (int)event.getX(), (int)event.getY(), action ); + } + return true; + } + + public void exitApp() { + mRenderer.exitApp(); + accelerometer.stop(); + accelerometer = null; + }; + + @Override + public boolean onKeyDown(int keyCode, final KeyEvent event) { + nativeKey( keyCode, 1 ); + return true; + } + + @Override + public boolean onKeyUp(int keyCode, final KeyEvent event) { + nativeKey( keyCode, 0 ); + return true; + } + + DemoRenderer mRenderer; + Activity mParent; + AccelerometerReader accelerometer = null; + + public native void nativeMouse( int x, int y, int action ); + public native void nativeKey( int keyCode, int down ); +} + + diff --git a/alienblaster/readme.txt b/alienblaster/readme.txt index 0afff1d04..0279301a3 100644 --- a/alienblaster/readme.txt +++ b/alienblaster/readme.txt @@ -29,7 +29,7 @@ To exit correctly press Menu key - it's redirected to Escape. This port also supports GL ES + SDL combo - there is GLXGears demo app in project/jni/application/glxgears, remove all files from project/jni/application/src and put glxgears.c there to check if it works. -Note that GL ES is NOT pure OpenGL - there are no glBegin() and glEnd() call and other widely used functions, +Note that GL ES is NOT pure OpenGL - there are no glBegin() and glEnd() call and other widely used functions, and generally it will take a lot of effort to port pure OpenGL application to GL ES. When porting you own app, first of all ensure that your application supports