project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java
changeset 7476 2fb781bbdd51
parent 7449 2e63537b44f3
child 7485 0481bd74267c
equal deleted inserted replaced
7473:45b9f25ff611 7476:2fb781bbdd51
     4 import javax.microedition.khronos.egl.EGLConfig;
     4 import javax.microedition.khronos.egl.EGLConfig;
     5 import javax.microedition.khronos.egl.EGLContext;
     5 import javax.microedition.khronos.egl.EGLContext;
     6 import javax.microedition.khronos.egl.EGLDisplay;
     6 import javax.microedition.khronos.egl.EGLDisplay;
     7 import javax.microedition.khronos.egl.EGLSurface;
     7 import javax.microedition.khronos.egl.EGLSurface;
     8 
     8 
     9 import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
       
    10 import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
     9 import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
    11 import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
    10 import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
       
    11 import org.hedgewars.hedgeroid.frontlib.Flib;
       
    12 import org.hedgewars.hedgeroid.frontlib.Frontlib.GameSetupPtr;
       
    13 import org.hedgewars.hedgeroid.frontlib.Frontlib.GameconnPtr;
       
    14 import org.hedgewars.hedgeroid.netplay.TickHandler;
    12 
    15 
    13 import android.app.Activity;
    16 import android.app.Activity;
    14 import android.content.Context;
    17 import android.content.Context;
    15 import android.graphics.Canvas;
    18 import android.graphics.Canvas;
    16 import android.graphics.PixelFormat;
    19 import android.graphics.PixelFormat;
    21 import android.media.AudioFormat;
    24 import android.media.AudioFormat;
    22 import android.media.AudioManager;
    25 import android.media.AudioManager;
    23 import android.media.AudioTrack;
    26 import android.media.AudioTrack;
    24 import android.os.Bundle;
    27 import android.os.Bundle;
    25 import android.os.Handler;
    28 import android.os.Handler;
       
    29 import android.os.HandlerThread;
    26 import android.os.Message;
    30 import android.os.Message;
    27 import android.util.DisplayMetrics;
    31 import android.util.DisplayMetrics;
    28 import android.util.Log;
    32 import android.util.Log;
    29 import android.view.KeyEvent;
    33 import android.view.KeyEvent;
    30 import android.view.MotionEvent;
    34 import android.view.MotionEvent;
    35 
    39 
    36 /**
    40 /**
    37     SDL Activity
    41     SDL Activity
    38  */
    42  */
    39 public class SDLActivity extends Activity {
    43 public class SDLActivity extends Activity {
    40 
    44 	/**
       
    45 	 * Set startConfig to the desired config when starting this activity. This avoids having to parcel all
       
    46 	 * the config objects into the Intent. Not particularly elegant, but it's actually a recommended
       
    47 	 * way to do this (http://developer.android.com/guide/faq/framework.html#3)
       
    48 	 */
       
    49 	public static volatile GameConfig startConfig;
       
    50 	
    41 	// Main components
    51 	// Main components
    42 	public static SDLActivity mSingleton;
    52 	public static SDLActivity mSingleton;
    43 	private static SDLSurface mSurface;
    53 	private static SDLSurface mSurface;
    44 
    54 
    45 	// This is what SDL runs in. It invokes SDL_main(), eventually
    55 	// This is what SDL runs in. It invokes SDL_main(), eventually
    46 	private static Thread mSDLThread;
    56 	private static Thread mSDLThread; // Guarded by SDLActivity.class
    47 
    57 
    48 	// Audio
    58 	// Audio
    49 	private static Thread mAudioThread;
    59 	private static Thread mAudioThread;
    50 	private static AudioTrack mAudioTrack;
    60 	private static AudioTrack mAudioTrack;
    51 
    61 
    72 
    82 
    73 		// So we can call stuff from static callbacks
    83 		// So we can call stuff from static callbacks
    74 		mSingleton = this;
    84 		mSingleton = this;
    75 
    85 
    76 		// Set up the surface
    86 		// Set up the surface
    77 		GameConfig config = getIntent().getParcelableExtra("config");
    87 		mSurface = new SDLSurface(getApplication(), startConfig);
    78 
       
    79 		mSurface = new SDLSurface(getApplication(), config);
       
    80 		setContentView(mSurface);
    88 		setContentView(mSurface);
    81 		SurfaceHolder holder = mSurface.getHolder();
       
    82 	}
    89 	}
    83 
    90 
    84 	// Events
    91 	// Events
    85 	protected void onPause() {
    92 	protected void onPause() {
    86 		Log.v("SDL", "onPause()");
    93 		Log.v("SDL", "onPause()");
   106 		Log.v("SDL", "onDestroy()");
   113 		Log.v("SDL", "onDestroy()");
   107 		// Send a quit message to the application
   114 		// Send a quit message to the application
   108 		SDLActivity.nativeQuit();
   115 		SDLActivity.nativeQuit();
   109 
   116 
   110 		// Now wait for the SDL thread to quit
   117 		// Now wait for the SDL thread to quit
   111 		if (mSDLThread != null) {
   118 		synchronized(SDLActivity.class) {
   112 			try {
   119 			if (mSDLThread != null) {
   113 				mSDLThread.join();
   120 				try {
   114 			} catch(Exception e) {
   121 					mSDLThread.join();
   115 				Log.v("SDL", "Problem stopping thread: " + e);
   122 				} catch(Exception e) {
   116 			}
   123 					Log.w("SDL", "Problem stopping thread: " + e);
   117 			mSDLThread = null;
   124 				}
   118 
   125 				mSDLThread = null;
   119 			//Log.v("SDL", "Finished waiting for SDL thread");
   126 			}
   120 		}
   127 		}
   121 	}
   128 	}
   122 
   129 
   123 	// Messages from the SDLMain thread
   130 	// Messages from the SDLMain thread
   124 	static int COMMAND_CHANGE_TITLE = 1;
   131 	static int COMMAND_CHANGE_TITLE = 1;
   173 	public static Context getContext() {
   180 	public static Context getContext() {
   174 		return mSingleton;
   181 		return mSingleton;
   175 	}
   182 	}
   176 
   183 
   177 	public static void startApp(int width, int height, GameConfig config) {
   184 	public static void startApp(int width, int height, GameConfig config) {
   178 		// Start up the C app thread
   185 		synchronized(SDLActivity.class) {
   179 		if (mSDLThread == null) {
   186 			// Start up the C app thread
   180 			mSDLThread = new Thread(new SDLMain(width, height, config), "SDLThread");
   187 			if (mSDLThread == null) {
   181 			mSDLThread.start();
   188 				mSDLThread = new Thread(new SDLMain(width, height, config), "SDLThread");
   182 		}
   189 				mSDLThread.start();
   183 		else {
   190 			} else {
   184 			SDLActivity.nativeResume();
   191 				SDLActivity.nativeResume();
       
   192 			}
   185 		}
   193 		}
   186 	}
   194 	}
   187 
   195 
   188 	// EGL functions
   196 	// EGL functions
   189 	public static boolean initEGL(int majorVersion, int minorVersion) {
   197 	public static boolean initEGL(int majorVersion, int minorVersion) {
   423 		surfaceHeight = height;
   431 		surfaceHeight = height;
   424 	}
   432 	}
   425 
   433 
   426 	public void run() {
   434 	public void run() {
   427 		//Set up the IPC socket server to communicate with the engine
   435 		//Set up the IPC socket server to communicate with the engine
   428 		EngineProtocolNetwork ipc = new EngineProtocolNetwork(config);
   436 		HandlerThread thread = new HandlerThread("IPC thread");
       
   437 		thread.start(); // TODO ensure it gets stopped
       
   438 		final GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Xeli", GameSetupPtr.createJavaOwned(config), false);
       
   439 		if(conn == null) {
       
   440 			throw new AssertionError();
       
   441 		}
       
   442 		int port = Flib.INSTANCE.flib_gameconn_getport(conn);
   429 
   443 
   430 		String path = Utils.getDataPath(SDLActivity.mSingleton);//This represents the data directory
   444 		String path = Utils.getDataPath(SDLActivity.mSingleton);//This represents the data directory
   431 		path = path.substring(0, path.length()-1);//remove the trailing '/'
   445 		path = path.substring(0, path.length()-1);//remove the trailing '/'
   432 
   446 
   433 
       
   434 		// Runs SDL_main() with added parameters
   447 		// Runs SDL_main() with added parameters
   435 		SDLActivity.nativeInit(new String[] { String.valueOf(ipc.port),
   448 		SDLActivity.nativeInit(new String[] { String.valueOf(port),
   436 				String.valueOf(surfaceWidth), String.valueOf(surfaceHeight),
   449 				String.valueOf(surfaceWidth), String.valueOf(surfaceHeight),
   437 				"0", "en.txt", "xeli", "1", "1", "1", path, ""  });
   450 				"0", "en.txt", "xeli", "1", "1", "1", path, ""  });
   438 
   451 
       
   452 		new TickHandler(thread.getLooper(), 50, new Runnable() {
       
   453 			public void run() {
       
   454 				Flib.INSTANCE.flib_gameconn_tick(conn);
       
   455 			}
       
   456 		});
   439 		try {
   457 		try {
   440 			ipc.quitIPC();
   458 			thread.quit();
   441 			ipc.join();
   459 			thread.join();
   442 		} catch (InterruptedException e) {
   460 		} catch (InterruptedException e) {
   443 			e.printStackTrace();
   461 			throw new AssertionError();
   444 		}
   462 		}
       
   463 		Flib.INSTANCE.flib_gameconn_destroy(conn);
   445 		Log.v("SDL", "SDL thread terminated");
   464 		Log.v("SDL", "SDL thread terminated");
   446 	}
   465 	}
   447 }
   466 }
   448 
   467 
   449 
   468