[Scummvm-cvs-logs] scummvm master -> aa2a2e046b0a5979709c79deb84b6eea3c8f09d5

dhewg dhewg at wiibrew.org
Sun Feb 27 10:17:45 CET 2011


This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
6b1c575d1d ANDROID: Remove another weird workaround
983e16b36a ANDROID: Formatting
25d895b859 ANDROID: Rework audio system
bea57f6950 AUDIO: Make mixCallback return the sample count
0e869a5cf0 ANDROID: Pause the AudioTrack when possible
d4c0501d1f ANDROID: Check audio buffer for silence
a73b2ec972 ANDROID: Remove unnecessary code
1c95d47cfa SWORD2: Respect screen pitch while postprocessing
aa2a2e046b SWORD2: Reduce overhead


Commit: 6b1c575d1d6471a922978559c69426b1f9856768
    https://github.com/scummvm/scummvm/commit/6b1c575d1d6471a922978559c69426b1f9856768
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:31-08:00

Commit Message:
ANDROID: Remove another weird workaround

Changed paths:
    backends/platform/android/gfx.cpp



diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 35c91d7..8601a3b 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -401,7 +401,7 @@ void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
 	_overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
 
 	// Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
-	updateScreen();
+	//updateScreen();
 }
 
 int16 OSystem_Android::getOverlayHeight() {


Commit: 983e16b36a68292021833aa9b69305a37ffe2f91
    https://github.com/scummvm/scummvm/commit/983e16b36a68292021833aa9b69305a37ffe2f91
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:31-08:00

Commit Message:
ANDROID: Formatting

Changed paths:
    backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
    backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
    backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
    backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
    backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java



diff --git a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
index 1a0972d..cede7ee 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
@@ -19,7 +19,7 @@ public class EditableSurfaceView extends SurfaceView {
 	}
 
 	public EditableSurfaceView(Context context, AttributeSet attrs,
-							   int defStyle) {
+								int defStyle) {
 		super(context, attrs, defStyle);
 	}
 
@@ -40,7 +40,9 @@ public class EditableSurfaceView extends SurfaceView {
 					getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 				imm.hideSoftInputFromWindow(getWindowToken(), 0);
 			}
-			return super.performEditorAction(actionCode); // Sends enter key
+
+			// Sends enter key
+			return super.performEditorAction(actionCode);
 		}
 	}
 
@@ -49,11 +51,12 @@ public class EditableSurfaceView extends SurfaceView {
 		outAttrs.initialCapsMode = 0;
 		outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
 		outAttrs.inputType = (InputType.TYPE_CLASS_TEXT |
-							  InputType.TYPE_TEXT_VARIATION_NORMAL |
-							  InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+								InputType.TYPE_TEXT_VARIATION_NORMAL |
+								InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
 		outAttrs.imeOptions = (EditorInfo.IME_ACTION_DONE |
-							   EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+								EditorInfo.IME_FLAG_NO_EXTRACT_UI);
 
 		return new MyInputConnection();
 	}
 }
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
index c94ab0a..3c91d9f 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
@@ -28,7 +28,7 @@ public class PluginProvider extends BroadcastReceiver {
 		try {
 			info = context.getPackageManager()
 				.getReceiverInfo(new ComponentName(context, this.getClass()),
-								 PackageManager.GET_META_DATA);
+									PackageManager.GET_META_DATA);
 		} catch (PackageManager.NameNotFoundException e) {
 			Log.e(LOG_TAG, "Error finding my own info?", e);
 			return;
@@ -38,17 +38,17 @@ public class PluginProvider extends BroadcastReceiver {
 		if (mylib != null) {
 			ArrayList<String> all_libs =
 				extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
-
 			all_libs.add(new Uri.Builder()
-						 .scheme("plugin")
-						 .authority(context.getPackageName())
-						 .path(mylib)
-						 .toString());
+							.scheme("plugin")
+							.authority(context.getPackageName())
+							.path(mylib)
+							.toString());
 
 			extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
-									  all_libs);
+										all_libs);
 		}
 
 		setResultExtras(extras);
 	}
 }
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index 0e905f4..698e508 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -35,16 +35,19 @@ import java.util.LinkedHashMap;
 public class ScummVM implements SurfaceHolder.Callback {
 	protected final static String LOG_TAG = "ScummVM";
 
-	private final int AUDIO_FRAME_SIZE = 2 * 2;	 // bytes. 16bit audio * stereo
+	// bytes. 16bit audio * stereo
+	private final int AUDIO_FRAME_SIZE = 2 * 2;
 	public static class AudioSetupException extends Exception {}
 
-	private long nativeScummVM;	// native code hangs itself here
+	// native code hangs itself here
+	private long nativeScummVM;
 	boolean scummVMRunning = false;
 
 	private native void create(AssetManager am);
 
 	public ScummVM(Context context) {
-		create(context.getAssets());  // Init C++ code, set nativeScummVM
+		// Init C++ code, set nativeScummVM
+		create(context.getAssets());
 	}
 
 	private native void nativeDestroy();
@@ -55,6 +58,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 			nativeScummVM = 0;
 		}
 	}
+
 	protected void finalize() {
 		destroy();
 	}
@@ -62,17 +66,17 @@ public class ScummVM implements SurfaceHolder.Callback {
 	// Surface creation:
 	// GUI thread: create surface, release lock
 	// ScummVM thread: acquire lock (block), read surface
-	//
+
 	// Surface deletion:
 	// GUI thread: post event, acquire lock (block), return
 	// ScummVM thread: read event, free surface, release lock
-	//
+
 	// In other words, ScummVM thread does this:
 	//	acquire lock
 	//	setup surface
 	//	when SCREEN_CHANGED arrives:
-	//	 destroy surface
-	//	 release lock
+	//		destroy surface
+	//		release lock
 	//	back to acquire lock
 	static final int configSpec[] = {
 		EGL10.EGL_RED_SIZE, 5,
@@ -82,6 +86,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 		EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
 		EGL10.EGL_NONE,
 	};
+
 	EGL10 egl;
 	EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
 	EGLConfig eglConfig;
@@ -96,7 +101,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 	}
 
 	public void surfaceChanged(SurfaceHolder holder, int format,
-							   int width, int height) {
+								int width, int height) {
 		// Disabled while I debug GL problems
 		pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
 	}
@@ -111,6 +116,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 
 	// For debugging
 	private static final Map<String, Integer> attribs;
+
 	static {
 		attribs = new LinkedHashMap<String, Integer>();
 		attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID);
@@ -141,11 +147,14 @@ public class ScummVM implements SurfaceHolder.Callback {
 		attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE);
 		attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE);
 	}
+
 	private void dumpEglConfig(EGLConfig config) {
 		int[] value = new int[1];
+
 		for (Map.Entry<String, Integer> entry : attribs.entrySet()) {
 			egl.eglGetConfigAttrib(eglDisplay, config,
-								   entry.getValue(), value);
+									entry.getValue(), value);
+
 			if (value[0] == EGL10.EGL_NONE)
 				Log.d(LOG_TAG, entry.getKey() + ": NONE");
 			else
@@ -157,12 +166,15 @@ public class ScummVM implements SurfaceHolder.Callback {
 	private void createScummVMGLContext() {
 		egl = (EGL10)EGLContext.getEGL();
 		eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
 		int[] version = new int[2];
 		egl.eglInitialize(eglDisplay, version);
+
 		int[] num_config = new int[1];
 		egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
 
 		final int numConfigs = num_config[0];
+
 		if (numConfigs <= 0)
 			throw new IllegalArgumentException("No configs match configSpec");
 
@@ -179,13 +191,15 @@ public class ScummVM implements SurfaceHolder.Callback {
 		// Android's eglChooseConfig is busted in several versions and
 		// devices so we have to filter/rank the configs again ourselves.
 		eglConfig = chooseEglConfig(configs);
+
 		if (false) {
 			Log.d(LOG_TAG, String.format("Chose EGL config from %d possibilities.", numConfigs));
 			dumpEglConfig(eglConfig);
 		}
 
 		eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
-										  EGL10.EGL_NO_CONTEXT, null);
+											EGL10.EGL_NO_CONTEXT, null);
+
 		if (eglContext == EGL10.EGL_NO_CONTEXT)
 			throw new RuntimeException("Failed to create context");
 	}
@@ -198,32 +212,43 @@ public class ScummVM implements SurfaceHolder.Callback {
 		for (int i = 0; i < configs.length; i++) {
 			EGLConfig config = configs[i];
 			int score = 10000;
+
 			egl.eglGetConfigAttrib(eglDisplay, config,
-								   EGL10.EGL_SURFACE_TYPE, value);
+									EGL10.EGL_SURFACE_TYPE, value);
+
+			// must have
 			if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0)
-				continue;  // must have
+				continue;
 
 			egl.eglGetConfigAttrib(eglDisplay, config,
-								   EGL10.EGL_CONFIG_CAVEAT, value);
+									EGL10.EGL_CONFIG_CAVEAT, value);
+
 			if (value[0] != EGL10.EGL_NONE)
 				score -= 1000;
 
 			// Must be at least 555, but then smaller is better
