mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-27 08:15:33 +01:00
Move emulation lifecycle handling into EmulationFragment.
The Activity is responsible for just its views and menus and such. It signals the Fragment via setGamePath, StartEmulation and StopEmulation. The Fragment manages the actual emulation lifecycle. It is solely responsible for calling the NativeLibrary lifecycle methods. With this lifecycle simplification, the NativeLibrary no longer needs to kill the Activity. It happens normally now. This simplifies a lot of things, live handling rotation.
This commit is contained in:
parent
d48c64457a
commit
4cab718065
@ -399,20 +399,6 @@ public final class NativeLibrary
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void endEmulationActivity()
|
|
||||||
{
|
|
||||||
Log.verbose("[NativeLibrary] Ending EmulationActivity.");
|
|
||||||
EmulationActivity emulationActivity = sEmulationActivity.get();
|
|
||||||
if (emulationActivity != null)
|
|
||||||
{
|
|
||||||
emulationActivity.exitWithAnimation();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.warning("[NativeLibrary] EmulationActivity is null, can't end.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setEmulationActivity(EmulationActivity emulationActivity)
|
public static void setEmulationActivity(EmulationActivity emulationActivity)
|
||||||
{
|
{
|
||||||
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
||||||
|
@ -23,7 +23,6 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
@ -55,8 +54,8 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
private static final String FRAGMENT_SUBMENU_TAG = "submenu";
|
private static final String FRAGMENT_SUBMENU_TAG = "submenu";
|
||||||
private View mDecorView;
|
private View mDecorView;
|
||||||
private ImageView mImageView;
|
private ImageView mImageView;
|
||||||
|
private EmulationFragment mEmulationFragment;
|
||||||
|
|
||||||
private FrameLayout mFrameEmulation;
|
|
||||||
private LinearLayout mMenuLayout;
|
private LinearLayout mMenuLayout;
|
||||||
|
|
||||||
private SharedPreferences mPreferences;
|
private SharedPreferences mPreferences;
|
||||||
@ -85,7 +84,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
private String mScreenPath;
|
private String mScreenPath;
|
||||||
private FrameLayout mFrameContent;
|
|
||||||
private String mSelectedTitle;
|
private String mSelectedTitle;
|
||||||
|
|
||||||
@Retention(SOURCE)
|
@Retention(SOURCE)
|
||||||
@ -219,12 +217,13 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
|
|
||||||
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||||
Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||||
|
|
||||||
setContentView(R.layout.activity_emulation);
|
setContentView(R.layout.activity_emulation);
|
||||||
|
|
||||||
mImageView = (ImageView) findViewById(R.id.image_screenshot);
|
mImageView = (ImageView) findViewById(R.id.image_screenshot);
|
||||||
mFrameContent = (FrameLayout) findViewById(R.id.frame_content);
|
|
||||||
mFrameEmulation = (FrameLayout) findViewById(R.id.frame_emulation_fragment);
|
|
||||||
mMenuLayout = (LinearLayout) findViewById(R.id.layout_ingame_menu);
|
mMenuLayout = (LinearLayout) findViewById(R.id.layout_ingame_menu);
|
||||||
|
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||||
|
.findFragmentById(R.id.fragment_emulation);
|
||||||
|
|
||||||
Intent gameToEmulate = getIntent();
|
Intent gameToEmulate = getIntent();
|
||||||
String path = gameToEmulate.getStringExtra("SelectedGame");
|
String path = gameToEmulate.getStringExtra("SelectedGame");
|
||||||
@ -260,14 +259,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
|
|
||||||
Animations.fadeViewOut(mImageView)
|
Animations.fadeViewOut(mImageView)
|
||||||
.setStartDelay(2000)
|
.setStartDelay(2000)
|
||||||
.withStartAction(new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
mFrameEmulation.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.withEndAction(new Runnable()
|
.withEndAction(new Runnable()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@ -277,18 +268,12 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Instantiate an EmulationFragment.
|
mEmulationFragment.setGamePath(path);
|
||||||
EmulationFragment emulationFragment = EmulationFragment.newInstance(path);
|
mEmulationFragment.startEmulation();
|
||||||
|
|
||||||
// Add fragment to the activity - this triggers all its lifecycle callbacks.
|
|
||||||
getSupportFragmentManager().beginTransaction()
|
|
||||||
.add(R.id.frame_emulation_fragment, emulationFragment, EmulationFragment.FRAGMENT_TAG)
|
|
||||||
.commit();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mImageView.setVisibility(View.GONE);
|
mImageView.setVisibility(View.GONE);
|
||||||
mFrameEmulation.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDeviceHasTouchScreen)
|
if (mDeviceHasTouchScreen)
|
||||||
@ -311,23 +296,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
mIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE;
|
mIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStart()
|
|
||||||
{
|
|
||||||
super.onStart();
|
|
||||||
Log.debug("[EmulationActivity] EmulationActivity starting.");
|
|
||||||
NativeLibrary.setEmulationActivity(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStop()
|
|
||||||
{
|
|
||||||
super.onStop();
|
|
||||||
Log.debug("[EmulationActivity] EmulationActivity stopping.");
|
|
||||||
|
|
||||||
NativeLibrary.clearEmulationActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostCreate(Bundle savedInstanceState)
|
protected void onPostCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
@ -376,7 +344,8 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stopEmulation();
|
mEmulationFragment.stopEmulation();
|
||||||
|
exitWithAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,15 +375,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopEmulation()
|
|
||||||
{
|
|
||||||
EmulationFragment fragment = (EmulationFragment) getSupportFragmentManager()
|
|
||||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
|
||||||
fragment.notifyEmulationStopped();
|
|
||||||
|
|
||||||
NativeLibrary.StopEmulation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exitWithAnimation()
|
public void exitWithAnimation()
|
||||||
{
|
{
|
||||||
runOnUiThread(new Runnable()
|
runOnUiThread(new Runnable()
|
||||||
@ -458,7 +418,6 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
mFrameContent.removeView(mFrameEmulation);
|
|
||||||
setResult(mPosition);
|
setResult(mPosition);
|
||||||
finishAfterTransition();
|
finishAfterTransition();
|
||||||
}
|
}
|
||||||
@ -599,20 +558,23 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case MENU_ACTION_EXIT:
|
case MENU_ACTION_EXIT:
|
||||||
toggleMenu();
|
toggleMenu(); // Hide the menu (it will be showing since we just clicked it)
|
||||||
stopEmulation();
|
mEmulationFragment.stopEmulation();
|
||||||
|
exitWithAnimation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void editControlsPlacement() {
|
private void editControlsPlacement()
|
||||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
{
|
||||||
.findFragmentById(R.id.frame_emulation_fragment);
|
if (mEmulationFragment.isConfiguringControls())
|
||||||
if (emulationFragment.isConfiguringControls()) {
|
{
|
||||||
emulationFragment.stopConfiguringControls();
|
mEmulationFragment.stopConfiguringControls();
|
||||||
} else {
|
}
|
||||||
emulationFragment.startConfiguringControls();
|
else
|
||||||
|
{
|
||||||
|
mEmulationFragment.startConfiguringControls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,20 +663,18 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
builder.setNeutralButton(getString(R.string.emulation_toggle_all), new DialogInterface.OnClickListener() {
|
builder.setNeutralButton(getString(R.string.emulation_toggle_all), new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i)
|
||||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
{
|
||||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
mEmulationFragment.toggleInputOverlayVisibility();
|
||||||
emulationFragment.toggleInputOverlayVisibility();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
|
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i)
|
||||||
|
{
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
mEmulationFragment.refreshInputOverlay();
|
||||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
|
||||||
emulationFragment.refreshInputOverlay();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -759,9 +719,7 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
editor.putInt("controlScale", seekbar.getProgress());
|
editor.putInt("controlScale", seekbar.getProgress());
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
mEmulationFragment.refreshInputOverlay();
|
||||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
|
||||||
emulationFragment.refreshInputOverlay();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -788,9 +746,7 @@ public final class EmulationActivity extends AppCompatActivity
|
|||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
EmulationFragment emulationFragment = (EmulationFragment) getSupportFragmentManager()
|
mEmulationFragment.refreshInputOverlay();
|
||||||
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
|
|
||||||
emulationFragment.refreshInputOverlay();
|
|
||||||
|
|
||||||
Toast.makeText(getApplication(), R.string.emulation_controller_changed, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplication(), R.string.emulation_controller_changed, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.dolphinemu.dolphinemu.fragments;
|
package org.dolphinemu.dolphinemu.fragments;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@ -14,15 +15,12 @@ import android.widget.Button;
|
|||||||
|
|
||||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
|
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||||
import org.dolphinemu.dolphinemu.overlay.InputOverlay;
|
import org.dolphinemu.dolphinemu.overlay.InputOverlay;
|
||||||
import org.dolphinemu.dolphinemu.utils.Log;
|
import org.dolphinemu.dolphinemu.utils.Log;
|
||||||
|
|
||||||
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
|
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
|
||||||
{
|
{
|
||||||
public static final String FRAGMENT_TAG = "emulation_fragment";
|
|
||||||
|
|
||||||
private static final String ARG_GAME_PATH = "game_path";
|
|
||||||
|
|
||||||
private SharedPreferences mPreferences;
|
private SharedPreferences mPreferences;
|
||||||
|
|
||||||
private Surface mSurface;
|
private Surface mSurface;
|
||||||
@ -31,18 +29,22 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
|
|
||||||
private Thread mEmulationThread;
|
private Thread mEmulationThread;
|
||||||
|
|
||||||
private boolean mEmulationStarted;
|
private String mGamePath;
|
||||||
private boolean mEmulationRunning;
|
private final EmulationState mEmulationState = new EmulationState();
|
||||||
|
|
||||||
public static EmulationFragment newInstance(String path)
|
@Override
|
||||||
|
public void onAttach(Context context)
|
||||||
{
|
{
|
||||||
EmulationFragment fragment = new EmulationFragment();
|
super.onAttach(context);
|
||||||
|
|
||||||
Bundle arguments = new Bundle();
|
if (context instanceof EmulationActivity)
|
||||||
arguments.putString(ARG_GAME_PATH, path);
|
{
|
||||||
fragment.setArguments(arguments);
|
NativeLibrary.setEmulationActivity((EmulationActivity) context);
|
||||||
|
}
|
||||||
return fragment;
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("EmulationFragment must have EmulationActivity parent");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,38 +69,20 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
{
|
{
|
||||||
View contents = inflater.inflate(R.layout.fragment_emulation, container, false);
|
View contents = inflater.inflate(R.layout.fragment_emulation, container, false);
|
||||||
|
|
||||||
SurfaceView surfaceView = (SurfaceView) contents.findViewById(R.id.surface_emulation);
|
SurfaceView surfaceView = contents.findViewById(R.id.surface_emulation);
|
||||||
mInputOverlay = (InputOverlay) contents.findViewById(R.id.surface_input_overlay);
|
|
||||||
|
|
||||||
surfaceView.getHolder().addCallback(this);
|
surfaceView.getHolder().addCallback(this);
|
||||||
|
|
||||||
// If the input overlay was previously disabled, then don't show it.
|
mInputOverlay = contents.findViewById(R.id.surface_input_overlay);
|
||||||
if (mInputOverlay != null)
|
if (mInputOverlay != null)
|
||||||
{
|
{
|
||||||
|
// If the input overlay was previously disabled, then don't show it.
|
||||||
if (!mPreferences.getBoolean("showInputOverlay", true))
|
if (!mPreferences.getBoolean("showInputOverlay", true))
|
||||||
{
|
{
|
||||||
mInputOverlay.setVisibility(View.GONE);
|
mInputOverlay.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (savedInstanceState == null)
|
Button doneButton = contents.findViewById(R.id.done_control_config);
|
||||||
{
|
|
||||||
mEmulationThread = new Thread(mEmulationRunner);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Likely a rotation occurred.
|
|
||||||
// TODO Pass native code the Surface, which will have been recreated, from surfaceChanged()
|
|
||||||
// TODO Also, write the native code that will get the video backend to accept the new Surface as one of its own.
|
|
||||||
}
|
|
||||||
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
Button doneButton = (Button) view.findViewById(R.id.done_control_config);
|
|
||||||
if (doneButton != null)
|
if (doneButton != null)
|
||||||
{
|
{
|
||||||
doneButton.setOnClickListener(new View.OnClickListener()
|
doneButton.setOnClickListener(new View.OnClickListener()
|
||||||
@ -110,29 +94,29 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// The new Surface created here will get passed to the native code via onSurfaceChanged.
|
||||||
public void onStart()
|
|
||||||
{
|
return contents;
|
||||||
super.onStart();
|
|
||||||
startEmulation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop()
|
public void onStop()
|
||||||
{
|
{
|
||||||
|
pauseEmulation();
|
||||||
super.onStop();
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView()
|
public void onDetach()
|
||||||
{
|
{
|
||||||
super.onDestroyView();
|
NativeLibrary.clearEmulationActivity();
|
||||||
if (getActivity().isFinishing() && mEmulationStarted)
|
super.onDetach();
|
||||||
{
|
}
|
||||||
NativeLibrary.StopEmulation();
|
|
||||||
}
|
public void setGamePath(String setPath)
|
||||||
|
{
|
||||||
|
this.mGamePath = setPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleInputOverlayVisibility()
|
public void toggleInputOverlayVisibility()
|
||||||
@ -171,6 +155,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
||||||
{
|
{
|
||||||
Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height);
|
Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height);
|
||||||
|
|
||||||
|
if (mEmulationState.isPaused())
|
||||||
|
{
|
||||||
|
NativeLibrary.UnPauseEmulation();
|
||||||
|
}
|
||||||
|
|
||||||
mSurface = holder.getSurface();
|
mSurface = holder.getSurface();
|
||||||
NativeLibrary.SurfaceChanged(mSurface);
|
NativeLibrary.SurfaceChanged(mSurface);
|
||||||
}
|
}
|
||||||
@ -181,45 +171,57 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
Log.debug("[EmulationFragment] Surface destroyed.");
|
Log.debug("[EmulationFragment] Surface destroyed.");
|
||||||
NativeLibrary.SurfaceDestroyed();
|
NativeLibrary.SurfaceDestroyed();
|
||||||
|
|
||||||
if (mEmulationRunning)
|
if (mEmulationState.isRunning())
|
||||||
{
|
{
|
||||||
pauseEmulation();
|
pauseEmulation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startEmulation()
|
public void startEmulation()
|
||||||
{
|
{
|
||||||
if (!mEmulationStarted)
|
synchronized (mEmulationState)
|
||||||
{
|
{
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.");
|
if (mEmulationState.isStopped())
|
||||||
|
{
|
||||||
|
Log.debug("[EmulationFragment] Starting emulation thread.");
|
||||||
|
|
||||||
mEmulationThread.start();
|
mEmulationThread = new Thread(mEmulationRunner, "NativeEmulation");
|
||||||
|
mEmulationThread.start();
|
||||||
|
// The thread will call mEmulationState.run()
|
||||||
|
}
|
||||||
|
else if (mEmulationState.isPaused())
|
||||||
|
{
|
||||||
|
Log.debug("[EmulationFragment] Resuming emulation.");
|
||||||
|
NativeLibrary.UnPauseEmulation();
|
||||||
|
mEmulationState.run();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.debug("[EmulationFragment] Bug, startEmulation called while running.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
|
||||||
|
public void stopEmulation() {
|
||||||
|
synchronized (mEmulationState)
|
||||||
{
|
{
|
||||||
Log.debug("[EmulationFragment] Resuming emulation.");
|
if (!mEmulationState.isStopped())
|
||||||
NativeLibrary.UnPauseEmulation();
|
{
|
||||||
|
NativeLibrary.StopEmulation();
|
||||||
|
mEmulationState.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mEmulationRunning = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pauseEmulation()
|
private void pauseEmulation()
|
||||||
{
|
{
|
||||||
Log.debug("[EmulationFragment] Pausing emulation.");
|
synchronized (mEmulationState)
|
||||||
|
{
|
||||||
|
Log.debug("[EmulationFragment] Pausing emulation.");
|
||||||
|
|
||||||
NativeLibrary.PauseEmulation();
|
NativeLibrary.PauseEmulation();
|
||||||
mEmulationRunning = false;
|
mEmulationState.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by containing activity to tell the Fragment emulation is already stopping,
|
|
||||||
* so it doesn't try to stop emulation on its way to the garbage collector.
|
|
||||||
*/
|
|
||||||
public void notifyEmulationStopped()
|
|
||||||
{
|
|
||||||
mEmulationStarted = false;
|
|
||||||
mEmulationRunning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Runnable mEmulationRunner = new Runnable()
|
private Runnable mEmulationRunner = new Runnable()
|
||||||
@ -227,18 +229,17 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
mEmulationRunning = true;
|
// Busy-wait for surface to be set
|
||||||
mEmulationStarted = true;
|
while (mSurface == null) {}
|
||||||
|
|
||||||
while (mSurface == null)
|
synchronized (mEmulationState)
|
||||||
if (!mEmulationRunning)
|
{
|
||||||
return;
|
Log.info("[EmulationFragment] Starting emulation: " + mSurface);
|
||||||
|
|
||||||
Log.info("[EmulationFragment] Starting emulation: " + mSurface);
|
|
||||||
|
|
||||||
|
mEmulationState.run();
|
||||||
|
}
|
||||||
// Start emulation using the provided Surface.
|
// Start emulation using the provided Surface.
|
||||||
String path = getArguments().getString(ARG_GAME_PATH);
|
NativeLibrary.Run(mGamePath);
|
||||||
NativeLibrary.Run(path);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -258,4 +259,50 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||||||
{
|
{
|
||||||
return mInputOverlay.isInEditMode();
|
return mInputOverlay.isInEditMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class EmulationState
|
||||||
|
{
|
||||||
|
private enum State
|
||||||
|
{
|
||||||
|
STOPPED, RUNNING, PAUSED
|
||||||
|
}
|
||||||
|
|
||||||
|
private State state;
|
||||||
|
|
||||||
|
EmulationState()
|
||||||
|
{
|
||||||
|
// Starting state is stopped.
|
||||||
|
state = State.STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStopped()
|
||||||
|
{
|
||||||
|
return state == State.STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRunning()
|
||||||
|
{
|
||||||
|
return state == State.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPaused()
|
||||||
|
{
|
||||||
|
return state == State.PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
state = State.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pause()
|
||||||
|
{
|
||||||
|
state = State.PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
state = State.STOPPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/frame_content">
|
android:id="@+id/frame_content">
|
||||||
|
|
||||||
<FrameLayout
|
<fragment
|
||||||
android:id="@+id/frame_emulation_fragment"
|
android:id="@+id/fragment_emulation"
|
||||||
|
android:name="org.dolphinemu.dolphinemu.fragments.EmulationFragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"/>
|
||||||
android:visibility="invisible"/>
|
|
||||||
|
|
||||||
<org.dolphinemu.dolphinemu.ui.NVidiaShieldWorkaroundView
|
<org.dolphinemu.dolphinemu.ui.NVidiaShieldWorkaroundView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/frame_content">
|
android:id="@+id/frame_content">
|
||||||
|
|
||||||
<FrameLayout
|
<fragment
|
||||||
android:id="@+id/frame_emulation_fragment"
|
android:id="@+id/fragment_emulation"
|
||||||
|
android:name="org.dolphinemu.dolphinemu.fragments.EmulationFragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"/>
|
||||||
android:visibility="invisible"/>
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -58,7 +58,6 @@ std::string s_set_userpath;
|
|||||||
|
|
||||||
jclass s_jni_class;
|
jclass s_jni_class;
|
||||||
jmethodID s_jni_method_alert;
|
jmethodID s_jni_method_alert;
|
||||||
jmethodID s_jni_method_end;
|
|
||||||
|
|
||||||
// The Core only supports using a single Host thread.
|
// The Core only supports using a single Host thread.
|
||||||
// If multiple threads want to call host functions then they need to queue
|
// If multiple threads want to call host functions then they need to queue
|
||||||
@ -732,7 +731,6 @@ Java_org_dolphinemu_dolphinemu_NativeLibrary_CacheClassesAndMethods(JNIEnv* env,
|
|||||||
// Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class
|
// Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class
|
||||||
s_jni_method_alert =
|
s_jni_method_alert =
|
||||||
env->GetStaticMethodID(s_jni_class, "displayAlertMsg", "(Ljava/lang/String;)V");
|
env->GetStaticMethodID(s_jni_class, "displayAlertMsg", "(Ljava/lang/String;)V");
|
||||||
s_jni_method_end = env->GetStaticMethodID(s_jni_class, "endEmulationActivity", "()V");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Surface Handling
|
// Surface Handling
|
||||||
@ -816,9 +814,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv*
|
|||||||
ANativeWindow_release(s_surf);
|
ANativeWindow_release(s_surf);
|
||||||
s_surf = nullptr;
|
s_surf = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the Java method.
|
|
||||||
env->CallStaticVoidMethod(s_jni_class, s_jni_method_end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
x
Reference in New Issue
Block a user