project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java
changeset 6599 1d3746138113
parent 6597 814683bbd230
child 6661 d16c898d1fe2
equal deleted inserted replaced
6596:4c06ea12de1c 6599:1d3746138113
     7 import javax.microedition.khronos.egl.EGLSurface;
     7 import javax.microedition.khronos.egl.EGLSurface;
     8 
     8 
     9 import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
     9 import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
    10 import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
    10 import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
    11 import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
    11 import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
    12 import org.hedgewars.hedgeroid.UserInput.TouchInterface;
       
    13 
    12 
    14 import android.app.Activity;
    13 import android.app.Activity;
    15 import android.content.Context;
    14 import android.content.Context;
    16 import android.graphics.Canvas;
    15 import android.graphics.Canvas;
    17 import android.graphics.PixelFormat;
    16 import android.graphics.PixelFormat;
    25 import android.os.Bundle;
    24 import android.os.Bundle;
    26 import android.os.Handler;
    25 import android.os.Handler;
    27 import android.os.Message;
    26 import android.os.Message;
    28 import android.util.Log;
    27 import android.util.Log;
    29 import android.view.KeyEvent;
    28 import android.view.KeyEvent;
       
    29 import android.view.MotionEvent;
    30 import android.view.SurfaceHolder;
    30 import android.view.SurfaceHolder;
    31 import android.view.SurfaceView;
    31 import android.view.SurfaceView;
    32 import android.view.View;
    32 import android.view.View;
    33 
    33 
       
    34 
    34 /**
    35 /**
    35  * SDL Activity
    36     SDL Activity
    36  */
    37  */
    37 public class SDLActivity extends Activity {
    38 public class SDLActivity extends Activity {
    38 
    39 
    39 	// Main components
    40 	// Main components
    40 	public static SDLActivity mSingleton;
    41 	public static SDLActivity mSingleton;
    41 	public static SDLSurface mSurface;
    42 	private static SDLSurface mSurface;
       
    43 
       
    44 	// This is what SDL runs in. It invokes SDL_main(), eventually
       
    45 	private static Thread mSDLThread;
    42 
    46 
    43 	// Audio
    47 	// Audio
    44 	private static Thread mAudioThread;
    48 	private static Thread mAudioThread;
    45 	private static AudioTrack mAudioTrack;
    49 	private static AudioTrack mAudioTrack;
    46 
    50 
       
    51 	// EGL private objects
       
    52 	private static EGLContext  mEGLContext;
       
    53 	private static EGLSurface  mEGLSurface;
       
    54 	private static EGLDisplay  mEGLDisplay;
       
    55 	private static EGLConfig   mEGLConfig;
       
    56 	private static int mGLMajor, mGLMinor;
       
    57 
    47 	// Load the .so
    58 	// Load the .so
    48 	static {
    59 	static {
    49 		System.loadLibrary("SDL");
    60 		System.loadLibrary("SDL");
    50 		System.loadLibrary("SDL_image");
    61 		//System.loadLibrary("SDL_image");
    51 		System.loadLibrary("mikmod");
    62 		//System.loadLibrary("SDL_mixer");
    52 		System.loadLibrary("SDL_net");
    63 		//System.loadLibrary("SDL_ttf");
    53 		System.loadLibrary("SDL_mixer");
       
    54 		System.loadLibrary("SDL_ttf");
       
    55 		System.loadLibrary("lua5.1");
       
    56 		System.loadLibrary("hwengine");
       
    57 		System.loadLibrary("main");
    64 		System.loadLibrary("main");
    58 	}
    65 	}
    59 
    66 
    60 	// Setup
    67 	// Setup
    61 	protected void onCreate(Bundle savedInstanceState) {
    68 	protected void onCreate(Bundle savedInstanceState) {
    62 		// Log.v("SDL", "onCreate()");
    69 		//Log.v("SDL", "onCreate()");
    63 		super.onCreate(savedInstanceState);
    70 		super.onCreate(savedInstanceState);
    64 
    71 
    65 		// So we can call stuff from static callbacks
    72 		// So we can call stuff from static callbacks
    66 		mSingleton = this;
    73 		mSingleton = this;
    67 
    74 
    68 		// Set up the surface
    75 		// Set up the surface
    69 		GameConfig config = getIntent().getParcelableExtra("config");
    76 		GameConfig config = getIntent().getParcelableExtra("config");
       
    77 
    70 		mSurface = new SDLSurface(getApplication(), config);
    78 		mSurface = new SDLSurface(getApplication(), config);
    71 		setContentView(mSurface);
    79 		setContentView(mSurface);
    72 		SurfaceHolder holder = mSurface.getHolder();
    80 		SurfaceHolder holder = mSurface.getHolder();
    73 		holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
       
    74 	}
    81 	}
    75 
    82 
    76 	// Events
    83 	// Events
    77 	protected void onPause() {
    84 	protected void onPause() {
    78 		// Log.v("SDL", "onPause()");
    85 		Log.v("SDL", "onPause()");
    79 		super.onPause();
    86 		super.onPause();
    80 
    87 
       
    88 		if(mEGLDisplay != null && mEGLContext != null){
       
    89 			EGL10 egl = (EGL10)EGLContext.getEGL();
       
    90 			egl.eglDestroyContext(mEGLDisplay, mEGLContext);
       
    91 			mEGLDisplay = null;
       
    92 			mEGLContext = null;
       
    93 		}
       
    94 
       
    95 		SDLActivity.nativePause();
    81 	}
    96 	}
    82 
    97 
    83 	protected void onResume() {
    98 	protected void onResume() {
    84 		// Log.v("SDL", "onResume()");
    99 		Log.v("SDL", "onResume()");
    85 		super.onResume();
   100 		super.onResume();
    86 	}
   101 	}
    87 	
   102 
    88 	public void onBackPressed(){
   103 	public void onBackPressed(){
    89 		nativeQuit();
       
    90 		super.onBackPressed();
   104 		super.onBackPressed();
       
   105 		PascalExports.HWterminate(true);
       
   106 	}
       
   107 
       
   108 	protected void onDestroy() {
       
   109 		super.onDestroy();
       
   110 		Log.v("SDL", "onDestroy()");
       
   111 		// Send a quit message to the application
       
   112 		SDLActivity.nativeQuit();
       
   113 
       
   114 		// Now wait for the SDL thread to quit
       
   115 		if (mSDLThread != null) {
       
   116 			try {
       
   117 				mSDLThread.join();
       
   118 			} catch(Exception e) {
       
   119 				Log.v("SDL", "Problem stopping thread: " + e);
       
   120 			}
       
   121 			mSDLThread = null;
       
   122 
       
   123 			//Log.v("SDL", "Finished waiting for SDL thread");
       
   124 		}
    91 	}
   125 	}
    92 
   126 
    93 	// Messages from the SDLMain thread
   127 	// Messages from the SDLMain thread
    94 	static int COMMAND_CHANGE_TITLE = 1;
   128 	static int COMMAND_CHANGE_TITLE = 1;
    95 
   129 
    96 	// Handler for the messages
   130 	// Handler for the messages
    97 	Handler commandHandler = new Handler() {
   131 	Handler commandHandler = new Handler() {
    98 		public void handleMessage(Message msg) {
   132 		public void handleMessage(Message msg) {
    99 			if (msg.arg1 == COMMAND_CHANGE_TITLE) {
   133 			if (msg.arg1 == COMMAND_CHANGE_TITLE) {
   100 				setTitle((String) msg.obj);
   134 				setTitle((String)msg.obj);
   101 			}
   135 			}
   102 		}
   136 		}
   103 	};
   137 	};
   104 
   138 
   105 	// Send a message from the SDLMain thread
   139 	// Send a message from the SDLMain thread
   109 		msg.obj = data;
   143 		msg.obj = data;
   110 		commandHandler.sendMessage(msg);
   144 		commandHandler.sendMessage(msg);
   111 	}
   145 	}
   112 
   146 
   113 	// C functions we call
   147 	// C functions we call
   114 	public static native void nativeInit(String[] argv);
   148 	public static native void nativeInit(String...args);
   115 
       
   116 	public static native void nativeQuit();
   149 	public static native void nativeQuit();
   117 
   150 	public static native void nativePause();
       
   151 	public static native void nativeResume();
   118 	public static native void onNativeResize(int x, int y, int format);
   152 	public static native void onNativeResize(int x, int y, int format);
   119 
       
   120 	public static native void onNativeKeyDown(int keycode);
   153 	public static native void onNativeKeyDown(int keycode);
   121 
       
   122 	public static native void onNativeKeyUp(int keycode);
   154 	public static native void onNativeKeyUp(int keycode);
   123 
   155 	public static native void onNativeTouch(int touchDevId, int pointerFingerId,
   124 	public static native void onNativeTouch(int touchDevId, int pointerFingerId, int action, float x, float y,
   156 			int action, float x, 
   125 			float p);
   157 			float y, float p);
   126 
       
   127 	public static native void onNativeAccel(float x, float y, float z);
   158 	public static native void onNativeAccel(float x, float y, float z);
   128 
       
   129 	public static native void nativeRunAudioThread();
   159 	public static native void nativeRunAudioThread();
   130 
   160 
       
   161 
   131 	// Java functions called from C
   162 	// Java functions called from C
   132 
   163 
   133 	public static boolean createGLContext(int majorVersion, int minorVersion) {
   164 	public static boolean createGLContext(int majorVersion, int minorVersion) {
   134 		return mSurface.initEGL(majorVersion, minorVersion);
   165 		return initEGL(majorVersion, minorVersion);
   135 	}
   166 	}
   136 
   167 
   137 	public static void flipBuffers() {
   168 	public static void flipBuffers() {
   138 		mSurface.flipEGL();
   169 		flipEGL();
   139 	}
   170 	}
   140 
   171 
   141 	public static void setActivityTitle(String title) {
   172 	public static void setActivityTitle(String title) {
   142 		// Called from SDLMain() thread and can't directly affect the view
   173 		// Called from SDLMain() thread and can't directly affect the view
   143 		mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
   174 		mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
   144 	}
   175 	}
   145 
   176 
       
   177 	public static Context getContext() {
       
   178 		return mSingleton;
       
   179 	}
       
   180 
       
   181 	public static void startApp(int width, int height, GameConfig config) {
       
   182 		// Start up the C app thread
       
   183 		if (mSDLThread == null) {
       
   184 			mSDLThread = new Thread(new SDLMain(width, height, config), "SDLThread");
       
   185 			mSDLThread.start();
       
   186 		}
       
   187 		else {
       
   188 			SDLActivity.nativeResume();
       
   189 		}
       
   190 	}
       
   191 
       
   192 	// EGL functions
       
   193 	public static boolean initEGL(int majorVersion, int minorVersion) {
       
   194 		if (SDLActivity.mEGLDisplay == null) {
       
   195 			//Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion);
       
   196 
       
   197 			try {
       
   198 				EGL10 egl = (EGL10)EGLContext.getEGL();
       
   199 
       
   200 				EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
       
   201 
       
   202 				int[] version = new int[2];
       
   203 				egl.eglInitialize(dpy, version);
       
   204 
       
   205 				int EGL_OPENGL_ES_BIT = 1;
       
   206 				int EGL_OPENGL_ES2_BIT = 4;
       
   207 				int renderableType = 0;
       
   208 				if (majorVersion == 2) {
       
   209 					renderableType = EGL_OPENGL_ES2_BIT;
       
   210 				} else if (majorVersion == 1) {
       
   211 					renderableType = EGL_OPENGL_ES_BIT;
       
   212 				}
       
   213 				int[] configSpec = {
       
   214 						//EGL10.EGL_DEPTH_SIZE,   16,
       
   215 						EGL10.EGL_RENDERABLE_TYPE, renderableType,
       
   216 						EGL10.EGL_NONE
       
   217 				};
       
   218 				EGLConfig[] configs = new EGLConfig[1];
       
   219 				int[] num_config = new int[1];
       
   220 				if (!egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config) || num_config[0] == 0) {
       
   221 					Log.e("SDL", "No EGL config available");
       
   222 					return false;
       
   223 				}
       
   224 				EGLConfig config = configs[0];
       
   225 
       
   226 				/*int EGL_CONTEXT_CLIENT_VERSION=0x3098;
       
   227                 int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, majorVersion, EGL10.EGL_NONE };
       
   228                 EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, contextAttrs);
       
   229 
       
   230                 if (ctx == EGL10.EGL_NO_CONTEXT) {
       
   231                     Log.e("SDL", "Couldn't create context");
       
   232                     return false;
       
   233                 }
       
   234                 SDLActivity.mEGLContext = ctx;*/
       
   235 				SDLActivity.mEGLDisplay = dpy;
       
   236 				SDLActivity.mEGLConfig = config;
       
   237 				SDLActivity.mGLMajor = majorVersion;
       
   238 				SDLActivity.mGLMinor = minorVersion;
       
   239 
       
   240 				SDLActivity.createEGLSurface();
       
   241 			} catch(Exception e) {
       
   242 				Log.v("SDL", e + "");
       
   243 				for (StackTraceElement s : e.getStackTrace()) {
       
   244 					Log.v("SDL", s.toString());
       
   245 				}
       
   246 			}
       
   247 		}
       
   248 		else SDLActivity.createEGLSurface();
       
   249 
       
   250 		return true;
       
   251 	}
       
   252 
       
   253 	public static boolean createEGLContext() {
       
   254 		EGL10 egl = (EGL10)EGLContext.getEGL();
       
   255 		int EGL_CONTEXT_CLIENT_VERSION=0x3098;
       
   256 		int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE };
       
   257 		SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs);
       
   258 		if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
       
   259 			Log.e("SDL", "Couldn't create context");
       
   260 			return false;
       
   261 		}
       
   262 		return true;
       
   263 	}
       
   264 
       
   265 	public static boolean createEGLSurface() {
       
   266 		if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) {
       
   267 			EGL10 egl = (EGL10)EGLContext.getEGL();
       
   268 			if (SDLActivity.mEGLContext == null) createEGLContext();
       
   269 
       
   270 			Log.v("SDL", "Creating new EGL Surface");
       
   271 			EGLSurface surface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null);
       
   272 			if (surface == EGL10.EGL_NO_SURFACE) {
       
   273 				Log.e("SDL", "Couldn't create surface");
       
   274 				return false;
       
   275 			}
       
   276 
       
   277 			if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) {
       
   278 				Log.e("SDL", "Old EGL Context doesnt work, trying with a new one");
       
   279 				createEGLContext();
       
   280 				if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) {
       
   281 					Log.e("SDL", "Failed making EGL Context current");
       
   282 					return false;
       
   283 				}
       
   284 			}
       
   285 			SDLActivity.mEGLSurface = surface;
       
   286 			return true;
       
   287 		}
       
   288 		return false;
       
   289 	}
       
   290 
       
   291 	// EGL buffer flip
       
   292 	public static void flipEGL() {
       
   293 		try {
       
   294 			EGL10 egl = (EGL10)EGLContext.getEGL();
       
   295 
       
   296 			egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null);
       
   297 
       
   298 			// drawing here
       
   299 
       
   300 			egl.eglWaitGL();
       
   301 
       
   302 			egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
       
   303 
       
   304 
       
   305 		} catch(Exception e) {
       
   306 			Log.v("SDL", "flipEGL(): " + e);
       
   307 			for (StackTraceElement s : e.getStackTrace()) {
       
   308 				Log.v("SDL", s.toString());
       
   309 			}
       
   310 		}
       
   311 	}
       
   312 
   146 	// Audio
   313 	// Audio
   147 	private static Object buf;
   314 	private static Object buf;
   148 
   315 
   149 	public static Object audioInit(int sampleRate, boolean is16Bit,
   316 	public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
   150 			boolean isStereo, int desiredFrames) {
   317 		int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
   151 		int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO
   318 		int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
   152 				: AudioFormat.CHANNEL_CONFIGURATION_MONO;
       
   153 		int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT
       
   154 				: AudioFormat.ENCODING_PCM_8BIT;
       
   155 		int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
   319 		int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
   156 
   320 
   157 		Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono")
   321 		Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
   158 				+ " " + (is16Bit ? "16-bit" : "8-bit") + " "
       
   159 				+ ((float) sampleRate / 1000f) + "kHz, " + desiredFrames
       
   160 				+ " frames buffer");
       
   161 
   322 
   162 		// Let the user pick a larger buffer if they really want -- but ye
   323 		// Let the user pick a larger buffer if they really want -- but ye
   163 		// gods they probably shouldn't, the minimums are horrifyingly high
   324 		// gods they probably shouldn't, the minimums are horrifyingly high
   164 		// latency already
   325 		// latency already
   165 		desiredFrames = Math.max(
   326 		desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
   166 				desiredFrames,
       
   167 				(AudioTrack.getMinBufferSize(sampleRate, channelConfig,
       
   168 						audioFormat) + frameSize - 1)
       
   169 						/ frameSize);
       
   170 
   327 
   171 		mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
   328 		mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
   172 				channelConfig, audioFormat, desiredFrames * frameSize,
   329 				channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
   173 				AudioTrack.MODE_STREAM);
       
   174 
   330 
   175 		audioStartThread();
   331 		audioStartThread();
   176 
   332 
   177 		Log.v("SDL",
   333 		Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
   178 				"SDL audio: got "
       
   179 						+ ((mAudioTrack.getChannelCount() >= 2) ? "stereo"
       
   180 								: "mono")
       
   181 						+ " "
       
   182 						+ ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit"
       
   183 								: "8-bit") + " "
       
   184 						+ ((float) mAudioTrack.getSampleRate() / 1000f)
       
   185 						+ "kHz, " + desiredFrames + " frames buffer");
       
   186 
   334 
   187 		if (is16Bit) {
   335 		if (is16Bit) {
   188 			buf = new short[desiredFrames * (isStereo ? 2 : 1)];
   336 			buf = new short[desiredFrames * (isStereo ? 2 : 1)];
   189 		} else {
   337 		} else {
   190 			buf = new byte[desiredFrames * (isStereo ? 2 : 1)];
   338 			buf = new byte[desiredFrames * (isStereo ? 2 : 1)]; 
   191 		}
   339 		}
   192 		return buf;
   340 		return buf;
   193 	}
   341 	}
   194 
   342 
   195 	public static void audioStartThread() {
   343 	public static void audioStartThread() {
   204 		mAudioThread.setPriority(Thread.MAX_PRIORITY);
   352 		mAudioThread.setPriority(Thread.MAX_PRIORITY);
   205 		mAudioThread.start();
   353 		mAudioThread.start();
   206 	}
   354 	}
   207 
   355 
   208 	public static void audioWriteShortBuffer(short[] buffer) {
   356 	public static void audioWriteShortBuffer(short[] buffer) {
   209 		for (int i = 0; i < buffer.length;) {
   357 		for (int i = 0; i < buffer.length; ) {
   210 			int result = mAudioTrack.write(buffer, i, buffer.length - i);
   358 			int result = mAudioTrack.write(buffer, i, buffer.length - i);
   211 			if (result > 0) {
   359 			if (result > 0) {
   212 				i += result;
   360 				i += result;
   213 			} else if (result == 0) {
   361 			} else if (result == 0) {
   214 				try {
   362 				try {
   215 					Thread.sleep(1);
   363 					Thread.sleep(1);
   216 				} catch (InterruptedException e) {
   364 				} catch(InterruptedException e) {
   217 					// Nom nom
   365 					// Nom nom
   218 				}
   366 				}
   219 			} else {
   367 			} else {
   220 				Log.w("SDL", "SDL audio: error return from write(short)");
   368 				Log.w("SDL", "SDL audio: error return from write(short)");
   221 				return;
   369 				return;
   222 			}
   370 			}
   223 		}
   371 		}
   224 	}
   372 	}
   225 
   373 
   226 	public static void audioWriteByteBuffer(byte[] buffer) {
   374 	public static void audioWriteByteBuffer(byte[] buffer) {
   227 		for (int i = 0; i < buffer.length;) {
   375 		for (int i = 0; i < buffer.length; ) {
   228 			int result = mAudioTrack.write(buffer, i, buffer.length - i);
   376 			int result = mAudioTrack.write(buffer, i, buffer.length - i);
   229 			if (result > 0) {
   377 			if (result > 0) {
   230 				i += result;
   378 				i += result;
   231 			} else if (result == 0) {
   379 			} else if (result == 0) {
   232 				try {
   380 				try {
   233 					Thread.sleep(1);
   381 					Thread.sleep(1);
   234 				} catch (InterruptedException e) {
   382 				} catch(InterruptedException e) {
   235 					// Nom nom
   383 					// Nom nom
   236 				}
   384 				}
   237 			} else {
   385 			} else {
   238 				Log.w("SDL", "SDL audio: error return from write(short)");
   386 				Log.w("SDL", "SDL audio: error return from write(short)");
   239 				return;
   387 				return;
   243 
   391 
   244 	public static void audioQuit() {
   392 	public static void audioQuit() {
   245 		if (mAudioThread != null) {
   393 		if (mAudioThread != null) {
   246 			try {
   394 			try {
   247 				mAudioThread.join();
   395 				mAudioThread.join();
   248 			} catch (Exception e) {
   396 			} catch(Exception e) {
   249 				Log.v("SDL", "Problem stopping audio thread: " + e);
   397 				Log.v("SDL", "Problem stopping audio thread: " + e);
   250 			}
   398 			}
   251 			mAudioThread = null;
   399 			mAudioThread = null;
   252 
   400 
   253 			// Log.v("SDL", "Finished waiting for audio thread");
   401 			//Log.v("SDL", "Finished waiting for audio thread");
   254 		}
   402 		}
   255 
   403 
   256 		if (mAudioTrack != null) {
   404 		if (mAudioTrack != null) {
   257 			mAudioTrack.stop();
   405 			mAudioTrack.stop();
   258 			mAudioTrack = null;
   406 			mAudioTrack = null;
   259 		}
   407 		}
   260 	}
   408 	}
   261 }
   409 }
   262 
   410 
   263 /**
   411 /**
   264  * Simple nativeInit() runnable
   412     Simple nativeInit() runnable
   265  */
   413  */
   266 class SDLMain implements Runnable {
   414 class SDLMain implements Runnable {
       
   415 
   267 	private int surfaceWidth, surfaceHeight;
   416 	private int surfaceWidth, surfaceHeight;
   268 	private GameConfig config;
   417 	private GameConfig config;
   269 
   418 
   270 	public SDLMain(int width, int height, GameConfig _config) {
   419 	public SDLMain(int width, int height, GameConfig _config) {
   271 		config = _config;
   420 		config = _config;
   278 		EngineProtocolNetwork ipc = new EngineProtocolNetwork(config);
   427 		EngineProtocolNetwork ipc = new EngineProtocolNetwork(config);
   279 
   428 
   280 		String path = Utils.getDataPath(SDLActivity.mSingleton);//This represents the data directory
   429 		String path = Utils.getDataPath(SDLActivity.mSingleton);//This represents the data directory
   281 		path = path.substring(0, path.length()-1);//remove the trailing '/'
   430 		path = path.substring(0, path.length()-1);//remove the trailing '/'
   282 
   431 
   283 		
   432 
   284 		// Runs SDL_main() with added parameters
   433 		// Runs SDL_main() with added parameters
   285 		SDLActivity.nativeInit(new String[] { String.valueOf(ipc.port),
   434 		SDLActivity.nativeInit(new String[] { String.valueOf(ipc.port),
   286 				String.valueOf(surfaceWidth), String.valueOf(surfaceHeight),
   435 				String.valueOf(surfaceWidth), String.valueOf(surfaceHeight),
   287 				"0", "null", "xeli", "1", "1", "1", path, ""  });
   436 				"0", "null", "xeli", "1", "1", "1", path, ""  });
   288 
   437 
   291 			ipc.join();
   440 			ipc.join();
   292 		} catch (InterruptedException e) {
   441 		} catch (InterruptedException e) {
   293 			e.printStackTrace();
   442 			e.printStackTrace();
   294 		}
   443 		}
   295 		//Log.v("SDL", "SDL thread terminated");
   444 		//Log.v("SDL", "SDL thread terminated");
   296 		SDLActivity.mSingleton.finish();
   445 		//Log.v("SDL", "SDL thread terminated");
   297 	}
   446 	}
   298 }
   447 }
   299 
   448 
       
   449 
   300 /**
   450 /**
   301  * SDLSurface. This is what we draw on, so we need to know when it's created in
   451     SDLSurface. This is what we draw on, so we need to know when it's created
   302  * order to do anything useful.
   452     in order to do anything useful. 
   303  * 
   453 
   304  * Because of this, that's where we set up the SDL thread
   454     Because of this, that's where we set up the SDL thread
   305  */
   455  */
   306 class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
   456 class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, 
   307 		View.OnKeyListener, SensorEventListener {
   457 View.OnKeyListener, View.OnTouchListener, SensorEventListener  {
   308 
   458 
   309 	// This is what SDL runs in. It invokes SDL_main(), eventually
   459 	private GameConfig config;
   310 	private Thread mSDLThread;
       
   311 
       
   312 	// EGL private objects
       
   313 	private EGLContext mEGLContext;
       
   314 	private EGLSurface mEGLSurface;
       
   315 	private EGLDisplay mEGLDisplay;
       
   316 
   460 
   317 	// Sensors
   461 	// Sensors
   318 	private static SensorManager mSensorManager;
   462 	private static SensorManager mSensorManager;
   319 
   463 
   320 	private GameConfig config;
   464 	// Startup    
   321 
       
   322 	// Startup
       
   323 	public SDLSurface(Context context, GameConfig _config) {
   465 	public SDLSurface(Context context, GameConfig _config) {
   324 		super(context);
   466 		super(context);
   325 		getHolder().addCallback(this);
   467 		getHolder().addCallback(this); 
   326 
   468 
   327 		setFocusable(true);
   469 		setFocusable(true);
   328 		setFocusableInTouchMode(true);
   470 		setFocusableInTouchMode(true);
   329 		requestFocus();
   471 		requestFocus();
   330 		setOnKeyListener(this);
   472 		setOnKeyListener(this); 
   331 		setOnTouchListener(TouchInterface.getTouchInterface());
   473 		setOnTouchListener(this);   
   332 
   474 
   333 		mSensorManager = (SensorManager) context.getSystemService("sensor");
   475 		mSensorManager = (SensorManager)context.getSystemService("sensor");
   334 
       
   335 		config = _config;
   476 		config = _config;
   336 	}
   477 	}
   337 
   478 
   338 	// Called when we have a valid drawing surface
   479 	// Called when we have a valid drawing surface
   339 	public void surfaceCreated(SurfaceHolder holder) {
   480 	public void surfaceCreated(SurfaceHolder holder) {
   340 		Log.v("SDL", "surfaceCreated()");
   481 		Log.v("SDL", "surfaceCreated()");
   341 
   482 		holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
   342 		//enableSensor(Sensor.TYPE_ACCELEROMETER, true);
   483 		SDLActivity.createEGLSurface();
       
   484 		enableSensor(Sensor.TYPE_ACCELEROMETER, true);
   343 	}
   485 	}
   344 
   486 
   345 	// Called when we lose the surface
   487 	// Called when we lose the surface
   346 	public void surfaceDestroyed(SurfaceHolder holder) {
   488 	public void surfaceDestroyed(SurfaceHolder holder) {
   347 		Log.v("SDL", "surfaceDestroyed()");
   489 		Log.v("SDL", "surfaceDestroyed()");
   348 
   490 		SDLActivity.nativePause();
   349 		// Send a quit message to the application
   491 		enableSensor(Sensor.TYPE_ACCELEROMETER, false);
   350 		//SDLActivity.nativeQuit();
       
   351                 PascalExports.HWterminate(true);
       
   352 
       
   353 		// Now wait for the SDL thread to quit
       
   354 		if (mSDLThread != null) {
       
   355 			try {
       
   356 				mSDLThread.join();
       
   357 			} catch (Exception e) {
       
   358 				Log.v("SDL", "Problem stopping thread: " + e);
       
   359 			}
       
   360 			mSDLThread = null;
       
   361 
       
   362 			Log.v("SDL", "Finished waiting for SDL thread");
       
   363 		}
       
   364 
       
   365 		//enableSensor(Sensor.TYPE_ACCELEROMETER, false);
       
   366 	}
   492 	}
   367 
   493 
   368 	// Called when the surface is resized
   494 	// Called when the surface is resized
   369 	public void surfaceChanged(SurfaceHolder holder, int format, int width,
   495 	public void surfaceChanged(SurfaceHolder holder,
   370 			int height) {
   496 			int format, int width, int height) {
   371 		Log.d("SDL", "surfaceChanged()" + width + " + " + height);
   497 		Log.v("SDL", "surfaceChanged()");
   372 
   498 
   373 		int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default
   499 		int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default
   374 		switch (format) {
   500 		switch (format) {
   375 		case PixelFormat.A_8:
   501 		case PixelFormat.A_8:
   376 			Log.v("SDL", "pixel format A_8");
   502 			Log.v("SDL", "pixel format A_8");
   413 		default:
   539 		default:
   414 			Log.v("SDL", "pixel format unknown " + format);
   540 			Log.v("SDL", "pixel format unknown " + format);
   415 			break;
   541 			break;
   416 		}
   542 		}
   417 		SDLActivity.onNativeResize(width, height, sdlFormat);
   543 		SDLActivity.onNativeResize(width, height, sdlFormat);
   418 
   544 		Log.v("SDL", "Window size:" + width + "x"+height);
   419 		// Now start up the C app thread
   545 
   420 		if (mSDLThread == null) {
   546 		SDLActivity.startApp(width, height, config);
   421 			mSDLThread = new Thread(new SDLMain(width, height, config),
       
   422 					"SDLThread");
       
   423 			mSDLThread.start();
       
   424 		}
       
   425 	}
   547 	}
   426 
   548 
   427 	// unused
   549 	// unused
   428 	public void onDraw(Canvas canvas) {
   550 	public void onDraw(Canvas canvas) {}
   429 	}
   551 
   430 
   552 
   431 	// EGL functions
   553 
   432 	public boolean initEGL(int majorVersion, int minorVersion) {
       
   433 		Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "."
       
   434 				+ minorVersion);
       
   435 
       
   436 		try {
       
   437 			EGL10 egl = (EGL10) EGLContext.getEGL();
       
   438 
       
   439 			EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
       
   440 
       
   441 			int[] version = new int[2];
       
   442 			egl.eglInitialize(dpy, version);
       
   443 
       
   444 			int EGL_OPENGL_ES_BIT = 1;
       
   445 			int EGL_OPENGL_ES2_BIT = 4;
       
   446 			int renderableType = 0;
       
   447 			if (majorVersion == 2) {
       
   448 				renderableType = EGL_OPENGL_ES2_BIT;
       
   449 			} else if (majorVersion == 1) {
       
   450 				renderableType = EGL_OPENGL_ES_BIT;
       
   451 			}
       
   452 			int[] configSpec = {
       
   453 					// EGL10.EGL_DEPTH_SIZE, 16,
       
   454 					EGL10.EGL_RENDERABLE_TYPE, renderableType, EGL10.EGL_NONE };
       
   455 			EGLConfig[] configs = new EGLConfig[1];
       
   456 			int[] num_config = new int[1];
       
   457 			if (!egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config)
       
   458 					|| num_config[0] == 0) {
       
   459 				Log.e("SDL", "No EGL config available");
       
   460 				return false;
       
   461 			}
       
   462 			EGLConfig config = configs[0];
       
   463 
       
   464 			EGLContext ctx = egl.eglCreateContext(dpy, config,
       
   465 					EGL10.EGL_NO_CONTEXT, null);
       
   466 			if (ctx == EGL10.EGL_NO_CONTEXT) {
       
   467 				Log.e("SDL", "Couldn't create context");
       
   468 				return false;
       
   469 			}
       
   470 
       
   471 			EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this,
       
   472 					null);
       
   473 			if (surface == EGL10.EGL_NO_SURFACE) {
       
   474 				Log.e("SDL", "Couldn't create surface");
       
   475 				return false;
       
   476 			}
       
   477 
       
   478 			if (!egl.eglMakeCurrent(dpy, surface, surface, ctx)) {
       
   479 				Log.e("SDL", "Couldn't make context current");
       
   480 				return false;
       
   481 			}
       
   482 
       
   483 			mEGLContext = ctx;
       
   484 			mEGLDisplay = dpy;
       
   485 			mEGLSurface = surface;
       
   486 
       
   487 		} catch (Exception e) {
       
   488 			Log.v("SDL", e + "");
       
   489 			for (StackTraceElement s : e.getStackTrace()) {
       
   490 				Log.v("SDL", s.toString());
       
   491 			}
       
   492 		}
       
   493 
       
   494 		return true;
       
   495 	}
       
   496 
       
   497 	// EGL buffer flip
       
   498 	public void flipEGL() {
       
   499 		try {
       
   500 			EGL10 egl = (EGL10) EGLContext.getEGL();
       
   501 
       
   502 			egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null);
       
   503 
       
   504 			// drawing here
       
   505 
       
   506 			egl.eglWaitGL();
       
   507 
       
   508 			egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);
       
   509 
       
   510 		} catch (Exception e) {
       
   511 			Log.v("SDL", "flipEGL(): " + e);
       
   512 			for (StackTraceElement s : e.getStackTrace()) {
       
   513 				Log.v("SDL", s.toString());
       
   514 			}
       
   515 			
       
   516 		}
       
   517 	}
       
   518 
   554 
   519 	// Key events
   555 	// Key events
   520 	public boolean onKey(View v, int keyCode, KeyEvent event) {
   556 	public boolean onKey(View  v, int keyCode, KeyEvent event) {
   521                 if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) return false;
   557 		if(keyCode == KeyEvent.KEYCODE_BACK) return false;
   522 		if (event.getAction() == KeyEvent.ACTION_DOWN) {
   558 		if (event.getAction() == KeyEvent.ACTION_DOWN) {
   523 			Log.v("SDL", "key down: " + keyCode);
   559 			//Log.v("SDL", "key down: " + keyCode);
   524 			if(keyCode == KeyEvent.KEYCODE_BACK){//TODO ask user to quit or not
   560 			SDLActivity.onNativeKeyDown(keyCode);
   525 				PascalExports.HWterminate(true);
       
   526 				//SDLActivity.mSingleton.finish();
       
   527 			}else{
       
   528 				SDLActivity.onNativeKeyDown(keyCode);	
       
   529 			}
       
   530 			
       
   531 			return true;
   561 			return true;
   532 		} else if (event.getAction() == KeyEvent.ACTION_UP) {
   562 		}
   533 			Log.v("SDL", "key up: " + keyCode);
   563 		else if (event.getAction() == KeyEvent.ACTION_UP) {
       
   564 			//Log.v("SDL", "key up: " + keyCode);
   534 			SDLActivity.onNativeKeyUp(keyCode);
   565 			SDLActivity.onNativeKeyUp(keyCode);
   535 			return true;
   566 			return true;
   536 		}
   567 		}
   537 
   568 
   538 		return false;
   569 		return false;
   539 	}
   570 	}
       
   571 
       
   572 	// Touch events
       
   573 	public boolean onTouch(View v, MotionEvent event) {
       
   574 		{
       
   575 			final int touchDevId = event.getDeviceId();
       
   576 			final int pointerCount = event.getPointerCount();
       
   577 			// touchId, pointerId, action, x, y, pressure
       
   578 			int actionPointerIndex = event.getActionIndex();
       
   579 			int pointerFingerId = event.getPointerId(actionPointerIndex);
       
   580 			int action = event.getActionMasked();
       
   581 
       
   582 			float x = event.getX(actionPointerIndex);
       
   583 			float y = event.getY(actionPointerIndex);
       
   584 			float p = event.getPressure(actionPointerIndex);
       
   585 
       
   586 			if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
       
   587 				// TODO send motion to every pointer if its position has
       
   588 				// changed since prev event.
       
   589 				for (int i = 0; i < pointerCount; i++) {
       
   590 					pointerFingerId = event.getPointerId(i);
       
   591 					x = event.getX(i);
       
   592 					y = event.getY(i);
       
   593 					p = event.getPressure(i);
       
   594 					SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
       
   595 				}
       
   596 			} else {
       
   597 				SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
       
   598 			}
       
   599 		}
       
   600 		return true;
       
   601 	} 
   540 
   602 
   541 	// Sensor events
   603 	// Sensor events
   542 	public void enableSensor(int sensortype, boolean enabled) {
   604 	public void enableSensor(int sensortype, boolean enabled) {
   543 		// TODO: This uses getDefaultSensor - what if we have >1 accels?
   605 		// TODO: This uses getDefaultSensor - what if we have >1 accels?
   544 		if (enabled) {
   606 		if (enabled) {
   545 			mSensorManager.registerListener(this,
   607 			mSensorManager.registerListener(this, 
   546 					mSensorManager.getDefaultSensor(sensortype),
   608 					mSensorManager.getDefaultSensor(sensortype), 
   547 					SensorManager.SENSOR_DELAY_GAME, null);
   609 					SensorManager.SENSOR_DELAY_GAME, null);
   548 		} else {
   610 		} else {
   549 			mSensorManager.unregisterListener(this,
   611 			mSensorManager.unregisterListener(this, 
   550 					mSensorManager.getDefaultSensor(sensortype));
   612 					mSensorManager.getDefaultSensor(sensortype));
   551 		}
   613 		}
   552 	}
   614 	}
   553 
   615 
   554 	public void onAccuracyChanged(Sensor sensor, int accuracy) {
   616 	public void onAccuracyChanged(Sensor sensor, int accuracy) {
   555 		// TODO
   617 		// TODO
   556 	}
   618 	}
   557 
   619 
   558 	public void onSensorChanged(SensorEvent event) {
   620 	public void onSensorChanged(SensorEvent event) {
   559 		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
   621 		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
   560 			SDLActivity.onNativeAccel(event.values[0], event.values[1],
   622 			SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH,
   561 					event.values[2]);
   623 					event.values[1] / SensorManager.GRAVITY_EARTH,
       
   624 					event.values[2] / SensorManager.GRAVITY_EARTH);
   562 		}
   625 		}
   563 	}
   626 	}
   564 
   627 
   565 }
   628 }
       
   629