Merge pull request #2624 from sigmabeta/android-save-screenshot

Android: Save screenshot at end of an emulation session.
This commit is contained in:
Ryan Houdek 2015-06-24 21:39:47 -05:00
commit 521f6e89c3
11 changed files with 67 additions and 20 deletions

View File

@ -274,6 +274,12 @@ public final class NativeLibrary
}); });
} }
public static void endEmulationActivity()
{
Log.v("DolphinEmu", "Ending EmulationActivity.");
mEmulationActivity.finish();
}
public static void setEmulationActivity(EmulationActivity emulationActivity) public static void setEmulationActivity(EmulationActivity emulationActivity)
{ {
Log.v("DolphinEmu", "Registering EmulationActivity."); Log.v("DolphinEmu", "Registering EmulationActivity.");

View File

@ -150,7 +150,11 @@ public final class EmulationActivity extends AppCompatActivity
else else
{ {
// Let the system handle it; i.e. quit the activity TODO or show "are you sure?" dialog. // Let the system handle it; i.e. quit the activity TODO or show "are you sure?" dialog.
super.onBackPressed(); EmulationFragment fragment = (EmulationFragment) getFragmentManager()
.findFragmentByTag(EmulationFragment.FRAGMENT_TAG);
fragment.notifyEmulationStopped();
NativeLibrary.StopEmulation();
} }
} }

View File