-			final int[] colorBits = {EGL10.EGL_RED_SIZE,
-									 EGL10.EGL_GREEN_SIZE,
-									 EGL10.EGL_BLUE_SIZE,
-									 EGL10.EGL_ALPHA_SIZE};
+			final int[] colorBits = { EGL10.EGL_RED_SIZE,
+										EGL10.EGL_GREEN_SIZE,
+										EGL10.EGL_BLUE_SIZE,
+										EGL10.EGL_ALPHA_SIZE
+									};
+
 			for (int component : colorBits) {
-				egl.eglGetConfigAttrib(eglDisplay, config,
-									   component, value);
+				egl.eglGetConfigAttrib(eglDisplay, config, component, value);
+
+				// boost if >5 bits accuracy
 				if (value[0] >= 5)
-					score += 10;   // boost if >5 bits accuracy
-				score -= value[0]; // penalize for wasted bits
+					score += 10;
+
+				// penalize for wasted bits
+				score -= value[0];
 			}
 
 			egl.eglGetConfigAttrib(eglDisplay, config,
-								   EGL10.EGL_DEPTH_SIZE, value);
-			score -= value[0];  // penalize for wasted bits
+									EGL10.EGL_DEPTH_SIZE, value);
+
+			// penalize for wasted bits
+			score -= value[0];
 
 			if (score > bestScore) {
 				best = i;
@@ -248,28 +273,35 @@ public class ScummVM implements SurfaceHolder.Callback {
 			Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e);
 			return;
 		}
+
 		eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
 												nativeSurface, null);
+
 		if (eglSurface == EGL10.EGL_NO_SURFACE)
 			Log.e(LOG_TAG, "CreateWindowSurface failed!");
+
 		egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
 
 		GL10 gl = (GL10)eglContext.getGL();
 
 		if (_log_version) {
 			Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
-										 egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
-										 egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
-										 gl.glGetString(GL10.GL_VERSION),
-										 gl.glGetString(GL10.GL_RENDERER),
-										 gl.glGetString(GL10.GL_VENDOR)));
-			_log_version = false; // only log this once
+											egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
+											egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
+											gl.glGetString(GL10.GL_VERSION),
+											gl.glGetString(GL10.GL_RENDERER),
+											gl.glGetString(GL10.GL_VENDOR)));
+
+			// only log this once
+			_log_version = false;
 		}
 
 		int[] value = new int[1];
 		egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value);
+
 		int width = value[0];
 		egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value);
+
 		int height = value[0];
 		Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height));
 		setSurfaceSize(width, height);
@@ -279,7 +311,8 @@ public class ScummVM implements SurfaceHolder.Callback {
 	protected void destroyScummVMSurface() {
 		if (eglSurface != null) {
 			egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
-							   EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+								EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+
 			egl.eglDestroySurface(eglDisplay, eglSurface);
 			eglSurface = EGL10.EGL_NO_SURFACE;
 		}
@@ -298,6 +331,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 			if (error == EGL11.EGL_CONTEXT_LOST)
 				return false;
 		}
+
 		return true;
 	}
 
@@ -324,6 +358,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 	protected void showVirtualKeyboard(boolean enable) {}
 	protected String[] getSysArchives() { return new String[0]; }
 	protected String[] getPluginDirectories() { return new String[0]; }
+
 	protected void initBackend() throws AudioSetupException {
 		createScummVMGLContext();
 		initAudio();
@@ -375,17 +410,19 @@ public class ScummVM implements SurfaceHolder.Callback {
 						scummvm.audioMixCallback(buf);
 						offset = 0;
 					}
+
 					int len = buf.length - offset;
 					int ret = audio_track.write(buf, offset, len);
 					if (ret < 0) {
 						Log.w(LOG_TAG, String.format(
-							"AudioTrack.write(%dB) returned error %d",
-							buf.length, ret));
+								"AudioTrack.write(%dB) returned error %d",
+								buf.length, ret));
 						break;
 					} else if (ret != len) {
 						Log.w(LOG_TAG, String.format(
-							"Short audio write.	 Wrote %dB, not %dB",
-							ret, buf.length));
+								"Short audio write.	 Wrote %dB, not %dB",
+								ret, buf.length));
+
 						// Buffer is full, so yield cpu for a while
 						Thread.sleep(100);
 					}
@@ -409,21 +446,27 @@ public class ScummVM implements SurfaceHolder.Callback {
 										AudioFormat.CHANNEL_CONFIGURATION_STEREO,
 										AudioFormat.ENCODING_PCM_16BIT);
 		if (buf_size < 0) {
-			int guess = AUDIO_FRAME_SIZE * sample_rate / 100;  // 10ms of audio
+			// 10ms of audio
+			int guess = AUDIO_FRAME_SIZE * sample_rate / 100;
+
 			Log.w(LOG_TAG, String.format(
 				"Unable to get min audio buffer size (error %d). Guessing %dB.",
 				buf_size, guess));
+
 			buf_size = guess;
 		}
+
 		Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",
-									 buf_size, sample_rate));
+										buf_size, sample_rate));
+
 		AudioTrack audio_track =
 			new AudioTrack(AudioManager.STREAM_MUSIC,
-						   sample_rate,
-						   AudioFormat.CHANNEL_CONFIGURATION_STEREO,
-						   AudioFormat.ENCODING_PCM_16BIT,
-						   buf_size,
-						   AudioTrack.MODE_STREAM);
+							sample_rate,
+							AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+							AudioFormat.ENCODING_PCM_16BIT,
+							buf_size,
+							AudioTrack.MODE_STREAM);
+
 		if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) {
 			Log.e(LOG_TAG, "Error initialising Android audio system.");
 			throw new AudioSetupException();
@@ -448,7 +491,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 		final boolean sleep_for_debugger = false;
 		if (sleep_for_debugger) {
 			try {
-				Thread.sleep(20*1000);
+				Thread.sleep(20 * 1000);
 			} catch (InterruptedException e) {
 			}
 		}
@@ -460,3 +503,4 @@ public class ScummVM implements SurfaceHolder.Callback {
 		System.load(libpath.getPath());
 	}
 }
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index 8929809..0dd1109 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -38,6 +38,7 @@ public class ScummVMActivity extends Activity {
 			// devices :(
 			DisplayMetrics metrics = new DisplayMetrics();
 			getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
 			try {
 				// This 'density' term is very confusing.
 				int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null);
@@ -63,6 +64,7 @@ public class ScummVMActivity extends Activity {
 				scummvmRunning = true;
 				notifyAll();
 			}
+
 			super.initBackend();
 		}
 
@@ -104,6 +106,7 @@ public class ScummVMActivity extends Activity {
 				});
 		}
 	}
+
 	private MyScummVM scummvm;
 	private Thread scummvm_thread;
 
@@ -125,18 +128,18 @@ public class ScummVMActivity extends Activity {
 				.setIcon(android.R.drawable.ic_dialog_alert)
 				.setMessage(R.string.no_sdcard)
 				.setNegativeButton(R.string.quit,
-								   new DialogInterface.OnClickListener() {
-									   public void onClick(DialogInterface dialog,
-														   int which) {
-										   finish();
-									   }
-								   })
+									new DialogInterface.OnClickListener() {
+										public void onClick(DialogInterface dialog,
+															int which) {
+											finish();
+										}
+									})
 				.show();
+
 			return;
 		}
 
 		SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
