From af3ae51ec8a295c40878acef168ad66bb5b3ceea Mon Sep 17 00:00:00 2001 From: James Sanford Date: Thu, 25 Jul 2013 20:19:47 -0700 Subject: [PATCH] Show current emulation speed in dialog. Use java.util.concurrent.atomic for objects shared between threads. --- jni/android_driver.c | 4 +-- src/com/froop/app/kegs/KegsThread.java | 37 ++++++++++++++--------- src/com/froop/app/kegs/SpeedFragment.java | 13 ++++++-- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/jni/android_driver.c b/jni/android_driver.c index 0c3e7d9..4b0b30a 100644 --- a/jni/android_driver.c +++ b/jni/android_driver.c @@ -566,12 +566,12 @@ check_input_events() // check if paused, first jclass cls = (*g_env)->GetObjectClass(g_env, g_thiz); - jmethodID mid = (*g_env)->GetMethodID(g_env, cls, "checkForPause", "()V"); + jmethodID mid = (*g_env)->GetMethodID(g_env, cls, "checkForPause", "(I)V"); (*g_env)->DeleteLocalRef(g_env, cls); if (mid == NULL) { return; } - (*g_env)->CallVoidMethod(g_env, g_thiz, mid); + (*g_env)->CallVoidMethod(g_env, g_thiz, mid, g_limit_speed); do { cls = (*g_env)->GetObjectClass(g_env, g_eventqueue); diff --git a/src/com/froop/app/kegs/KegsThread.java b/src/com/froop/app/kegs/KegsThread.java index 7855457..ddea821 100644 --- a/src/com/froop/app/kegs/KegsThread.java +++ b/src/com/froop/app/kegs/KegsThread.java @@ -3,6 +3,8 @@ package com.froop.app.kegs; import android.graphics.Bitmap; import android.util.AttributeSet; import android.util.Log; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.ConcurrentLinkedQueue; @@ -14,12 +16,13 @@ class KegsThread extends Thread { private String mConfigFile; // full path to config_kegs private Bitmap mBitmap; + private final AtomicInteger mCurrentSpeed = new AtomicInteger(0); private final ReentrantLock mPauseLock = new ReentrantLock(); private final ReentrantLock mPowerWait = new ReentrantLock(); // Look also at mPauseLock. - private boolean mPaused = false; - private boolean mReady = false; // 'true' will begin the native thread. + private final AtomicBoolean mPaused = new AtomicBoolean(false); + private final AtomicBoolean mReady = new AtomicBoolean(false); interface UpdateScreen { void updateScreen(); @@ -47,8 +50,9 @@ class KegsThread extends Thread { } // Called by native thread. - private void checkForPause() { - if (mPaused) { + private void checkForPause(int currentEmulationSpeed) { + mCurrentSpeed.set(currentEmulationSpeed); // NOTE: This is a hack. + if (mPaused.get()) { mPauseLock.lock(); // deadlock here until onResume. Maybe not efficient. mPauseLock.unlock(); @@ -80,22 +84,22 @@ class KegsThread extends Thread { } public void onPause() { - if (!mReady) { + if (!mReady.get()) { return; // bail out, we haven't started doing anything yet } - if (!mPaused) { - mPaused = true; + if (!mPaused.get()) { + mPaused.set(true); mPauseLock.lock(); } } public void onResume() { - if (!mReady) { + if (!mReady.get()) { return; // bail out, we haven't started doing anything yet } updateScreen(); - if (mPaused) { - mPaused = false; + if (mPaused.get()) { + mPaused.set(false); mPauseLock.unlock(); } else if (!isAlive()) { start(); @@ -108,7 +112,7 @@ class KegsThread extends Thread { } public void doPowerOff() { - if (!mReady) { + if (!mReady.get()) { return; // bail out, we haven't started doing anything yet } @@ -121,8 +125,8 @@ class KegsThread extends Thread { // Call from the UI thread only. public void allowPowerOn() { - if (!mReady) { - mReady = true; + if (!mReady.get()) { + mReady.set(true); onResume(); // Will start the thread if not already started. return; } @@ -136,7 +140,7 @@ class KegsThread extends Thread { // Is native thread loop sitting around waiting for us to allow power on? public boolean nowWaitingForPowerOn() { - if (!mReady) { + if (!mReady.get()) { return true; // bail out, we haven't started doing anything yet } @@ -150,6 +154,11 @@ class KegsThread extends Thread { getEventQueue().add(new Event.KeyKegsEvent(speed + 0x80, true)); } + public int getEmulationSpeed() { + // Equal to g_limit_speed inside KEGS. + return mCurrentSpeed.get(); + } + public void doWarmReset() { // Press keys down. getEventQueue().add(new Event.KeyKegsEvent(KegsKeyboard.KEY_OPEN_APPLE, false)); diff --git a/src/com/froop/app/kegs/SpeedFragment.java b/src/com/froop/app/kegs/SpeedFragment.java index 078af7e..dc3f340 100644 --- a/src/com/froop/app/kegs/SpeedFragment.java +++ b/src/com/froop/app/kegs/SpeedFragment.java @@ -12,13 +12,20 @@ public class SpeedFragment extends SherlockDialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - // TODO: Show the current speed and use setSingleChoiceItems + + int currentSpeed = ((KegsMain)getActivity()).getThread().getEmulationSpeed(); + // Adjust g_limit_speed to match default item number. + currentSpeed--; + if (currentSpeed < 0) { + currentSpeed = 3; + } + builder.setTitle(R.string.speed_title); - builder.setItems(R.array.speed_choices, + builder.setSingleChoiceItems(R.array.speed_choices, currentSpeed, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { dismiss(); - // Adjust item number to match g_limit_speed. + // Adjust selected item number to match g_limit_speed. item++; if (item > 3) { item = 0;