Added JS script monitoring thread to prevent bad scripts from hanging the gui.
This commit is contained in:
parent
5495c7eddc
commit
1fc813803e
|
@ -131,12 +131,12 @@ bool EmuScriptObject::paused()
|
||||||
return FCEUI_EmulationPaused() != 0;
|
return FCEUI_EmulationPaused() != 0;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
int EmuScriptObject::framecount()
|
int EmuScriptObject::frameCount()
|
||||||
{
|
{
|
||||||
return FCEUMOV_GetFrame();
|
return FCEUMOV_GetFrame();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
int EmuScriptObject::lagcount()
|
int EmuScriptObject::lagCount()
|
||||||
{
|
{
|
||||||
return FCEUI_GetLagCount();
|
return FCEUI_GetLagCount();
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ bool EmuScriptObject::lagged()
|
||||||
return FCEUI_GetLagged();
|
return FCEUI_GetLagged();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void EmuScriptObject::setlagflag(bool flag)
|
void EmuScriptObject::setLagFlag(bool flag)
|
||||||
{
|
{
|
||||||
FCEUI_SetLagFlag(flag);
|
FCEUI_SetLagFlag(flag);
|
||||||
}
|
}
|
||||||
|
@ -200,14 +200,14 @@ void EmuScriptObject::speedMode(const QString& mode)
|
||||||
FCEUD_SetEmulationSpeed(speed);
|
FCEUD_SetEmulationSpeed(speed);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void EmuScriptObject::registerBefore(const QJSValue& func)
|
void EmuScriptObject::registerBeforeFrame(const QJSValue& func)
|
||||||
{
|
{
|
||||||
script->registerBefore(func);
|
script->registerBeforeEmuFrame(func);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void EmuScriptObject::registerAfter(const QJSValue& func)
|
void EmuScriptObject::registerAfterFrame(const QJSValue& func)
|
||||||
{
|
{
|
||||||
script->registerAfter(func);
|
script->registerAfterEmuFrame(func);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void EmuScriptObject::registerStop(const QJSValue& func)
|
void EmuScriptObject::registerStop(const QJSValue& func)
|
||||||
|
@ -278,7 +278,7 @@ static void addressReadCallback(unsigned int address, unsigned int value, void *
|
||||||
{
|
{
|
||||||
QJSValueList args = { address, value };
|
QJSValueList args = { address, value };
|
||||||
|
|
||||||
func->call(args);
|
mem->getScript()->runFunc( *func, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ static void addressWriteCallback(unsigned int address, unsigned int value, void
|
||||||
{
|
{
|
||||||
QJSValueList args = { address, value };
|
QJSValueList args = { address, value };
|
||||||
|
|
||||||
func->call(args);
|
mem->getScript()->runFunc( *func, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ static void addressExecCallback(unsigned int address, unsigned int value, void *
|
||||||
{
|
{
|
||||||
QJSValueList args = { address, value };
|
QJSValueList args = { address, value };
|
||||||
|
|
||||||
func->call(args);
|
mem->getScript()->runFunc( *func, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,6 +699,11 @@ void QtScriptInstance::shutdownEngine()
|
||||||
delete onScriptStopCallback;
|
delete onScriptStopCallback;
|
||||||
onScriptStopCallback = nullptr;
|
onScriptStopCallback = nullptr;
|
||||||
}
|
}
|
||||||
|
if (onGuiUpdateCallback != nullptr)
|
||||||
|
{
|
||||||
|
delete onGuiUpdateCallback;
|
||||||
|
onGuiUpdateCallback = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (engine != nullptr)
|
if (engine != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -849,7 +854,7 @@ void QtScriptInstance::loadUI(const QString& uiFilePath)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void QtScriptInstance::registerBefore(const QJSValue& func)
|
void QtScriptInstance::registerBeforeEmuFrame(const QJSValue& func)
|
||||||
{
|
{
|
||||||
if (onFrameBeginCallback != nullptr)
|
if (onFrameBeginCallback != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -858,7 +863,7 @@ void QtScriptInstance::registerBefore(const QJSValue& func)
|
||||||
onFrameBeginCallback = new QJSValue(func);
|
onFrameBeginCallback = new QJSValue(func);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void QtScriptInstance::registerAfter(const QJSValue& func)
|
void QtScriptInstance::registerAfterEmuFrame(const QJSValue& func)
|
||||||
{
|
{
|
||||||
if (onFrameFinishCallback != nullptr)
|
if (onFrameFinishCallback != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -876,6 +881,15 @@ void QtScriptInstance::registerStop(const QJSValue& func)
|
||||||
onScriptStopCallback = new QJSValue(func);
|
onScriptStopCallback = new QJSValue(func);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
void QtScriptInstance::registerGuiUpdate(const QJSValue& func)
|
||||||
|
{
|
||||||
|
if (onGuiUpdateCallback != nullptr)
|
||||||
|
{
|
||||||
|
delete onGuiUpdateCallback;
|
||||||
|
}
|
||||||
|
onGuiUpdateCallback = new QJSValue(func);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
void QtScriptInstance::print(const QString& msg)
|
void QtScriptInstance::print(const QString& msg)
|
||||||
{
|
{
|
||||||
if (dialog)
|
if (dialog)
|
||||||
|
@ -933,6 +947,26 @@ void QtScriptInstance::printSymbols(QJSValue& val, int iter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
int QtScriptInstance::runFunc(QJSValue &func, const QJSValueList& args)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
auto state = getExecutionState();
|
||||||
|
|
||||||
|
state->start();
|
||||||
|
|
||||||
|
QJSValue callResult = func.call(args);
|
||||||
|
|
||||||
|
state->stop();
|
||||||
|
|
||||||
|
if (callResult.isError())
|
||||||
|
{
|
||||||
|
retval = -1;
|
||||||
|
running = false;
|
||||||
|
print(callResult.toString());
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
int QtScriptInstance::call(const QString& funcName, const QJSValueList& args)
|
int QtScriptInstance::call(const QString& funcName, const QJSValueList& args)
|
||||||
{
|
{
|
||||||
if (engine == nullptr)
|
if (engine == nullptr)
|
||||||
|
@ -947,19 +981,10 @@ int QtScriptInstance::call(const QString& funcName, const QJSValueList& args)
|
||||||
QJSValue func = engine->globalObject().property(funcName);
|
QJSValue func = engine->globalObject().property(funcName);
|
||||||
|
|
||||||
FCEU_WRAPPER_LOCK();
|
FCEU_WRAPPER_LOCK();
|
||||||
QJSValue callResult = func.call(args);
|
int retval = runFunc(func, args);
|
||||||
FCEU_WRAPPER_UNLOCK();
|
FCEU_WRAPPER_UNLOCK();
|
||||||
|
|
||||||
if (callResult.isError())
|
return retval;
|
||||||
{
|
|
||||||
print(callResult.toString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//printf("Script Call Success!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void QtScriptInstance::stopRunning()
|
void QtScriptInstance::stopRunning()
|
||||||
|
@ -969,12 +994,7 @@ void QtScriptInstance::stopRunning()
|
||||||
{
|
{
|
||||||
if (onScriptStopCallback != nullptr && onScriptStopCallback->isCallable())
|
if (onScriptStopCallback != nullptr && onScriptStopCallback->isCallable())
|
||||||
{
|
{
|
||||||
QJSValue callResult = onScriptStopCallback->call();
|
runFunc( *onScriptStopCallback );
|
||||||
|
|
||||||
if (callResult.isError())
|
|
||||||
{
|
|
||||||
print(callResult.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
running = false;
|
running = false;
|
||||||
|
|
||||||
|
@ -987,13 +1007,7 @@ void QtScriptInstance::onFrameBegin()
|
||||||
{
|
{
|
||||||
if (running && onFrameBeginCallback != nullptr && onFrameBeginCallback->isCallable())
|
if (running && onFrameBeginCallback != nullptr && onFrameBeginCallback->isCallable())
|
||||||
{
|
{
|
||||||
QJSValue callResult = onFrameBeginCallback->call();
|
runFunc( *onFrameBeginCallback );
|
||||||
|
|
||||||
if (callResult.isError())
|
|
||||||
{
|
|
||||||
print(callResult.toString());
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
@ -1001,14 +1015,59 @@ void QtScriptInstance::onFrameFinish()
|
||||||
{
|
{
|
||||||
if (running && onFrameFinishCallback != nullptr && onFrameFinishCallback->isCallable())
|
if (running && onFrameFinishCallback != nullptr && onFrameFinishCallback->isCallable())
|
||||||
{
|
{
|
||||||
QJSValue callResult = onFrameFinishCallback->call();
|
runFunc( *onFrameFinishCallback );
|
||||||
|
}
|
||||||
if (callResult.isError())
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
void QtScriptInstance::onGuiUpdate()
|
||||||
{
|
{
|
||||||
print(callResult.toString());
|
if (running && onGuiUpdateCallback != nullptr && onGuiUpdateCallback->isCallable())
|
||||||
running = false;
|
{
|
||||||
|
runFunc( *onGuiUpdateCallback );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
ScriptExecutionState* QtScriptInstance::getExecutionState()
|
||||||
|
{
|
||||||
|
ScriptExecutionState* state;
|
||||||
|
|
||||||
|
if (onEmulationThread())
|
||||||
|
{
|
||||||
|
state = &emuFuncState;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = &guiFuncState;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
void QtScriptInstance::checkForHang()
|
||||||
|
{
|
||||||
|
static constexpr uint64_t funcTimeoutMs = 1000;
|
||||||
|
|
||||||
|
if ( guiFuncState.isRunning() )
|
||||||
|
{
|
||||||
|
uint64_t timeRunningMs = guiFuncState.timeRunning();
|
||||||
|
|
||||||
|
if (timeRunningMs > funcTimeoutMs)
|
||||||
|
{
|
||||||
|
printf("Interrupted GUI Thread Script Function\n");
|
||||||
|
engine->setInterrupted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( emuFuncState.isRunning() )
|
||||||
|
{
|
||||||
|
uint64_t timeRunningMs = emuFuncState.timeRunning();
|
||||||
|
|
||||||
|
if (timeRunningMs > funcTimeoutMs)
|
||||||
|
{
|
||||||
|
printf("Interrupted Emulation Thread Script Function\n");
|
||||||
|
engine->setInterrupted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
QString QtScriptInstance::openFileBrowser(const QString& initialPath)
|
QString QtScriptInstance::openFileBrowser(const QString& initialPath)
|
||||||
|
@ -1069,10 +1128,19 @@ QtScriptManager::QtScriptManager(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
_instance = this;
|
_instance = this;
|
||||||
|
monitorThread = new ScriptMonitorThread_t();
|
||||||
|
monitorThread->start();
|
||||||
|
|
||||||
|
periodicUpdateTimer = new QTimer(this);
|
||||||
|
connect( periodicUpdateTimer, &QTimer::timeout, this, &QtScriptManager::guiUpdate );
|
||||||
|
periodicUpdateTimer->start(50); // ~20hz
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
QtScriptManager::~QtScriptManager()
|
QtScriptManager::~QtScriptManager()
|
||||||
{
|
{
|
||||||
|
monitorThread->requestInterruption();
|
||||||
|
monitorThread->wait();
|
||||||
|
|
||||||
_instance = nullptr;
|
_instance = nullptr;
|
||||||
//printf("QtScriptManager destroyed\n");
|
//printf("QtScriptManager destroyed\n");
|
||||||
}
|
}
|
||||||
|
@ -1096,11 +1164,13 @@ void QtScriptManager::destroy(void)
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void QtScriptManager::addScriptInstance(QtScriptInstance* script)
|
void QtScriptManager::addScriptInstance(QtScriptInstance* script)
|
||||||
{
|
{
|
||||||
|
FCEU::autoScopedLock autoLock(scriptListMutex);
|
||||||
scriptList.push_back(script);
|
scriptList.push_back(script);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
void QtScriptManager::removeScriptInstance(QtScriptInstance* script)
|
void QtScriptManager::removeScriptInstance(QtScriptInstance* script)
|
||||||
{
|
{
|
||||||
|
FCEU::autoScopedLock autoLock(scriptListMutex);
|
||||||
auto it = scriptList.begin();
|
auto it = scriptList.begin();
|
||||||
|
|
||||||
while (it != scriptList.end())
|
while (it != scriptList.end())
|
||||||
|
@ -1136,6 +1206,41 @@ void QtScriptManager::frameFinishedUpdate()
|
||||||
FCEU_WRAPPER_UNLOCK();
|
FCEU_WRAPPER_UNLOCK();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
void QtScriptManager::guiUpdate()
|
||||||
|
{
|
||||||
|
FCEU_WRAPPER_LOCK();
|
||||||
|
for (auto script : scriptList)
|
||||||
|
{
|
||||||
|
script->onGuiUpdate();
|
||||||
|
}
|
||||||
|
FCEU_WRAPPER_UNLOCK();
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
//---- Qt Script Monitor Thread
|
||||||
|
//----------------------------------------------------
|
||||||
|
ScriptMonitorThread_t::ScriptMonitorThread_t(QObject *parent)
|
||||||
|
: QThread(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
|
void ScriptMonitorThread_t::run()
|
||||||
|
{
|
||||||
|
//printf("Script Monitor Thread is Running...\n");
|
||||||
|
QtScriptManager* manager = QtScriptManager::getInstance();
|
||||||
|
|
||||||
|
while (!isInterruptionRequested())
|
||||||
|
{
|
||||||
|
manager->scriptListMutex.lock();
|
||||||
|
for (auto script : manager->scriptList)
|
||||||
|
{
|
||||||
|
script->checkForHang();
|
||||||
|
}
|
||||||
|
manager->scriptListMutex.unlock();
|
||||||
|
msleep(100);
|
||||||
|
}
|
||||||
|
//printf("Script Monitor Thread is Stopping...\n");
|
||||||
|
}
|
||||||
|
//----------------------------------------------------
|
||||||
//---- Qt Script Dialog Window
|
//---- Qt Script Dialog Window
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
QScriptDialog_t::QScriptDialog_t(QWidget *parent)
|
QScriptDialog_t::QScriptDialog_t(QWidget *parent)
|
||||||
|
|
|
@ -26,8 +26,10 @@
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
#include <QJSEngine>
|
#include <QJSEngine>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include "Qt/main.h"
|
#include "Qt/main.h"
|
||||||
|
#include "utils/mutex.h"
|
||||||
#include "utils/timeStamp.h"
|
#include "utils/timeStamp.h"
|
||||||
|
|
||||||
class QScriptDialog_t;
|
class QScriptDialog_t;
|
||||||
|
@ -85,13 +87,13 @@ public slots:
|
||||||
Q_INVOKABLE void pause();
|
Q_INVOKABLE void pause();
|
||||||
Q_INVOKABLE void unpause();
|
Q_INVOKABLE void unpause();
|
||||||
Q_INVOKABLE bool paused();
|
Q_INVOKABLE bool paused();
|
||||||
Q_INVOKABLE int framecount();
|
Q_INVOKABLE int frameCount();
|
||||||
Q_INVOKABLE int lagcount();
|
Q_INVOKABLE int lagCount();
|
||||||
Q_INVOKABLE bool lagged();
|
Q_INVOKABLE bool lagged();
|
||||||
Q_INVOKABLE void setlagflag(bool flag);
|
Q_INVOKABLE void setLagFlag(bool flag);
|
||||||
Q_INVOKABLE bool emulating();
|
Q_INVOKABLE bool emulating();
|
||||||
Q_INVOKABLE void registerBefore(const QJSValue& func);
|
Q_INVOKABLE void registerBeforeFrame(const QJSValue& func);
|
||||||
Q_INVOKABLE void registerAfter(const QJSValue& func);
|
Q_INVOKABLE void registerAfterFrame(const QJSValue& func);
|
||||||
Q_INVOKABLE void registerStop(const QJSValue& func);
|
Q_INVOKABLE void registerStop(const QJSValue& func);
|
||||||
Q_INVOKABLE void message(const QString& msg);
|
Q_INVOKABLE void message(const QString& msg);
|
||||||
Q_INVOKABLE void speedMode(const QString& mode);
|
Q_INVOKABLE void speedMode(const QString& mode);
|
||||||
|
@ -113,6 +115,7 @@ public:
|
||||||
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
|
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
QtScriptInstance* getScript(){ return script; }
|
||||||
QJSValue* getReadFunc(int address) { return readFunc[address]; }
|
QJSValue* getReadFunc(int address) { return readFunc[address]; }
|
||||||
QJSValue* getWriteFunc(int address) { return writeFunc[address]; }
|
QJSValue* getWriteFunc(int address) { return writeFunc[address]; }
|
||||||
QJSValue* getExecFunc(int address) { return execFunc[address]; }
|
QJSValue* getExecFunc(int address) { return execFunc[address]; }
|
||||||
|
@ -161,6 +164,36 @@ public slots:
|
||||||
};
|
};
|
||||||
} // JS
|
} // JS
|
||||||
|
|
||||||
|
class ScriptExecutionState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
startTime.readNew();
|
||||||
|
executing = true;
|
||||||
|
}
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
executing = false;
|
||||||
|
}
|
||||||
|
bool isRunning(){ return executing; }
|
||||||
|
|
||||||
|
uint64_t timeRunning()
|
||||||
|
{
|
||||||
|
FCEU::timeStampRecord now, diff;
|
||||||
|
|
||||||
|
now.readNew();
|
||||||
|
|
||||||
|
diff = now - startTime;
|
||||||
|
|
||||||
|
return diff.toMilliSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool executing = false;
|
||||||
|
FCEU::timeStampRecord startTime;
|
||||||
|
};
|
||||||
|
|
||||||
class QtScriptInstance : public QObject
|
class QtScriptInstance : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -177,6 +210,9 @@ public:
|
||||||
int call(const QString& funcName, const QJSValueList& args = QJSValueList());
|
int call(const QString& funcName, const QJSValueList& args = QJSValueList());
|
||||||
void onFrameBegin();
|
void onFrameBegin();
|
||||||
void onFrameFinish();
|
void onFrameFinish();
|
||||||
|
void onGuiUpdate();
|
||||||
|
void checkForHang();
|
||||||
|
int runFunc(QJSValue &func, const QJSValueList& args = QJSValueList());
|
||||||
|
|
||||||
int throwError(QJSValue::ErrorType errorType, const QString &message = QString());
|
int throwError(QJSValue::ErrorType errorType, const QString &message = QString());
|
||||||
|
|
||||||
|
@ -189,6 +225,8 @@ private:
|
||||||
void printSymbols(QJSValue& val, int iter = 0);
|
void printSymbols(QJSValue& val, int iter = 0);
|
||||||
void loadObjectChildren(QJSValue& jsObject, QObject* obj);
|
void loadObjectChildren(QJSValue& jsObject, QObject* obj);
|
||||||
|
|
||||||
|
ScriptExecutionState* getExecutionState();
|
||||||
|
|
||||||
QJSEngine* engine = nullptr;
|
QJSEngine* engine = nullptr;
|
||||||
QScriptDialog_t* dialog = nullptr;
|
QScriptDialog_t* dialog = nullptr;
|
||||||
JS::EmuScriptObject* emu = nullptr;
|
JS::EmuScriptObject* emu = nullptr;
|
||||||
|
@ -197,19 +235,34 @@ private:
|
||||||
QJSValue *onFrameBeginCallback = nullptr;
|
QJSValue *onFrameBeginCallback = nullptr;
|
||||||
QJSValue *onFrameFinishCallback = nullptr;
|
QJSValue *onFrameFinishCallback = nullptr;
|
||||||
QJSValue *onScriptStopCallback = nullptr;
|
QJSValue *onScriptStopCallback = nullptr;
|
||||||
|
QJSValue *onGuiUpdateCallback = nullptr;
|
||||||
|
ScriptExecutionState guiFuncState;
|
||||||
|
ScriptExecutionState emuFuncState;
|
||||||
bool running = false;
|
bool running = false;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_INVOKABLE void print(const QString& msg);
|
Q_INVOKABLE void print(const QString& msg);
|
||||||
Q_INVOKABLE void loadUI(const QString& uiFilePath);
|
Q_INVOKABLE void loadUI(const QString& uiFilePath);
|
||||||
Q_INVOKABLE QString openFileBrowser(const QString& initialPath = QString());
|
Q_INVOKABLE QString openFileBrowser(const QString& initialPath = QString());
|
||||||
Q_INVOKABLE void registerBefore(const QJSValue& func);
|
Q_INVOKABLE void registerBeforeEmuFrame(const QJSValue& func);
|
||||||
Q_INVOKABLE void registerAfter(const QJSValue& func);
|
Q_INVOKABLE void registerAfterEmuFrame(const QJSValue& func);
|
||||||
Q_INVOKABLE void registerStop(const QJSValue& func);
|
Q_INVOKABLE void registerStop(const QJSValue& func);
|
||||||
|
Q_INVOKABLE void registerGuiUpdate(const QJSValue& func);
|
||||||
Q_INVOKABLE bool onGuiThread();
|
Q_INVOKABLE bool onGuiThread();
|
||||||
Q_INVOKABLE bool onEmulationThread();
|
Q_INVOKABLE bool onEmulationThread();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScriptMonitorThread_t : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run( void ) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptMonitorThread_t( QObject *parent = 0 );
|
||||||
|
};
|
||||||
|
|
||||||
class QtScriptManager : public QObject
|
class QtScriptManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -228,12 +281,17 @@ public:
|
||||||
private:
|
private:
|
||||||
static QtScriptManager* _instance;
|
static QtScriptManager* _instance;
|
||||||
|
|
||||||
|
FCEU::mutex scriptListMutex;
|
||||||
QList<QtScriptInstance*> scriptList;
|
QList<QtScriptInstance*> scriptList;
|
||||||
FCEU::timeStampRecord lastFrameUpdate;
|
QTimer *periodicUpdateTimer = nullptr;
|
||||||
|
ScriptMonitorThread_t *monitorThread = nullptr;
|
||||||
|
|
||||||
|
friend class ScriptMonitorThread_t;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void frameBeginUpdate();
|
void frameBeginUpdate();
|
||||||
void frameFinishedUpdate();
|
void frameFinishedUpdate();
|
||||||
|
void guiUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsPropertyItem : public QTreeWidgetItem
|
class JsPropertyItem : public QTreeWidgetItem
|
||||||
|
|
Loading…
Reference in New Issue