-		
 		main_surface.setOnTouchListener(new View.OnTouchListener() {
 				public boolean onTouch(View v, MotionEvent event) {
 					return onTouchEvent(event);
@@ -151,6 +154,7 @@ public class ScummVMActivity extends Activity {
 
 		// Start ScummVM
 		scummvm = new MyScummVM();
+
 		scummvm_thread = new Thread(new Runnable() {
 				public void run() {
 					try {
@@ -166,6 +170,7 @@ public class ScummVMActivity extends Activity {
 					}
 				}
 			}, "ScummVM");
+
 		scummvm_thread.start();
 
 		// Block UI thread until ScummVM has started.  In particular,
@@ -207,14 +212,17 @@ public class ScummVMActivity extends Activity {
 			was_paused = true;
 			scummvm.pause();
 		}
+
 		super.onPause();
 	}
 
 	@Override
 	public void onResume() {
 		super.onResume();
+
 		if (scummvm != null && was_paused)
 			scummvm.resume();
+
 		was_paused = false;
 	}
 
@@ -222,16 +230,20 @@ public class ScummVMActivity extends Activity {
 	public void onStop() {
 		if (scummvm != null) {
 			scummvm.pushEvent(new Event(Event.EVENT_QUIT));
+
 			try {
-				scummvm_thread.join(1000);	// 1s timeout
+				// 1s timeout
+				scummvm_thread.join(1000);
 			} catch (InterruptedException e) {
 				Log.i(ScummVM.LOG_TAG, "Error while joining ScummVM thread", e);
 			}
 		}
+
 		super.onStop();
 	}
 
 	static final int MSG_MENU_LONG_PRESS = 1;
+
 	private final Handler keycodeMenuTimeoutHandler = new Handler() {
 			@Override
 			public void handleMessage(Message msg) {
@@ -251,7 +263,7 @@ public class ScummVMActivity extends Activity {
 
 	@Override
 	public boolean onKeyMultiple(int keyCode, int repeatCount,
-									 KeyEvent kevent) {
+									KeyEvent kevent) {
 		return onKeyDown(keyCode, kevent);
 	}
 
@@ -261,12 +273,12 @@ public class ScummVMActivity extends Activity {
 		switch (keyCode) {
 		case KeyEvent.KEYCODE_MENU:
 			// Have to reimplement hold-down-menu-brings-up-softkeybd
-			// ourselves, since we are otherwise hijacking the menu
-			// key :(
+			// ourselves, since we are otherwise hijacking the menu key :(
 			// See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
 			// for the usual Android implementation of this feature.
+
+			// Ignore keyrepeat for menu
 			if (kevent.getRepeatCount() > 0)
-				// Ignore keyrepeat for menu
 				return false;
 
 			boolean timeout_fired = !keycodeMenuTimeoutHandler.hasMessages(MSG_MENU_LONG_PRESS);
@@ -274,20 +286,24 @@ public class ScummVMActivity extends Activity {
 
 			if (kevent.getAction() == KeyEvent.ACTION_DOWN) {
 				keycodeMenuTimeoutHandler.sendMessageDelayed(keycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
-															 ViewConfiguration.getLongPressTimeout());
+																ViewConfiguration.getLongPressTimeout());
 				return true;
 			}
 
 			if (kevent.getAction() == KeyEvent.ACTION_UP) {
 				if (!timeout_fired)
 					scummvm.pushEvent(new Event(Event.EVENT_MAINMENU));
+
 				return true;
 			}
+
 			return false;
+
 		case KeyEvent.KEYCODE_CAMERA:
 		case KeyEvent.KEYCODE_SEARCH:
 			_do_right_click = (kevent.getAction() == KeyEvent.ACTION_DOWN);
 			return true;
+
 		case KeyEvent.KEYCODE_DPAD_CENTER:
 		case KeyEvent.KEYCODE_DPAD_UP:
 		case KeyEvent.KEYCODE_DPAD_DOWN:
@@ -299,45 +315,59 @@ public class ScummVMActivity extends Activity {
 			// Some other handsets lack a trackball, so the DPAD is
 			// the only way of moving the cursor.
 			int motion_action;
+
 			// FIXME: this logic is a mess.
 			if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
 				switch (kevent.getAction()) {
 				case KeyEvent.ACTION_DOWN:
 					motion_action = MotionEvent.ACTION_DOWN;
 					break;
+
 				case KeyEvent.ACTION_UP:
 					motion_action = MotionEvent.ACTION_UP;
 					break;
-				default:  // ACTION_MULTIPLE
+
+				// ACTION_MULTIPLE
+				default:
 					return false;
 				}
-			} else
+			} else {
 				motion_action = MotionEvent.ACTION_MOVE;
+			}
 
 			Event e = new Event(getEventType(motion_action));
+
 			e.mouse_x = 0;
 			e.mouse_y = 0;
 			e.mouse_relative = true;
+
 			switch (keyCode) {
 			case KeyEvent.KEYCODE_DPAD_UP:
 				e.mouse_y = -TRACKBALL_SCALE;
 				break;
+
 			case KeyEvent.KEYCODE_DPAD_DOWN:
 				e.mouse_y = TRACKBALL_SCALE;
 				break;
+
 			case KeyEvent.KEYCODE_DPAD_LEFT:
 				e.mouse_x = -TRACKBALL_SCALE;
 				break;
+
 			case KeyEvent.KEYCODE_DPAD_RIGHT:
 				e.mouse_x = TRACKBALL_SCALE;
 				break;
 			}
+
 			scummvm.pushEvent(e);
+
 			return true;
 		}
+
 		case KeyEvent.KEYCODE_BACK:
 			// skip isSystem() check and fall through to main code
 			break;
+
 		default:
 			if (kevent.isSystem())
 				return false;
@@ -352,51 +382,63 @@ public class ScummVMActivity extends Activity {
 			e.type = Event.EVENT_KEYDOWN;
 			e.synthetic = false;
 			break;
+
 		case KeyEvent.ACTION_UP:
 			e.type = Event.EVENT_KEYUP;
 			e.synthetic = false;
 			break;
+
 		case KeyEvent.ACTION_MULTIPLE:
 			// e.type is handled below
 			e.synthetic = true;
 			break;
+
 		default:
 			return false;
 		}
 
 		e.kbd_keycode = Event.androidKeyMap.containsKey(keyCode) ?
 			Event.androidKeyMap.get(keyCode) : Event.KEYCODE_INVALID;
+
 		e.kbd_ascii = kevent.getUnicodeChar();
+
 		if (e.kbd_ascii == 0)
 			e.kbd_ascii = e.kbd_keycode; // scummvm keycodes are mostly ascii
 
-
 		e.kbd_flags = 0;
+
 		if (kevent.isAltPressed())
 			e.kbd_flags |= Event.KBD_ALT;
-		if (kevent.isSymPressed()) // no ctrl key in android, so use sym (?)
+
+		// no ctrl key in android, so use sym (?)
+		if (kevent.isSymPressed())
 			e.kbd_flags |= Event.KBD_CTRL;
+
 		if (kevent.isShiftPressed()) {
 			if (keyCode >= KeyEvent.KEYCODE_0 &&
-				keyCode <= KeyEvent.KEYCODE_9) {
+					keyCode <= KeyEvent.KEYCODE_9) {
 				// Shift+number -> convert to F* key
 				int offset = keyCode == KeyEvent.KEYCODE_0 ?
 					10 : keyCode - KeyEvent.KEYCODE_1; // turn 0 into 10
+
 				e.kbd_keycode = Event.KEYCODE_F1 + offset;
 				e.kbd_ascii = Event.ASCII_F1 + offset;
-			} else
+			} else {
 				e.kbd_flags |= Event.KBD_SHIFT;
+			}
 		}
 
 		if (kevent.getAction() == KeyEvent.ACTION_MULTIPLE) {
 			for (int i = 0; i <= kevent.getRepeatCount(); i++) {
 				e.type = Event.EVENT_KEYDOWN;
 				scummvm.pushEvent(e);
+
 				e.type = Event.EVENT_KEYUP;
 				scummvm.pushEvent(e);
 			}
-		} else
+		} else {
 			scummvm.pushEvent(e);
+		}
 
 		return true;
 	}
@@ -407,11 +449,14 @@ public class ScummVMActivity extends Activity {
 			_last_click_was_right = _do_right_click;
 			return _last_click_was_right ?
 				Event.EVENT_RBUTTONDOWN : Event.EVENT_LBUTTONDOWN;
+
 		case MotionEvent.ACTION_UP:
 			return _last_click_was_right ?
 				Event.EVENT_RBUTTONUP : Event.EVENT_LBUTTONUP;
+
 		case MotionEvent.ACTION_MOVE:
 			return Event.EVENT_MOUSEMOVE;
+
 		default:
 			return Event.EVENT_INVALID;
 		}
@@ -429,6 +474,7 @@ public class ScummVMActivity extends Activity {
 		e.mouse_y =
 			(int)(event.getY() * event.getYPrecision()) * TRACKBALL_SCALE;
 		e.mouse_relative = true;
+
 		scummvm.pushEvent(e);
 
 		return true;
@@ -437,6 +483,7 @@ public class ScummVMActivity extends Activity {
 	@Override
 	public boolean onTouchEvent(MotionEvent event) {
 		int type = getEventType(event.getAction());
+
 		if (type == Event.EVENT_INVALID)
 			return false;
 
@@ -444,6 +491,7 @@ public class ScummVMActivity extends Activity {
 		e.mouse_x = (int)event.getX();
 		e.mouse_y = (int)event.getY();
 		e.mouse_relative = false;
+
 		scummvm.pushEvent(e);
 
 		return true;
@@ -453,6 +501,7 @@ public class ScummVMActivity extends Activity {
 		SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
 		InputMethodManager imm = (InputMethodManager)
 			getSystemService(INPUT_METHOD_SERVICE);
+
 		if (show)
 			imm.showSoftInput(main_surface, InputMethodManager.SHOW_IMPLICIT);
 		else
@@ -460,3 +509,4 @@ public class ScummVMActivity extends Activity {
 										InputMethodManager.HIDE_IMPLICIT_ONLY);
 	}
 }
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
index 37a9d09..80735e2 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
@@ -13,11 +13,12 @@ public class ScummVMApplication extends Application {
 	@Override
 	public void onCreate() {
 		super.onCreate();
+
 		// This is still on /data :(
 		cache_dir = getCacheDir();
 		// This is mounted noexec :(
 		//cache_dir = new File(Environment.getExternalStorageDirectory(),
-		//			 "/.ScummVM.tmp");
+		//				"/.ScummVM.tmp");
 		// This is owned by download manager and requires special
 		// permissions to access :(
 		//cache_dir = Environment.getDownloadCacheDirectory();
@@ -27,3 +28,4 @@ public class ScummVMApplication extends Application {
 		return cache_dir;
 	}
 }
+


Commit: 25d895b859af0df8ea6daa85ba6ec5a0acb81f9d
    https://github.com/scummvm/scummvm/commit/25d895b859af0df8ea6daa85ba6ec5a0acb81f9d
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:36-08:00

Commit Message:
ANDROID: Rework audio system

Move the audio thread to the bright side

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h
    backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
    backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 4968e4b..08b9579 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -26,6 +26,7 @@
 #if defined(__ANDROID__)
 
 #include <sys/time.h>
+#include <sys/resource.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -98,7 +99,9 @@ static inline T scalef(T in, float numerator, float denominator) {
 	return static_cast<float>(in) * numerator / denominator;
 }
 
-OSystem_Android::OSystem_Android() :
+OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
+	_audio_sample_rate(audio_sample_rate),
+	_audio_buffer_size(audio_buffer_size),
 	_screen_changeid(0),
 	_force_redraw(false),
 	_game_texture(0),
@@ -137,6 +140,10 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 	OSystem_Android *system = (OSystem_Android *)arg;
 	DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
 
+	// renice this thread to boost the audio thread
+	if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+		warning("couldn't renice the timer thread");
+
 	JNI::attachThread();
 
 	struct timespec tv;
@@ -153,6 +160,72 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 	return 0;
 }
 
+void *OSystem_Android::audioThreadFunc(void *arg) {
+	JNI::attachThread();
+
+	JNI::setAudioPlay();
+
+	OSystem_Android *system = (OSystem_Android *)arg;
+	Audio::MixerImpl *mixer = system->_mixer;
+
+	uint buf_size = system->_audio_buffer_size;
+
+	JNIEnv *env = JNI::getEnv();
+
+	jbyteArray bufa = env->NewByteArray(buf_size);
+
+	byte *buf;
+	int offset, left, written;
+
+	struct timespec tv;
+	tv.tv_sec = 0;
+	tv.tv_nsec = 20 * 1000 * 1000;
+
+	while (!system->_audio_thread_exit) {
+		buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0);
+		assert(buf);
+
+		mixer->mixCallback(buf, buf_size);
+
+		env->ReleasePrimitiveArrayCritical(bufa, buf, 0);
+
+		offset = 0;
+		left = buf_size;
+		written = 0;
+
+		while (left > 0) {
+			written = JNI::writeAudio(env, bufa, offset, left);
+
+			if (written < 0) {
+				error("AudioTrack error: %d", written);
+				break;
+			}
+
+			// buffer full
+			if (written < left)
+				nanosleep(&tv, 0);
+
+			offset += written;
+			left -= written;
+		}
+
+		if (written < 0)
+			break;
+
+		// sleep a little, prepare the next buffer, and run into the
+		// blocking AudioTrack.write
+		nanosleep(&tv, 0);
+	}
+
+	JNI::setAudioStop();
+
+	env->DeleteLocalRef(bufa);
+
+	JNI::detachThread();
+
+	return 0;
+}
+
 void OSystem_Android::initBackend() {
 	ENTER();
 
@@ -173,7 +246,7 @@ void OSystem_Android::initBackend() {
 
 	gettimeofday(&_startTime, 0);
 
-	_mixer = new Audio::MixerImpl(this, JNI::getAudioSampleRate());
+	_mixer = new Audio::MixerImpl(this, _audio_sample_rate);
 	_mixer->setReady(true);
 
 	JNI::initBackend();
@@ -181,9 +254,16 @@ void OSystem_Android::initBackend() {
 	_timer_thread_exit = false;
 	pthread_create(&_timer_thread, 0, timerThreadFunc, this);
 
+	_audio_thread_exit = false;
+	pthread_create(&_audio_thread, 0, audioThreadFunc, this);
+
 	OSystem::initBackend();
 
 	setupSurface();
+
+	// renice this thread to boost the audio thread
+	if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+		warning("couldn't renice the main thread");
 }
 
 void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
@@ -391,6 +471,9 @@ void OSystem_Android::deleteMutex(MutexRef mutex) {
 void OSystem_Android::quit() {
 	ENTER();
 
+	_audio_thread_exit = true;
+	pthread_join(_audio_thread, 0);
+
 	_timer_thread_exit = true;
 	pthread_join(_timer_thread, 0);
 }
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 23c1e85..f4e9d61 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -92,6 +92,10 @@ protected:
 
 class OSystem_Android : public BaseBackend, public PaletteManager {
 private:
+	// passed from the dark side
+	int _audio_sample_rate;
+	int _audio_buffer_size;
+
 	int _screen_changeid;
 	int _egl_surface_width;
 	int _egl_surface_height;
@@ -123,6 +127,10 @@ private:
 	pthread_t _timer_thread;
 	static void *timerThreadFunc(void *arg);
 
+	bool _audio_thread_exit;
+	pthread_t _audio_thread;
+	static void *audioThreadFunc(void *arg);
+
 	bool _enable_zoning;
 	bool _virtkeybd_on;
 
@@ -137,7 +145,7 @@ private:
 	void _setCursorPalette(const byte *colors, uint start, uint num);
 
 public:
-	OSystem_Android();
+	OSystem_Android(int audio_sample_rate, int audio_buffer_size);
 	virtual ~OSystem_Android();
 
 	virtual void initBackend();
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index f24a60d..5e11203 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -39,6 +39,7 @@ jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
 
 JavaVM *JNI::_vm = 0;
 jobject JNI::_jobj = 0;
+jobject JNI::_jobj_audio_track = 0;
 
 Common::Archive *JNI::_asset_archive = 0;
 OSystem_Android *JNI::_system = 0;
@@ -56,7 +57,6 @@ jfieldID JNI::_FID_ScummVM_nativeScummVM = 0;
 jmethodID JNI::_MID_displayMessageOnOSD = 0;
 jmethodID JNI::_MID_setWindowCaption = 0;
 jmethodID JNI::_MID_initBackend = 0;
-jmethodID JNI::_MID_audioSampleRate = 0;
 jmethodID JNI::_MID_showVirtualKeyboard = 0;
 jmethodID JNI::_MID_getSysArchives = 0;
 jmethodID JNI::_MID_getPluginDirectories = 0;
@@ -64,8 +64,14 @@ jmethodID JNI::_MID_setupScummVMSurface = 0;
 jmethodID JNI::_MID_destroyScummVMSurface = 0;
 jmethodID JNI::_MID_swapBuffers = 0;
 
+jmethodID JNI::_MID_AudioTrack_pause = 0;
+jmethodID JNI::_MID_AudioTrack_play = 0;
+jmethodID JNI::_MID_AudioTrack_stop = 0;
+jmethodID JNI::_MID_AudioTrack_write = 0;
+
 const JNINativeMethod JNI::_natives[] = {
-	{ "create", "(Landroid/content/res/AssetManager;)V",
+	{ "create", "(Landroid/content/res/AssetManager;"
+				"Landroid/media/AudioTrack;II)V",
 		(void *)JNI::create },
 	{ "nativeDestroy", "()V",
 		(void *)JNI::destroy },
@@ -73,8 +79,6 @@ const JNINativeMethod JNI::_natives[] = {
 	 	(void *)JNI::main },
 	{ "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
 		(void *)JNI::pushEvent },
-	{ "audioMixCallback", "([B)V",
-		(void *)JNI::audioMixCallback },
 	{ "setConfMan", "(Ljava/lang/String;I)V",
 		(void *)JNI::setConfManInt },
 	{ "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
@@ -194,23 +198,6 @@ void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
 
 // calls to the dark side
 
-int JNI::getAudioSampleRate() {
-	JNIEnv *env = JNI::getEnv();
-
-	jint sample_rate = env->CallIntMethod(_jobj, _MID_audioSampleRate);
-
-	if (env->ExceptionCheck()) {
-		warning("Error finding audio sample rate - assuming 11025HZ");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-
-		return 11025;
-	}
-
-	return sample_rate;
-}
-
 void JNI::initBackend() {
 	JNIEnv *env = JNI::getEnv();
 
@@ -342,15 +329,55 @@ void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
 	}
 }
 
+void JNI::setAudioPause() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause);
+
+	if (env->ExceptionCheck()) {
+		warning("Error setting AudioTrack: pause");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+}
+
+void JNI::setAudioPlay() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_play);
+
+	if (env->ExceptionCheck()) {
+		warning("Error setting AudioTrack: play");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+}
+
+void JNI::setAudioStop() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_stop);
+
+	if (env->ExceptionCheck()) {
+		warning("Error setting AudioTrack: stop");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+}
+
 // natives for the dark side
 
-void JNI::create(JNIEnv *env, jobject self, jobject am) {
+void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
+					jint audio_sample_rate, jint audio_buffer_size) {
 	assert(!_system);
 
 	_asset_archive = new AndroidAssetArchive(am);
 	assert(_asset_archive);
 
-	_system = new OSystem_Android();
+	_system = new OSystem_Android(audio_sample_rate, audio_buffer_size);
 	assert(_system);
 
 	// weak global ref to allow class to be unloaded
@@ -369,7 +396,6 @@ void JNI::create(JNIEnv *env, jobject self, jobject am) {
 	FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
 	FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
 	FIND_METHOD(initBackend, "()V");
-	FIND_METHOD(audioSampleRate, "()I");
 	FIND_METHOD(showVirtualKeyboard, "(Z)V");
 	FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
 	FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
@@ -381,6 +407,23 @@ void JNI::create(JNIEnv *env, jobject self, jobject am) {
 
 	env->SetLongField(self, _FID_ScummVM_nativeScummVM, (jlong)_system);
 
+	_jobj_audio_track = env->NewGlobalRef(at);
+
+	cls = env->GetObjectClass(_jobj_audio_track);
+
+#define FIND_METHOD(name, signature) do {									\
+		_MID_AudioTrack_ ## name = env->GetMethodID(cls, #name, signature);	\
+		if (_MID_AudioTrack_ ## name == 0)									\
+			return;															\
+	} while (0)
+
+	FIND_METHOD(pause, "()V");
+	FIND_METHOD(play, "()V");
+	FIND_METHOD(stop, "()V");
+	FIND_METHOD(write, "([BII)I");
+
+#undef FIND_METHOD
+
 	g_system = _system;
 }
 
@@ -397,6 +440,7 @@ void JNI::destroy(JNIEnv *env, jobject self) {
 
 	// see above
 	//JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
+	JNI::getEnv()->DeleteGlobalRef(_jobj_audio_track);
 	JNI::getEnv()->DeleteGlobalRef(_jobj);
 }
 
@@ -514,25 +558,6 @@ void JNI::pushEvent(JNIEnv *env, jobject self, jobject java_event) {
 	_system->pushEvent(event);
 }
 
-void JNI::audioMixCallback(JNIEnv *env, jobject self, jbyteArray jbuf) {
-	assert(_system);
-
-	jsize len = env->GetArrayLength(jbuf);
-	jbyte *buf = env->GetByteArrayElements(jbuf, 0);
-
-	if (buf == 0) {
-		warning("Unable to get Java audio byte array. Skipping");
-		return;
-	}
-
-	Audio::MixerImpl *mixer =
-		static_cast<Audio::MixerImpl *>(_system->getMixer());
-	assert(mixer);
-	mixer->mixCallback(reinterpret_cast<byte *>(buf), len);
-
-	env->ReleaseByteArrayElements(jbuf, buf, 0);
-}
-
 void JNI::setConfManInt(JNIEnv *env, jclass cls, jstring key_obj, jint value) {
 	ENTER("%p, %d", key_obj, (int)value);
 
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index 02eabba..a1fc3df 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -48,7 +48,6 @@ public:
 	static void attachThread();
 	static void detachThread();
 
-	static int getAudioSampleRate();
 	static void initBackend();
 	static void getPluginDirectories(Common::FSList &dirs);
 	static void setWindowCaption(const char *caption);
@@ -60,10 +59,18 @@ public:
 	static inline void destroySurface();
 	static inline bool swapBuffers();
 
+	static void setAudioPause();
+	static void setAudioPlay();
+	static void setAudioStop();
+
+	static inline int writeAudio(JNIEnv *env, jbyteArray &data, int offset,
+									int size);
+
 private:
 	static JavaVM *_vm;
 	// back pointer to (java) peer instance
 	static jobject _jobj;
+	static jobject _jobj_audio_track;
 
 	static Common::Archive *_asset_archive;
 	static OSystem_Android *_system;
@@ -81,7 +88,6 @@ private:
 	static jmethodID _MID_displayMessageOnOSD;
 	static jmethodID _MID_setWindowCaption;
 	static jmethodID _MID_initBackend;
-	static jmethodID _MID_audioSampleRate;
 	static jmethodID _MID_showVirtualKeyboard;
 	static jmethodID _MID_getSysArchives;
 	static jmethodID _MID_getPluginDirectories;
@@ -89,16 +95,21 @@ private:
 	static jmethodID _MID_destroyScummVMSurface;
 	static jmethodID _MID_swapBuffers;
 
+	static jmethodID _MID_AudioTrack_pause;
+	static jmethodID _MID_AudioTrack_play;
+	static jmethodID _MID_AudioTrack_stop;
+	static jmethodID _MID_AudioTrack_write;
+
 	static const JNINativeMethod _natives[];
 
 	static void throwByName(JNIEnv *env, const char *name, const char *msg);
 
 	// natives for the dark side
-	static void create(JNIEnv *env, jobject self, jobject am);
+	static void create(JNIEnv *env, jobject self, jobject am, jobject at,
+						jint sample_rate, jint buffer_size);
 	static void destroy(JNIEnv *env, jobject self);
 	static jint main(JNIEnv *env, jobject self, jobjectArray args);
 	static void pushEvent(JNIEnv *env, jobject self, jobject java_event);
-	static void audioMixCallback(JNIEnv *env, jobject self, jbyteArray jbuf);
 	static void setConfManInt(JNIEnv *env, jclass cls, jstring key_obj,
 								jint value);
 	static void setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
@@ -128,6 +139,10 @@ inline bool JNI::swapBuffers() {
 	return env->CallBooleanMethod(_jobj, _MID_swapBuffers);
 }
 
+inline int JNI::writeAudio(JNIEnv *env, jbyteArray &data, int offset, int size) {
+	return env->CallIntMethod(_jobj_audio_track, _MID_AudioTrack_write, data, offset, size);
+}
+
 #endif
 #endif
 
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index 698e508..7a32645 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -35,19 +35,48 @@ import java.util.LinkedHashMap;
 public class ScummVM implements SurfaceHolder.Callback {
 	protected final static String LOG_TAG = "ScummVM";
 
-	// bytes. 16bit audio * stereo
-	private final int AUDIO_FRAME_SIZE = 2 * 2;
-	public static class AudioSetupException extends Exception {}
-
 	// native code hangs itself here
 	private long nativeScummVM;
 	boolean scummVMRunning = false;
 
-	private native void create(AssetManager am);
+	private native void create(AssetManager am, AudioTrack audio_track,
+								int sample_rate, int buffer_size);
+
+	public ScummVM(Context context) throws Exception {
+		int sample_rate = AudioTrack.getNativeOutputSampleRate(
+							AudioManager.STREAM_MUSIC);
+		int buffer_size = AudioTrack.getMinBufferSize(sample_rate,
+							AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+							AudioFormat.ENCODING_PCM_16BIT);
+
+		// ~100ms
+		int buffer_size_want = (sample_rate * 2 * 2 / 10) & ~1023;
+
+		if (buffer_size < buffer_size_want) {
+			Log.w(LOG_TAG, String.format(
+				"adjusting audio buffer size (was: %d)", buffer_size));
+
+			buffer_size = buffer_size_want;
+		}
+
+		Log.i(LOG_TAG, String.format("Using %d bytes buffer for %dHz audio",
+										buffer_size, sample_rate));
+
+		AudioTrack audio_track =
+			new AudioTrack(AudioManager.STREAM_MUSIC,
+							sample_rate,
+							AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+							AudioFormat.ENCODING_PCM_16BIT,
+							buffer_size,
+							AudioTrack.MODE_STREAM);
+
+		if (audio_track.getState() != AudioTrack.STATE_INITIALIZED)
+			throw new Exception(
+				String.format("Error initialising AudioTrack: %d",
+								audio_track.getState()));
 
-	public ScummVM(Context context) {
 		// Init C++ code, set nativeScummVM
-		create(context.getAssets());
+		create(context.getAssets(), audio_track, sample_rate, buffer_size);
 	}
 
 	private native void nativeDestroy();
@@ -345,8 +374,6 @@ public class ScummVM implements SurfaceHolder.Callback {
 	// Feed an event to ScummVM.  Safe to call from other threads.
 	final public native void pushEvent(Event e);
 
-	final private native void audioMixCallback(byte[] buf);
-
 	// Runs the actual ScummVM program and returns when it does.
 	// This should not be called from multiple threads simultaneously...
 	final public native int scummVMMain(String[] argv);
@@ -359,131 +386,18 @@ public class ScummVM implements SurfaceHolder.Callback {
 	protected String[] getSysArchives() { return new String[0]; }
 	protected String[] getPluginDirectories() { return new String[0]; }
 
-	protected void initBackend() throws AudioSetupException {
+	protected void initBackend() {
 		createScummVMGLContext();
-		initAudio();
-	}
-
-	private static class AudioThread extends Thread {
-		final private int buf_size;
-		private boolean is_paused = false;
-		final private ScummVM scummvm;
-		final private AudioTrack audio_track;
-
-		AudioThread(ScummVM scummvm, AudioTrack audio_track, int buf_size) {
-			super("AudioThread");
-			this.scummvm = scummvm;
-			this.audio_track = audio_track;
-			this.buf_size = buf_size;
-			setPriority(Thread.MAX_PRIORITY);
-			setDaemon(true);
-		}
-
-		public void pauseAudio() {
-			synchronized (this) {
-				is_paused = true;
-			}
-			audio_track.pause();
-		}
-
-		public void resumeAudio() {
-			synchronized (this) {
-				is_paused = false;
-				notifyAll();
-			}
-			audio_track.play();
-		}
-
-		public void run() {
-			byte[] buf = new byte[buf_size];
-			audio_track.play();
-			int offset = 0;
-			try {
-				while (true) {
-					synchronized (this) {
-						while (is_paused)
-							wait();
-					}
-
-					if (offset == buf.length) {
-						// Grab new audio data
-						scummvm.audioMixCallback(buf);
-						offset = 0;
-					}
-
-					int len = buf.length - offset;
-					int ret = audio_track.write(buf, offset, len);
-					if (ret < 0) {
-						Log.w(LOG_TAG, String.format(
-								"AudioTrack.write(%dB) returned error %d",
-								buf.length, ret));
-						break;
-					} else if (ret != len) {
-						Log.w(LOG_TAG, String.format(
-								"Short audio write.	 Wrote %dB, not %dB",
-								ret, buf.length));
-
-						// Buffer is full, so yield cpu for a while
-						Thread.sleep(100);
-					}
-					offset += ret;
-				}
-			} catch (InterruptedException e) {
-				Log.e(LOG_TAG, "Audio thread interrupted", e);
-			}
-		}
-	}
-	private AudioThread audio_thread;
-
-	final public int audioSampleRate() {
-		return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
-	}
-
-	private void initAudio() throws AudioSetupException {
-		int sample_rate = audioSampleRate();
-		int buf_size =
-			AudioTrack.getMinBufferSize(sample_rate,
-										AudioFormat.CHANNEL_CONFIGURATION_STEREO,
-										AudioFormat.ENCODING_PCM_16BIT);
-		if (buf_size < 0) {
-			// 10ms of audio
-			int guess = AUDIO_FRAME_SIZE * sample_rate / 100;
-
-			Log.w(LOG_TAG, String.format(
-				"Unable to get min audio buffer size (error %d). Guessing %dB.",
-				buf_size, guess));
-
-			buf_size = guess;
-		}
-
-		Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",
-										buf_size, sample_rate));
-
-		AudioTrack audio_track =
-			new AudioTrack(AudioManager.STREAM_MUSIC,
-							sample_rate,
-							AudioFormat.CHANNEL_CONFIGURATION_STEREO,
-							AudioFormat.ENCODING_PCM_16BIT,
-							buf_size,
-							AudioTrack.MODE_STREAM);
-
-		if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) {
-			Log.e(LOG_TAG, "Error initialising Android audio system.");
-			throw new AudioSetupException();
-		}
-
-		audio_thread = new AudioThread(this, audio_track, buf_size);
-		audio_thread.start();
 	}
 
 	public void pause() {
-		audio_thread.pauseAudio();
-		// TODO: need to pause engine too
+		// TODO: need to pause audio
+		// TODO: need to pause engine
 	}
 
 	public void resume() {
-		// TODO: need to resume engine too
-		audio_thread.resumeAudio();
+		// TODO: need to resume audio
+		// TODO: need to resume engine
 	}
 
 	static {
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index 0dd1109..fb6020c 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -49,7 +49,7 @@ public class ScummVMActivity extends Activity {
 			}
 		}
 
-		public MyScummVM() {
+		public MyScummVM() throws Exception {
 			super(ScummVMActivity.this);
 
 			// Enable ScummVM zoning on 'small' screens.
@@ -59,7 +59,7 @@ public class ScummVMActivity extends Activity {
 		}
 
 		@Override
-		protected void initBackend() throws ScummVM.AudioSetupException {
+		protected void initBackend() {
 			synchronized (this) {
 				scummvmRunning = true;
 				notifyAll();
@@ -153,7 +153,13 @@ public class ScummVMActivity extends Activity {
 		main_surface.requestFocus();
 
 		// Start ScummVM
-		scummvm = new MyScummVM();
+		try {
+			scummvm = new MyScummVM();
+		} catch (Exception e) {
+			Log.e(ScummVM.LOG_TAG, "Fatal error", e);
+			finish();
+			return;
+		}
 
 		scummvm_thread = new Thread(new Runnable() {
 				public void run() {


Commit: bea57f695064c6f084ff26405d91b812848fee33
    https://github.com/scummvm/scummvm/commit/bea57f695064c6f084ff26405d91b812848fee33
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:36-08:00

Commit Message:
AUDIO: Make mixCallback return the sample count

The RateConverter::flow result was never used, pipe it through
Channel::mix to MixerImpl::mixCallback, so backends can decide
if they want to waste cpu cycles while playing empty buffers.

Changed paths:
    audio/mixer.cpp
    audio/mixer_intern.h



diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index c2271b1..dc0287e 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -54,8 +54,9 @@ public:
 	 * @param len  number of sample *pairs*. So a value of
 	 *             10 means that the buffer contains twice 10 sample, each
 	 *             16 bits, for a total of 40 bytes.
+	 * @return number of sample pairs processed (which can still be silence!)
 	 */
-	void mix(int16 *data, uint len);
+	int mix(int16 *data, uint len);
 
 	/**
 	 * Queries whether the channel is still playing or not.
@@ -257,7 +258,7 @@ void MixerImpl::playStream(
 	insertChannel(handle, chan);
 }
 
-void MixerImpl::mixCallback(byte *samples, uint len) {
+int MixerImpl::mixCallback(byte *samples, uint len) {
 	assert(samples);
 
 	Common::StackLock lock(_mutex);
@@ -272,14 +273,21 @@ void MixerImpl::mixCallback(byte *samples, uint len) {
 	memset(buf, 0, 2 * len * sizeof(int16));
 
 	// mix all channels
+	int res = 0, tmp;
 	for (int i = 0; i != NUM_CHANNELS; i++)
 		if (_channels[i]) {
 			if (_channels[i]->isFinished()) {
 				delete _channels[i];
 				_channels[i] = 0;
-			} else if (!_channels[i]->isPaused())
-				_channels[i]->mix(buf, len);
+			} else if (!_channels[i]->isPaused()) {
+				tmp = _channels[i]->mix(buf, len);
+
+				if (tmp > res)
+					res = tmp;
+			}
 		}
+
+	return res;
 }
 
 void MixerImpl::stopAll() {
@@ -538,19 +546,23 @@ Timestamp Channel::getElapsedTime() {
 	return ts;
 }
 
-void Channel::mix(int16 *data, uint len) {
+int Channel::mix(int16 *data, uint len) {
 	assert(_stream);
 
+	int res = 0;
+
 	if (_stream->endOfData()) {
 		// TODO: call drain method
 	} else {
 		assert(_converter);
-
 		_samplesConsumed = _samplesDecoded;
 		_mixerTimeStamp = g_system->getMillis();
 		_pauseTime = 0;
-		_samplesDecoded += _converter->flow(*_stream, data, len, _volL, _volR);
+		res = _converter->flow(*_stream, data, len, _volL, _volR);
+		_samplesDecoded += res;
 	}
+
+	return res;
 }
 
 } // End of namespace Audio
diff --git a/audio/mixer_intern.h b/audio/mixer_intern.h
index c8df9a5..dd2746e 100644
--- a/audio/mixer_intern.h
+++ b/audio/mixer_intern.h
@@ -118,8 +118,10 @@ public:
 	 * The mixer callback function, to be called at regular intervals by
 	 * the backend (e.g. from an audio mixing thread). All the actual mixing
 	 * work is done from here.
+	 *
+	 * @return number of sample pairs processed (which can still be silence!)
 	 */
-	void mixCallback(byte *samples, uint len);
+	int mixCallback(byte *samples, uint len);
 
 	/**
 	 * Set the internal 'is ready' flag of the mixer.


Commit: 0e869a5cf0e455f7cd5ce5c39192f3433b931e97
    https://github.com/scummvm/scummvm/commit/0e869a5cf0e455f7cd5ce5c39192f3433b931e97
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:37-08:00

Commit Message:
ANDROID: Pause the AudioTrack when possible

Only works in situations without any registered channels (or all paused)
at the mixer (like on the launcher or GMM).

CPU usage before (Galaxy Tab):
~5% scummvm
~15% mediaserver

After:
~2% scummvm
0% mediaserver

;)

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 08b9579..860ff1f 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -163,8 +163,6 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 void *OSystem_Android::audioThreadFunc(void *arg) {
 	JNI::attachThread();
 
-	JNI::setAudioPlay();
-
 	OSystem_Android *system = (OSystem_Android *)arg;
 	Audio::MixerImpl *mixer = system->_mixer;
 
@@ -174,21 +172,60 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 
 	jbyteArray bufa = env->NewByteArray(buf_size);
 
+	bool paused = true;
+
 	byte *buf;
 	int offset, left, written;
+	int samples;
 
-	struct timespec tv;
-	tv.tv_sec = 0;
-	tv.tv_nsec = 20 * 1000 * 1000;
+	struct timespec tv_delay;
+	tv_delay.tv_sec = 0;
+	tv_delay.tv_nsec = 20 * 1000 * 1000;
+
+	uint msecs_full = buf_size * 1000 / (mixer->getOutputRate() * 2 * 2);
+
+	struct timespec tv_full;
+	tv_full.tv_sec = 0;
+	tv_full.tv_nsec = msecs_full * 1000 * 1000;
+
+	uint silence_count = 0;
 
 	while (!system->_audio_thread_exit) {
 		buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0);
 		assert(buf);
 
-		mixer->mixCallback(buf, buf_size);
+		samples = mixer->mixCallback(buf, buf_size);
 
 		env->ReleasePrimitiveArrayCritical(bufa, buf, 0);
 
+		if (samples < 1) {
+			if (!paused)
+				silence_count++;
+
+			// only pause after a while to prevent toggle mania
+			if (silence_count > 32) {
+				if (!paused) {
+					LOGD("AudioTrack pause");
+
+					JNI::setAudioPause();
+					paused = true;
+				}
+
+				nanosleep(&tv_full, 0);
+
+				continue;
+			}
+		}
+
+		if (paused) {
+			LOGD("AudioTrack play");
+
+			JNI::setAudioPlay();
+			paused = false;
+
+			silence_count = 0;
+		}
+
 		offset = 0;
 		left = buf_size;
 		written = 0;
@@ -203,7 +240,7 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 
 			// buffer full
 			if (written < left)
-				nanosleep(&tv, 0);
+				nanosleep(&tv_delay, 0);
 
 			offset += written;
 			left -= written;
@@ -214,7 +251,7 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 
 		// sleep a little, prepare the next buffer, and run into the
 		// blocking AudioTrack.write
-		nanosleep(&tv, 0);
+		nanosleep(&tv_delay, 0);
 	}
 
 	JNI::setAudioStop();
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 5e11203..8964fe6 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -64,6 +64,7 @@ jmethodID JNI::_MID_setupScummVMSurface = 0;
 jmethodID JNI::_MID_destroyScummVMSurface = 0;
 jmethodID JNI::_MID_swapBuffers = 0;
 
+jmethodID JNI::_MID_AudioTrack_flush = 0;
 jmethodID JNI::_MID_AudioTrack_pause = 0;
 jmethodID JNI::_MID_AudioTrack_play = 0;
 jmethodID JNI::_MID_AudioTrack_stop = 0;
@@ -332,6 +333,15 @@ void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
 void JNI::setAudioPause() {
 	JNIEnv *env = JNI::getEnv();
 
+	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_flush);
+
+	if (env->ExceptionCheck()) {
+		warning("Error flushing AudioTrack");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+
 	env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause);
 
 	if (env->ExceptionCheck()) {
@@ -417,6 +427,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 			return;															\
 	} while (0)
 
+	FIND_METHOD(flush, "()V");
 	FIND_METHOD(pause, "()V");
 	FIND_METHOD(play, "()V");
 	FIND_METHOD(stop, "()V");
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index a1fc3df..0bc6498 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -95,6 +95,7 @@ private:
 	static jmethodID _MID_destroyScummVMSurface;
 	static jmethodID _MID_swapBuffers;
 
+	static jmethodID _MID_AudioTrack_flush;
 	static jmethodID _MID_AudioTrack_pause;
 	static jmethodID _MID_AudioTrack_play;
 	static jmethodID _MID_AudioTrack_stop;


Commit: d4c0501d1fcc8c98d39b2b7ba627cccb29cbc476
    https://github.com/scummvm/scummvm/commit/d4c0501d1fcc8c98d39b2b7ba627cccb29cbc476
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:37-08:00

Commit Message:
ANDROID: Check audio buffer for silence

Most games register a music channel, and when there is no music,
they still stream silence (and run through all the Converter::flow
code!). Scan the buffer for that to pause the AudioTrack. Ugly, but
worth it - reduces CPU usage on many games and hence saves battery life.

Changed paths:
    backends/platform/android/android.cpp



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 860ff1f..f20cf84 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -176,7 +176,7 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 
 	byte *buf;
 	int offset, left, written;
-	int samples;
+	int samples, i;
 
 	struct timespec tv_delay;
 	tv_delay.tv_sec = 0;
@@ -188,6 +188,7 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 	tv_full.tv_sec = 0;
 	tv_full.tv_nsec = msecs_full * 1000 * 1000;
 
+	bool silence;
 	uint silence_count = 0;
 
 	while (!system->_audio_thread_exit) {
@@ -196,9 +197,24 @@ void *OSystem_Android::audioThreadFunc(void *arg) {
 
 		samples = mixer->mixCallback(buf, buf_size);
 
+		silence = samples < 1;
+
+		// looks stupid, and it is, but currently there's no way to detect
+		// silence-only buffers from the mixer
+		if (!silence) {
+			silence = true;
+
+			for (i = 0; i < samples; i += 2)
+				// SID streams constant crap
+				if (READ_UINT16(buf + i) > 32) {
+					silence = false;
+					break;
+				}
+		}
+
 		env->ReleasePrimitiveArrayCritical(bufa, buf, 0);
 
-		if (samples < 1) {
+		if (silence) {
 			if (!paused)
 				silence_count++;
 


Commit: a73b2ec97279b1ef1562ece18c7905591e6a7cc4
    https://github.com/scummvm/scummvm/commit/a73b2ec97279b1ef1562ece18c7905591e6a7cc4
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T00:04:38-08:00

Commit Message:
ANDROID: Remove unnecessary code

Changed paths:
    backends/platform/android/jni.cpp
    backends/platform/android/org/inodes/gus/scummvm/ScummVM.java



diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 8964fe6..d8203e2 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -52,7 +52,6 @@ jfieldID JNI::_FID_Event_kbd_flags = 0;
 jfieldID JNI::_FID_Event_mouse_x = 0;
 jfieldID JNI::_FID_Event_mouse_y = 0;
 jfieldID JNI::_FID_Event_mouse_relative = 0;
-jfieldID JNI::_FID_ScummVM_nativeScummVM = 0;
 
 jmethodID JNI::_MID_displayMessageOnOSD = 0;
 jmethodID JNI::_MID_setWindowCaption = 0;
@@ -111,10 +110,6 @@ jint JNI::onLoad(JavaVM *vm) {
 	if (env->RegisterNatives(cls, _natives, ARRAYSIZE(_natives)) < 0)
 		return JNI_ERR;
 
-	_FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
-	if (_FID_ScummVM_nativeScummVM == 0)
-		return JNI_ERR;
-
 	jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
 	if (event == 0)
 		return JNI_ERR;
@@ -415,8 +410,6 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 
 #undef FIND_METHOD
 
-	env->SetLongField(self, _FID_ScummVM_nativeScummVM, (jlong)_system);
-
 	_jobj_audio_track = env->NewGlobalRef(at);
 
 	cls = env->GetObjectClass(_jobj_audio_track);
@@ -439,7 +432,8 @@ void JNI::create(JNIEnv *env, jobject self, jobject am, jobject at,
 }
 
 void JNI::destroy(JNIEnv *env, jobject self) {
-	assert(_system);
+	if (!_system)
+		return;
 
 	OSystem_Android *tmp = _system;
 	g_system = 0;
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index 7a32645..a6bc5fa 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -35,10 +35,6 @@ import java.util.LinkedHashMap;
 public class ScummVM implements SurfaceHolder.Callback {
 	protected final static String LOG_TAG = "ScummVM";
 
-	// native code hangs itself here
-	private long nativeScummVM;
-	boolean scummVMRunning = false;
-
 	private native void create(AssetManager am, AudioTrack audio_track,
 								int sample_rate, int buffer_size);
 
@@ -75,17 +71,14 @@ public class ScummVM implements SurfaceHolder.Callback {
 				String.format("Error initialising AudioTrack: %d",
 								audio_track.getState()));
 
-		// Init C++ code, set nativeScummVM
+		// Init C++ code
 		create(context.getAssets(), audio_track, sample_rate, buffer_size);
 	}
 
 	private native void nativeDestroy();
 
 	public synchronized void destroy() {
-		if (nativeScummVM != 0) {
-			nativeDestroy();
-			nativeScummVM = 0;
-		}
+		nativeDestroy();
 	}
 
 	protected void finalize() {
@@ -295,6 +288,7 @@ public class ScummVM implements SurfaceHolder.Callback {
 
 	// Called by ScummVM thread
 	static private boolean _log_version = true;
+
 	protected void setupScummVMSurface() {
 		try {
 			surfaceLock.acquire();


Commit: 1c95d47cfaf1f39b3c3012aa649ce3ced90ed147
    https://github.com/scummvm/scummvm/commit/1c95d47cfaf1f39b3c3012aa649ce3ced90ed147
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T01:10:44-08:00

Commit Message:
SWORD2: Respect screen pitch while postprocessing

Fixes subtitles on androids

Changed paths:
    engines/sword2/animation.cpp
    engines/sword2/animation.h



diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 3c506c0..8d0600a 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -110,7 +110,7 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
 
 	terminated = !playVideo();
 
-	closeTextObject(_currentMovieText, NULL);
+	closeTextObject(_currentMovieText, NULL, 0);
 
 	if (terminated) {
 		_snd->stopHandle(*_bgSoundHandle);
@@ -165,7 +165,7 @@ void MoviePlayer::openTextObject(uint32 index) {
 	}
 }
 
-void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
+void MoviePlayer::closeTextObject(uint32 index, byte *screen, uint16 pitch) {
 	if (index < _numMovieTexts) {
 		MovieText *text = &_movieTexts[index];
 
@@ -183,7 +183,7 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
 				int frameX = (_system->getWidth() - frameWidth) / 2;
 				int frameY = (_system->getHeight() - frameHeight) / 2;
 
-				byte *dst = screen + _textY * _system->getWidth();
+				byte *dst = screen + _textY * pitch;
 
 				for (int y = 0; y < text->_textSprite.h; y++) {
 					if (_textY + y < frameY || _textY + y >= frameY + frameHeight) {
@@ -195,7 +195,7 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
 							memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + text->_textSprite.w - (frameX + frameWidth));
 					}
 
-					dst += _system->getWidth();
+					dst += pitch;
 				}
 			}
 
@@ -205,7 +205,7 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen) {
 	}
 }
 
-void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
+void MoviePlayer::drawTextObject(uint32 index, byte *screen, uint16 pitch) {
 	MovieText *text = &_movieTexts[index];
 
 	byte white = findWhitePalIndex();
@@ -224,7 +224,7 @@ void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
 			src = buffer;
 		}
 
-		byte *dst = screen + _textY * RENDERWIDE + _textX;
+		byte *dst = screen + _textY * pitch + _textX;
 
 		for (int y = 0; y < height; y++) {
 			for (int x = 0; x < width; x++) {
@@ -234,12 +234,12 @@ void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
 					dst[x] = white;
 			}
 			src += width;
-			dst += RENDERWIDE;
+			dst += pitch;
 		}
 	}
 }
 
-void MoviePlayer::performPostProcessing(byte *screen) {
+void MoviePlayer::performPostProcessing(byte *screen, uint16 pitch) {
 	MovieText *text;
 	int frame = _decoder->getCurFrame();
 
@@ -261,9 +261,9 @@ void MoviePlayer::performPostProcessing(byte *screen) {
 			_vm->_sound->playCompSpeech(text->_speechId, 16, 0);
 		}
 		if (frame < text->_endFrame) {
-			drawTextObject(_currentMovieText, screen);
+			drawTextObject(_currentMovieText, screen, pitch);
 		} else {
-			closeTextObject(_currentMovieText, screen);
+			closeTextObject(_currentMovieText, screen, pitch);
 			_currentMovieText++;
 		}
 	}
@@ -313,7 +313,7 @@ bool MoviePlayer::playVideo() {
 			}
 
 			Graphics::Surface *screen = _vm->_system->lockScreen();
-			performPostProcessing((byte *)screen->pixels);
+			performPostProcessing((byte *)screen->pixels, screen->pitch);
 			_vm->_system->unlockScreen();
 			_vm->_system->updateScreen();
 		}
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index 550ac0f..afe7dfc 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -96,12 +96,12 @@ protected:
 	uint32 _leadOut;
 	int _leadOutFrame;
 
-	void performPostProcessing(byte *screen);
+	void performPostProcessing(byte *screen, uint16 pitch);
 	bool playVideo();
 
 	void openTextObject(uint32 index);
-	void closeTextObject(uint32 index, byte *screen);
-	void drawTextObject(uint32 index, byte *screen);
+	void closeTextObject(uint32 index, byte *screen, uint16 pitch);
+	void drawTextObject(uint32 index, byte *screen, uint16 pitch);
 
 	byte findBlackPalIndex();
 	byte findWhitePalIndex();


Commit: aa2a2e046b0a5979709c79deb84b6eea3c8f09d5
    https://github.com/scummvm/scummvm/commit/aa2a2e046b0a5979709c79deb84b6eea3c8f09d5
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-27T01:13:18-08:00

Commit Message:
SWORD2: Reduce overhead

Changed paths:
    engines/sword2/animation.cpp



diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 8d0600a..2fafb70 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -182,17 +182,18 @@ void MoviePlayer::closeTextObject(uint32 index, byte *screen, uint16 pitch) {
 				int frameHeight = _decoder->getHeight();
 				int frameX = (_system->getWidth() - frameWidth) / 2;
 				int frameY = (_system->getHeight() - frameHeight) / 2;
+				byte black = findBlackPalIndex();
 
 				byte *dst = screen + _textY * pitch;
 
 				for (int y = 0; y < text->_textSprite.h; y++) {
 					if (_textY + y < frameY || _textY + y >= frameY + frameHeight) {
-						memset(dst + _textX, findBlackPalIndex(), text->_textSprite.w);
+						memset(dst + _textX, black, text->_textSprite.w);
 					} else {
 						if (frameX > _textX)
-							memset(dst + _textX, findBlackPalIndex(), frameX - _textX);
+							memset(dst + _textX, black, frameX - _textX);
 						if (frameX + frameWidth < _textX + text->_textSprite.w)
-							memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + text->_textSprite.w - (frameX + frameWidth));
+							memset(dst + frameX + frameWidth, black, _textX + text->_textSprite.w - (frameX + frameWidth));
 					}
 
 					dst += pitch;






More information about the Scummvm-git-logs mailing list