@ -79,9 +79,13 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
{ {
if (mCursor.moveToPosition(position)) if (mCursor.moveToPosition(position))
{ {
String screenPath = mCursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH);
Picasso.with(holder.imageScreenshot.getContext())
.invalidate(screenPath);
// Fill in the view contents. // Fill in the view contents.
Picasso.with(holder.imageScreenshot.getContext()) Picasso.with(holder.imageScreenshot.getContext())
.load(mCursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH)) .load(screenPath)
.fit() .fit()
.centerCrop() .centerCrop()
.error(R.drawable.no_banner) .error(R.drawable.no_banner)

View File

@ -119,7 +119,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
public void onDestroyView() public void onDestroyView()
{ {
super.onDestroyView(); super.onDestroyView();
if (getActivity().isFinishing()) if (getActivity().isFinishing() && mEmulationStarted)
{ {
NativeLibrary.StopEmulation(); NativeLibrary.StopEmulation();
} }
@ -195,6 +195,16 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
mEmulationRunning = false; mEmulationRunning = false;
} }
/**
* 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()
{ {
@Override @Override

View File

@ -113,21 +113,7 @@ public final class Game
{ {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
// TODO Come up with a way of finding the most recent screenshot that doesn't involve counting files String screenPath = PATH_SCREENSHOT_FOLDER + gameId + "/thumb.png";
String screenshotFolderPath = PATH_SCREENSHOT_FOLDER + gameId + "/";
// Count how many screenshots are available, so we can use the most recent one.
File screenshotFolder = new File(screenshotFolderPath.substring(screenshotFolderPath.indexOf('s') - 1));
int screenCount = 0;
if (screenshotFolder.isDirectory())
{
screenCount = screenshotFolder.list().length;
}
String screenPath = screenshotFolderPath
+ gameId + "-"
+ screenCount + ".png";
values.put(GameDatabase.KEY_GAME_PLATFORM, platform); values.put(GameDatabase.KEY_GAME_PLATFORM, platform);
values.put(GameDatabase.KEY_GAME_TITLE, title); values.put(GameDatabase.KEY_GAME_TITLE, title);

View File

@ -636,7 +636,7 @@ EState GetState()
return CORE_UNINITIALIZED; return CORE_UNINITIALIZED;
} }
static std::string GenerateScreenshotName() static std::string GenerateScreenshotFolderPath()
{ {
const std::string& gameId = SConfig::GetInstance().GetUniqueID(); const std::string& gameId = SConfig::GetInstance().GetUniqueID();
std::string path = File::GetUserPath(D_SCREENSHOTS_IDX) + gameId + DIR_SEP_CHR; std::string path = File::GetUserPath(D_SCREENSHOTS_IDX) + gameId + DIR_SEP_CHR;
@ -647,8 +647,15 @@ static std::string GenerateScreenshotName()
path = File::GetUserPath(D_SCREENSHOTS_IDX); path = File::GetUserPath(D_SCREENSHOTS_IDX);
} }
return path;
}
static std::string GenerateScreenshotName()
{
std::string path = GenerateScreenshotFolderPath();
//append gameId, path only contains the folder here. //append gameId, path only contains the folder here.
path += gameId; path += SConfig::GetInstance().GetUniqueID();
std::string name; std::string name;
for (int i = 1; File::Exists(name = StringFromFormat("%s-%d.png", path.c_str(), i)); ++i) for (int i = 1; File::Exists(name = StringFromFormat("%s-%d.png", path.c_str(), i)); ++i)
@ -671,6 +678,20 @@ void SaveScreenShot()
SetState(CORE_RUN); SetState(CORE_RUN);
} }
void SaveScreenShot(const std::string name)
{
const bool bPaused = (GetState() == CORE_PAUSE);
SetState(CORE_PAUSE);
std::string filePath = GenerateScreenshotFolderPath() + name + ".png";
g_video_backend->Video_Screenshot(filePath);
if (!bPaused)
SetState(CORE_RUN);
}
void RequestRefreshInfo() void RequestRefreshInfo()
{ {
s_request_refresh_info = true; s_request_refresh_info = true;

View File

@ -52,6 +52,7 @@ void SetState(EState _State);
EState GetState(); EState GetState();
void SaveScreenShot(); void SaveScreenShot();
void SaveScreenShot(std::string name);
void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size); void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size);

View File

@ -31,6 +31,7 @@
#include "UICommon/UICommon.h" #include "UICommon/UICommon.h"
#include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoBackendBase.h"
ANativeWindow* surf; ANativeWindow* surf;
@ -40,6 +41,7 @@ std::string g_set_userpath = "";
JavaVM* g_java_vm; JavaVM* g_java_vm;
jclass g_jni_class; jclass g_jni_class;
jmethodID g_jni_method_alert; jmethodID g_jni_method_alert;
jmethodID g_jni_method_end;
#define DOLPHIN_TAG "DolphinEmuNative" #define DOLPHIN_TAG "DolphinEmuNative"
@ -394,6 +396,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulati
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv *env, jobject obj) JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv *env, jobject obj)
{ {
Core::SaveScreenShot("thumb");
Renderer::s_screenshotCompleted.Wait();
Core::Stop(); Core::Stop();
updateMainFrameEvent.Set(); // Kick the waiting event updateMainFrameEvent.Set(); // Kick the waiting event
} }
@ -591,6 +595,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_CacheClasses
// Method signature taken from javap -s Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class // Method signature taken from javap -s Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class
g_jni_method_alert = env->GetStaticMethodID(g_jni_class, "displayAlertMsg", "(Ljava/lang/String;)V"); g_jni_method_alert = env->GetStaticMethodID(g_jni_class, "displayAlertMsg", "(Ljava/lang/String;)V");
g_jni_method_end = env->GetStaticMethodID(g_jni_class, "endEmulationActivity", "()V");
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj, jobject _surf) JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj, jobject _surf)
@ -624,6 +629,9 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
UICommon::Shutdown(); UICommon::Shutdown();
ANativeWindow_release(surf); ANativeWindow_release(surf);
// Execute the Java method.
env->CallStaticVoidMethod(g_jni_class, g_jni_method_end);
} }

View File

@ -1515,6 +1515,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
// Reset settings // Reset settings
s_sScreenshotName.clear(); s_sScreenshotName.clear();
s_bScreenshot = false; s_bScreenshot = false;
s_screenshotCompleted.Set();
} }
// Frame dumps are handled a little differently in Windows // Frame dumps are handled a little differently in Windows

View File

@ -17,6 +17,7 @@
#include <string> #include <string>
#include "Common/Atomic.h" #include "Common/Atomic.h"
#include "Common/Event.h"
#include "Common/Profiler.h" #include "Common/Profiler.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "Common/Timer.h" #include "Common/Timer.h"
@ -53,6 +54,8 @@ Renderer *g_renderer = nullptr;
std::mutex Renderer::s_criticalScreenshot; std::mutex Renderer::s_criticalScreenshot;
std::string Renderer::s_sScreenshotName; std::string Renderer::s_sScreenshotName;
Common::Event Renderer::s_screenshotCompleted;
volatile bool Renderer::s_bScreenshot; volatile bool Renderer::s_bScreenshot;
// The framebuffer size // The framebuffer size

View File

@ -17,6 +17,7 @@
#include <mutex> #include <mutex>
#include <string> #include <string>
#include "Common/Event.h"
#include "Common/MathUtil.h" #include "Common/MathUtil.h"
#include "Common/Thread.h" #include "Common/Thread.h"
#include "VideoCommon/BPMemory.h" #include "VideoCommon/BPMemory.h"
@ -133,6 +134,8 @@ public:
// Max height/width // Max height/width
virtual int GetMaxTextureSize() = 0; virtual int GetMaxTextureSize() = 0;
static Common::Event s_screenshotCompleted;
protected: protected:
static void CalculateTargetScale(int x, int y, int* scaledX, int* scaledY); static void CalculateTargetScale(int x, int y, int* scaledX, int* scaledY);