Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate legacy controller system to QJSEngine #2682

Merged
merged 169 commits into from
Jun 14, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
169 commits
Select commit Hold shift + click to select a range
e2441bd
Replace QtScript classes with QtQml script classes
ferranpujolcamins Mar 25, 2018
8e21856
Move controllerengine files into new engine subfolder
ferranpujolcamins Aug 18, 2018
3bf236a
Expose Controller and ControllerEngine scripting apis through a proxy
ferranpujolcamins Aug 18, 2018
08dd110
Add checks for JS engine evaluation errors
ferranpujolcamins Aug 19, 2018
6ddae3d
Remove unused evaluate slot in ControllerEngine
ferranpujolcamins Aug 19, 2018
9b3b28f
Refactor exceptions
ferranpujolcamins Aug 19, 2018
50f8059
Add nullengine exception handling
ferranpujolcamins Aug 20, 2018
2b14555
Fix tests build
ferranpujolcamins Aug 30, 2018
a3475d8
Add controller script name to assertion message
ferranpujolcamins Aug 30, 2018
9009fc9
Fix script error not displaying file name
ferranpujolcamins Aug 30, 2018
d7b6811
Remove comment
ferranpujolcamins Aug 30, 2018
6bd1f15
Adapt hid devices to new JS Engine
ferranpujolcamins Sep 1, 2018
4047bf8
Add QtQml dependency to travis config file
ferranpujolcamins Sep 3, 2018
5ed5280
Update comments
ferranpujolcamins Sep 3, 2018
b3380ba
Remove QScriptEngineDebugger from SkinContext
ferranpujolcamins Sep 3, 2018
6274220
Components: use Function.prototype.bind for QJSEngine
Be-ing Nov 22, 2018
ed4b00c
Xone K2: use Function.prototype.bind for QJSEngine
Be-ing Nov 22, 2018
ccbc73c
Hercules P32: use Function.prototype.bind for QJSEngine
Be-ing Nov 22, 2018
eb06da4
Add comment to depends.py
ferranpujolcamins Nov 24, 2018
1200db3
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Nov 25, 2018
9143bb3
Add missing file to depends.py
ferranpujolcamins Nov 25, 2018
7c65f81
Fix usage of deprecated parameter
ferranpujolcamins Nov 25, 2018
c34427d
Replace checks with VERIFY_OR_DEBUG_ASSERT
ferranpujolcamins Nov 25, 2018
630c781
Replace tabs with spaces
ferranpujolcamins Nov 25, 2018
da214be
Rename ControllerEngine member
ferranpujolcamins Nov 25, 2018
4bee8ab
Replace tabs with spaces
ferranpujolcamins Nov 25, 2018
98818df
Rename function in ControllerEngine
ferranpujolcamins Nov 25, 2018
86efb47
Rename variable
ferranpujolcamins Nov 25, 2018
b69b9b9
Improve comments
ferranpujolcamins Nov 25, 2018
cf40beb
Rename method in ControllerEngine
ferranpujolcamins Nov 25, 2018
d572eb1
Let subclasses of Controller provide custom JS api
ferranpujolcamins Nov 25, 2018
8521131
Remove redundant warning
ferranpujolcamins Nov 25, 2018
d9013e8
Replace tabs with spaces
ferranpujolcamins Nov 25, 2018
85b7855
Rename MidiController member
ferranpujolcamins Nov 27, 2018
d6d86e8
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Nov 27, 2018
bd58277
Add missing Q_OBJECT macro
Be-ing Nov 27, 2018
f6291d7
Add missing Q_OBJECT macro
Be-ing Nov 27, 2018
6f5dfd2
Add HidControllerJSProxy
ferranpujolcamins Nov 27, 2018
e8e25a4
Make Controller::send virtual
ferranpujolcamins Nov 27, 2018
70b16f7
Remove unused method of ControllerEngine
ferranpujolcamins Nov 27, 2018
a353c34
Centralise script evaluation handling
ferranpujolcamins Nov 29, 2018
06ad456
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Nov 29, 2018
8da5220
Remove close button from script error dialog
ferranpujolcamins Nov 29, 2018
e804155
Fix the retry button of the script error dialog
ferranpujolcamins Nov 29, 2018
ad2e814
Fix typo in comment
Pegasus-RPG Nov 29, 2018
11c7508
Revert renaming of send(QByteArray) to sendByteArray
ferranpujolcamins Nov 29, 2018
ca59d2d
Fix method hiding warning in FakeController
ferranpujolcamins Nov 29, 2018
3053d2e
Fix connectionExecutesWithCorrectThisObject test
ferranpujolcamins Nov 29, 2018
fb54489
Check precondition of showScriptExceptionDialog(QJSValue)
ferranpujolcamins Nov 29, 2018
77d2372
Add warnings when m_pScriptEngine is null
ferranpujolcamins Nov 29, 2018
733e7b0
Revert "Add warnings when m_pScriptEngine is null"
ferranpujolcamins Nov 30, 2018
c0c3268
Rename evaluateProgram to evaluateCodeString
Nov 30, 2018
1170b0b
Add missing override
Nov 30, 2018
a003f1f
Delete ControllerEngine::isReady()
Nov 30, 2018
2cfa4bc
Merge pull request #5 from Be-ing/update_scripts_for_qjsengine
ferranpujolcamins Dec 1, 2018
0ab3fee
showScriptExceptionDialog inside evaluateCodeString
ferranpujolcamins Dec 1, 2018
907d9df
Rename internalExecute and remove execute methods
ferranpujolcamins Dec 1, 2018
17cb8eb
Remove internalExecute methods
ferranpujolcamins Dec 1, 2018
183eb08
Update comments
ferranpujolcamins Dec 1, 2018
70ed3c9
Fix log message
ferranpujolcamins Dec 1, 2018
e0295ad
Add script error dialog on executeFunction and ScriptConnection
ferranpujolcamins Dec 2, 2018
3337dfd
Remove controllerengineexceptions.h
ferranpujolcamins Dec 2, 2018
aa28540
Don't open new error dialogs when there's already one
ferranpujolcamins Dec 2, 2018
80263a9
Rename variable
ferranpujolcamins Dec 8, 2018
075664d
Evaluate timer callback strings on beginTimer
ferranpujolcamins Dec 8, 2018
bd2185a
Avoid recalculation of m_byteArrayToScriptValueJSFunction
ferranpujolcamins Dec 8, 2018
4fa82f7
Remove m_bPopups
ferranpujolcamins Dec 8, 2018
b57ef7b
Add missing function in header file
ferranpujolcamins Dec 8, 2018
49e01ed
Fix controller scripts
ferranpujolcamins Dec 8, 2018
2deded5
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Dec 8, 2018
f2f04d2
Patch novation launchpad generated scripts
ferranpujolcamins Dec 8, 2018
90d6770
Add QtQml to linux appveyor config
ferranpujolcamins Dec 9, 2018
ecedd59
remove 'use strict' from Novation Launchpad scripts
Be-ing Dec 28, 2018
a4c198b
Components.js: remove dependency on Lodash
Be-ing Dec 28, 2018
c2ebe26
Merge remote-tracking branch 'upstream/master' into qjsengine_migration
Be-ing Dec 28, 2018
28497ba
remove controller scripts' dependency on Lodash
Be-ing Dec 28, 2018
fa6393b
remove Lodash
Be-ing Dec 28, 2018
99f9f36
Merge pull request #6 from Be-ing/qjsengine_migration
ferranpujolcamins Dec 28, 2018
619b1df
Throw QJSEngine exceptions on evaluation failure of callbacks
ferranpujolcamins Dec 19, 2018
4e1d544
Remove warning in ControllerEngine
ferranpujolcamins Dec 28, 2018
454d1ed
Improve ControllerEngine error messages
ferranpujolcamins Dec 28, 2018
6740331
make ControllerEngine throw an errorr on faulty makeConnection callback
ferranpujolcamins Dec 28, 2018
d3c5f65
make ControllerEngine throw an errorr on faulty makeConnection callback
ferranpujolcamins Dec 28, 2018
11f4be3
Fix build error in ControllerEngine
ferranpujolcamins Dec 28, 2018
ac6b3ba
Display controller name on ControllerEngine script error dialog
ferranpujolcamins Dec 28, 2018
8906c5d
Correct message on ControllerEngine script error dialog
ferranpujolcamins Dec 28, 2018
b845529
Improve ControllerEngine error message on callbacks
ferranpujolcamins Dec 29, 2018
191ce6f
use function pointers for Qt connections in ControllerEngine
Be-ing Dec 29, 2018
bb885fb
Merge pull request #7 from Be-ing/qjsengine_migration
ferranpujolcamins Dec 29, 2018
2d2bac7
Add alternative to QJSEngine::throwError for QT < 5.12.0
ferranpujolcamins Dec 30, 2018
9158b50
Check presets for compatibility with ControllerEngine version
ferranpujolcamins Dec 30, 2018
3a00f84
Correct engine version
ferranpujolcamins Dec 30, 2018
76f4b77
Revert "remove Lodash"
ferranpujolcamins Dec 31, 2018
e14c247
Revert "remove controller scripts' dependency on Lodash"
ferranpujolcamins Dec 31, 2018
996df30
Revert "Components.js: remove dependency on Lodash"
ferranpujolcamins Dec 31, 2018
8eeb00f
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Dec 31, 2018
de53702
Add comment on ControllerEngine version
ferranpujolcamins Dec 31, 2018
c7dd4db
Disable apply and accept buttons when loading an incompatible mapping
ferranpujolcamins Jan 2, 2019
059e6a3
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jan 6, 2019
3ca5bfd
Disconnect DlgPreferences::changePage before deleting controller dele…
ferranpujolcamins Jan 6, 2019
c1d34f9
Replace Qt foreach macro with standard C++11 for loop
ferranpujolcamins Jan 6, 2019
299fcfd
Use new signals and slots syntax in DlgPrefControllers
ferranpujolcamins Jan 7, 2019
98ffee1
Hide unsupported mapping warning when controller is disabled
ferranpujolcamins Jan 7, 2019
9058f5f
Mixtrack Platinum: use Function.prototype.bind for QJSEngine
Be-ing Jan 7, 2019
718f971
Numark N4: use Function.prototype.bind for QJSEngine
Be-ing Jan 7, 2019
8bd4ad9
Pioneer DDJ-SB2: use Function.prototype.bind for QJSEngine
Be-ing Jan 7, 2019
72cd1ca
fix script validation tests failing with nonexistent COs
Be-ing Jan 7, 2019
a7a7bdb
Add FakeControllerJSProxy
Be-ing Jan 7, 2019
e5916c1
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jan 11, 2019
d5a980e
Fix beginTimer trying to evaluate the result of an evaluation
ferranpujolcamins Jan 11, 2019
e622a07
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jan 22, 2019
cc13e7c
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Feb 17, 2019
60ac314
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Feb 17, 2019
431c40a
Fix merge and simplify tests
ferranpujolcamins Feb 17, 2019
1df12b1
add bundles
dszakallas Feb 27, 2019
276f0dc
add sources
dszakallas Feb 27, 2019
f2610e3
Merge pull request #10 from dszakallas/upgrade-lp
ferranpujolcamins Mar 2, 2019
c86cc16
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jun 8, 2019
ab78036
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jun 8, 2019
db6aadc
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jun 21, 2019
e1a1b71
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jun 24, 2019
803d1cb
Remove mixco based controlelr scripts
ferranpujolcamins Jun 24, 2019
eb62363
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jun 27, 2019
2c4936a
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Oct 23, 2019
0f50ff6
Format code
ferranpujolcamins Oct 23, 2019
a17bdf8
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jan 19, 2020
9cdf435
Merge branch 'master' into migrate-to-QJSEngine
ferranpujolcamins Jan 19, 2020
155f066
Merge branch 'master' into migrate-to-QJSEngine
Mar 27, 2020
cfc4142
Merge branch 'master' into migrate-to-QJSEngine
Mar 27, 2020
e122b79
controllers/bulk: Fix BulkController constructor
Holzhaus Apr 9, 2020
97d5623
Merge pull request #15 from Holzhaus/bulk-controller-fix
ferranpujolcamins Apr 12, 2020
381214a
Fix wrong file path in scons
ferranpujolcamins Apr 12, 2020
9b658d1
Merge branch 'master' of github.com:mixxxdj/mixxx into migrate-to-QJS…
Holzhaus Apr 9, 2020
863b59c
Merge branch 'migrate-to-QJSEngine' of https://github.com/ferranpujol…
Holzhaus Apr 18, 2020
e5984a6
Merge branch 'master' of github.com:mixxxdj/mixxx into migrate-to-QJS…
Holzhaus Apr 18, 2020
a99fd38
ColorMapper(JSProxy): port to QJSEngine/QJSValue API
Be-ing Apr 19, 2020
7949bc6
MidiControllerPreset/HidControllerPreset: add missing 'override's
Be-ing Apr 19, 2020
7e47924
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing Apr 19, 2020
b65729e
ControllerMapperJSProxyTest: remove tests we can't test anymore
Be-ing Apr 19, 2020
bfbed64
ControllerMapperJSProxy: prevent segfault with default constructor
Be-ing Apr 19, 2020
2aa0433
controllers: allow scripts to work without XML mappings
Be-ing Apr 19, 2020
2068ce6
MidiControllerTest: fix segfault
Be-ing Apr 19, 2020
5b6bea1
ColorMapperJSProxy: remove hack for string-indexed maps
Be-ing Apr 19, 2020
44f11ef
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing Apr 22, 2020
082908f
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing Apr 25, 2020
3970b4e
Revert "controllers: allow scripts to work without XML mappings"
Be-ing Apr 25, 2020
00feedc
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 7, 2020
4b297dd
Roland DJ 505: use Function.prototype.bind for QJSEngine
Be-ing May 7, 2020
cb3c6f0
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 12, 2020
1cbcaf7
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 19, 2020
e1896f8
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 20, 2020
3130882
controllers: assorted code cleanup
Be-ing May 22, 2020
4b43d25
ControllerEngine: assorted code cleanup
Be-ing May 22, 2020
ec1d9aa
remove "controller engine version" concept
Be-ing May 22, 2020
68b6330
move ScriptConnection & ScriptConnectionJSProxy to their own files
Be-ing May 22, 2020
98bc040
ControllerEngine: cleaup comments and code formatting
Be-ing May 22, 2020
18aaec7
ControllerEngine: reorganize method order
Be-ing May 22, 2020
1b777b6
disable JS JIT compilation for Qt >= 5.14.0 to work around Qt bug
Be-ing May 27, 2020
4af2051
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 27, 2020
214ae8e
fix SCons build
Be-ing May 20, 2020
ec51aff
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 27, 2020
ccbe088
DlgPrefController: break long line
Be-ing May 27, 2020
48952ad
disable QV4_FORCE_INTERPRETER for Qt 5.15.1
Be-ing May 28, 2020
ca1e353
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing May 28, 2020
469eda7
fix disconnection of ScriptConnectionJSProxy by connectControl
Be-ing May 28, 2020
91bc471
try to fix Hss1394Controller build
Be-ing May 28, 2020
ada0929
Merge remote-tracking branch 'upstream/master' into migrate-to-QJSEngine
Be-ing Jun 6, 2020
d596ded
ColorMapper: fixes from PR #2733
Be-ing Jun 6, 2020
6e96bdb
Components: fix HotcueButton color output
Be-ing Jun 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'master' of github.com:mixxxdj/mixxx into migrate-to-QJS…
…Engine
  • Loading branch information
Holzhaus committed Apr 18, 2020
commit e5984a69282211b3144d087aaf6b6fc41eef0117
10 changes: 5 additions & 5 deletions src/controllers/dlgprefcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ class DlgPrefController : public DlgPreferencePage {
DlgPreferencePage::State state() override;

public slots:
// Called when we should apply / save our changes.
void slotApply() override;
// Called when we should cancel the changes made.
void slotCancel() override;
// Called when preference dialog (not this dialog) is displayed.
/// Called when the preference dialog (not this page) is shown to the user.
void slotUpdate() override;
/// Called when the user clicks the global "Apply" button.
void slotApply() override;
/// Called when the user clicks the global "Reset to Defaults" button.
void slotResetToDefaults() override;

signals:
void applyPreset(Controller* pController, ControllerPresetPointer pPreset, bool bEnabled);
Expand Down
176 changes: 115 additions & 61 deletions src/controllers/engine/controllerengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,25 @@ ControllerEngine::~ControllerEngine() {
m_scratchFilters[i] = nullptr;
}

// Delete the script engine, first clearing the pointer so that
// other threads will not get the dead pointer after we delete it.
if (m_pScriptEngine != nullptr) {
QJSEngine* engine = m_pScriptEngine;
m_pScriptEngine = nullptr;
engine->deleteLater();
}
uninitializeScriptEngine();
}

/* -------- ------------------------------------------------------
Purpose: Calls the same method on a list of JS Objects
Input: -
Output: -
-------- ------------------------------------------------------ */
void ControllerEngine::callFunctionOnObjects(QList<QString> scriptFunctionPrefixes,
bool ControllerEngine::callFunctionOnObjects(QList<QString> scriptFunctionPrefixes,
const QString& function,
QJSValueList args) {
QJSValueList args,
bool bFatalError) {
VERIFY_OR_DEBUG_ASSERT(m_pScriptEngine) {
return false;
}

const QJSValue global = m_pScriptEngine->globalObject();

bool success = true;
for (const QString& prefixName : scriptFunctionPrefixes) {
QJSValue prefix = global.property(prefixName);
if (!prefix.isObject()) {
Expand All @@ -99,9 +99,11 @@ void ControllerEngine::callFunctionOnObjects(QList<QString> scriptFunctionPrefix
controllerDebug("ControllerEngine: Executing" << prefixName << "." << function);
QJSValue result = init.callWithInstance(prefix, args);
if (result.isError()) {
showScriptExceptionDialog(result);
showScriptExceptionDialog(result, bFatalError);
success = false;
}
}
return success;
}

QJSValue ControllerEngine::byteArrayToScriptValue(const QByteArray byteArray) {
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -130,6 +132,12 @@ Output: QJSValue of JS snippet wrapped in an anonymous function
------------------------------------------------------------------- */
QJSValue ControllerEngine::wrapFunctionCode(const QString& codeSnippet,
int numberOfArgs) {
// This function is called from outside the controller engine, so we can't
// use VERIFY_OR_DEBUG_ASSERT here
if (m_pScriptEngine == nullptr) {
return QJSValue();
}

QJSValue wrappedFunction;

auto i = m_scriptWrappedFunctionCache.constFind(codeSnippet);
Expand Down Expand Up @@ -160,7 +168,7 @@ Input: -
Output: -
-------- ------------------------------------------------------ */
void ControllerEngine::gracefulShutdown() {
if (m_pEngine == nullptr) {
if (m_pScriptEngine == nullptr) {
return;
}

Expand Down Expand Up @@ -203,8 +211,9 @@ void ControllerEngine::gracefulShutdown() {
}

void ControllerEngine::initializeScriptEngine() {
// Clear any errors from previous script engine usages
m_scriptErrors.clear();
VERIFY_OR_DEBUG_ASSERT(!m_pScriptEngine) {
return;
}

// Create the Script Engine
m_pScriptEngine = new QJSEngine(this);
Expand Down Expand Up @@ -235,9 +244,9 @@ void ControllerEngine::initializeScriptEngine() {
void ControllerEngine::uninitializeScriptEngine() {
// Delete the script engine, first clearing the pointer so that
// other threads will not get the dead pointer after we delete it.
if (m_pEngine != nullptr) {
QScriptEngine* engine = m_pEngine;
m_pEngine = nullptr;
if (m_pScriptEngine != nullptr) {
QJSEngine* engine = m_pScriptEngine;
m_pScriptEngine = nullptr;
engine->deleteLater();
}
}
Expand All @@ -259,8 +268,7 @@ bool ControllerEngine::loadScriptFiles(const QList<ControllerPreset::ScriptFileI

connect(&m_scriptWatcher, &QFileSystemWatcher::fileChanged, this, &ControllerEngine::scriptHasChanged);

bool success = result && m_scriptErrors.isEmpty();
if (!success) {
if (!scriptsEvaluatedCorrectly) {
gracefulShutdown();
uninitializeScriptEngine();
}
Expand All @@ -280,14 +288,7 @@ void ControllerEngine::reloadScripts() {
ControllerPresetPointer pPreset = m_pController->getPreset();

gracefulShutdown();

// Delete the script engine, first clearing the pointer so that
// other threads will not get the dead pointer after we delete it.
if (m_pScriptEngine != nullptr) {
QJSEngine* engine = m_pScriptEngine;
m_pScriptEngine = nullptr;
engine->deleteLater();
}
uninitializeScriptEngine();

initializeScriptEngine();
if (!loadScriptFiles(m_lastScriptFiles)) {
Expand Down Expand Up @@ -318,18 +319,20 @@ void ControllerEngine::initializeScripts(const QList<ControllerPreset::ScriptFil
args << QJSValue(ControllerDebug::enabled());

// Call the init method for all the prefixes.
callFunctionOnObjects(m_scriptFunctionPrefixes, "init", args);
bool success = callFunctionOnObjects(m_scriptFunctionPrefixes, "init", args, true);

// We failed to initialize the controller scripts, shutdown the script
// engine to avoid error popups on every button press or slider move
if (checkException(true)) {
if (!success) {
gracefulShutdown();
uninitializeScriptEngine();
}
}

bool ControllerEngine::executeFunction(QJSValue functionObject, QJSValueList args) {
VERIFY_OR_DEBUG_ASSERT(!(m_pScriptEngine == nullptr)) {
// This function is called from outside the controller engine, so we can't
// use VERIFY_OR_DEBUG_ASSERT here
if (!m_pScriptEngine) {
return false;
}

Expand Down Expand Up @@ -357,7 +360,9 @@ bool ControllerEngine::executeFunction(QJSValue functionObject, QJSValueList arg
}

bool ControllerEngine::executeFunction(QJSValue functionObject, const QByteArray data) {
Be-ing marked this conversation as resolved.
Show resolved Hide resolved
VERIFY_OR_DEBUG_ASSERT(!(m_pScriptEngine == nullptr)) {
// This function is called from outside the controller engine, so we can't
// use VERIFY_OR_DEBUG_ASSERT here
if (!m_pScriptEngine) {
return false;
}
QJSValueList args;
Expand All @@ -379,14 +384,14 @@ void ControllerEngine::throwJSError(const QString& message) {
QString errorText = tr("Uncaught exception: %1").arg(message);
qWarning() << "ControllerEngine:" << errorText;
if (!m_bDisplayingExceptionDialog) {
scriptErrorDialog(errorText);
scriptErrorDialog(errorText, errorText);
}
#else
m_pScriptEngine->throwError(message);
#endif
}

void ControllerEngine::showScriptExceptionDialog(QJSValue evaluationResult) {
void ControllerEngine::showScriptExceptionDialog(QJSValue evaluationResult, bool bFatalError) {
VERIFY_OR_DEBUG_ASSERT(evaluationResult.isError()) {
return;
}
Expand All @@ -396,21 +401,26 @@ void ControllerEngine::showScriptExceptionDialog(QJSValue evaluationResult) {
QString backtrace = evaluationResult.property("stack").toString();
QString filename = evaluationResult.property("fileName").toString();

QString errorText = tr("Uncaught exception at line %1 in file %2: %3")
.arg(line, (filename.isEmpty() ? "" : filename), errorMessage);
QString errorText;
if (filename.isEmpty()) {
errorText = QString("Uncaught exception at line %1 in passed code.").arg(line);
} else {
errorText = QString("Uncaught exception at line %1 in file %2.").arg(line, filename);
}

if (filename.isEmpty())
errorText = tr("Uncaught exception at line %1 in passed code: %2")
.arg(line, errorMessage);
errorText += QStringLiteral("\n\nException:\n ") + errorMessage;

QString detailedError = ControllerDebug::enabled() ? QString("%1\nBacktrace:\n%2")
.arg(errorText, backtrace)
: errorText;
// Do not include backtrace in dialog key because it might contain midi
// slider values that will differ most of the time. This would break
// the "Ignore" feature of the error dialog.
QString key = errorText;
qWarning() << "ControllerEngine:" << errorText;

qWarning() << "ControllerEngine:" << detailedError;
// Add backtrace to the error details
errorText += QStringLiteral("\n\nBacktrace:\n") + backtrace;

if (!m_bDisplayingExceptionDialog) {
scriptErrorDialog(detailedError);
scriptErrorDialog(errorText, key, bFatalError);
}
}

Expand All @@ -420,22 +430,55 @@ void ControllerEngine::showScriptExceptionDialog(QJSValue evaluationResult) {
Input: Detailed error string
Output: -
-------- ------------------------------------------------------ */
void ControllerEngine::scriptErrorDialog(const QString& detailedError) {
ErrorDialogProperties* props = ErrorDialogHandler::instance()->newDialogProperties();
void ControllerEngine::scriptErrorDialog(
const QString& detailedError, const QString& key, bool bFatalError) {
if (m_bTesting) {
return;
}

ErrorDialogProperties* props =
ErrorDialogHandler::instance()->newDialogProperties();

QString additionalErrorText;
if (bFatalError) {
additionalErrorText =
tr("The functionality provided by this controller mapping will "
"be disabled until the issue has been resolved.");
} else {
additionalErrorText =
tr("You can ignore this error for this session but "
"you may experience erratic behavior.") +
QString("<br>") +
tr("Try to recover by resetting your controller.");
}

props->setType(DLG_WARNING);
props->setTitle(tr("Controller script error"));
props->setText(tr("The mapping for the %1 controller is not working properly.").arg(m_pController->getName()));
props->setInfoText("<html>" + tr("The script code needs to be fixed.") +
"<p>" + tr("For now, you can: Ignore this error for this session but you may experience erratic behavior.") +
"<br>" + tr("Try to recover by resetting your controller.") + "</p>" + "</html>");
props->setDetails(detailedError);
props->setKey(detailedError); // To prevent multiple windows for the same error
props->setTitle(tr("Controller Preset Error"));
props->setText(QString(tr("The preset for your controller \"%1\" is not "
"working properly."))
.arg(m_pController->getName()));
props->setInfoText(QStringLiteral("<html>") +
tr("The script code needs to be fixed.") + QStringLiteral("<p>") +
additionalErrorText + QStringLiteral("</p></html>"));

// Add "Details" text and set monospace font since they may contain
// backtraces and code.
props->setDetails(detailedError, true);

// To prevent multiple windows for the same error
props->setKey(key);

// Allow user to suppress further notifications about this particular error
props->addButton(QMessageBox::Ignore);
props->addButton(QMessageBox::Retry);
props->setDefaultButton(QMessageBox::Ignore);
props->setEscapeButton(QMessageBox::Ignore);
if (!bFatalError) {
props->addButton(QMessageBox::Ignore);
props->addButton(QMessageBox::Retry);
props->setDefaultButton(QMessageBox::Ignore);
props->setEscapeButton(QMessageBox::Ignore);
} else {
props->addButton(QMessageBox::Close);
props->setDefaultButton(QMessageBox::Close);
props->setEscapeButton(QMessageBox::Close);
}
props->setModal(false);

if (ErrorDialogHandler::instance()->requestErrorDialog(props)) {
Expand Down Expand Up @@ -863,7 +906,7 @@ void ControllerEngine::trigger(QString group, QString name) {
Output: false if the script file has errors or doesn't exist
-------- ------------------------------------------------------ */
bool ControllerEngine::evaluateScriptFile(const QFileInfo& scriptFile) {
VERIFY_OR_DEBUG_ASSERT(!(m_pScriptEngine == nullptr)) {
VERIFY_OR_DEBUG_ASSERT(m_pScriptEngine) {
return false;
}

Expand All @@ -884,9 +927,20 @@ bool ControllerEngine::evaluateScriptFile(const QFileInfo& scriptFile) {
// Set up error dialog
ErrorDialogProperties* props = ErrorDialogHandler::instance()->newDialogProperties();
props->setType(DLG_WARNING);
props->setTitle("Controller script file problem");
props->setText(QString("There was a problem opening the controller script file %1.").arg(filename));
props->setInfoText(input.errorString());
props->setTitle(tr("Controller Mapping File Problem"));
props->setText(tr("The mapping for controller \"%1\" cannot be opened.")
.arg(m_pController->getName()));
props->setInfoText(
tr("The functionality provided by this controller mapping will "
"be disabled until the issue has been resolved."));

// We usually don't translate the details field, but the cause of
// this problem lies in the user's system (e.g. a permission
// issue). Translating this will help users to fix the issue even
// when they don't speak english.
props->setDetails(tr("File:") + QStringLiteral(" ") + filename +
QStringLiteral("\n") + tr("Error:") + QStringLiteral(" ") +
input.errorString());

// Ask above layer to display the dialog & handle user response
ErrorDialogHandler::instance()->requestErrorDialog(props);
Expand All @@ -901,7 +955,7 @@ bool ControllerEngine::evaluateScriptFile(const QFileInfo& scriptFile) {
// Evaluate the code
QJSValue scriptFunction = evaluateCodeString(scriptCode, filename);
if (scriptFunction.isError()) {
showScriptExceptionDialog(scriptFunction);
showScriptExceptionDialog(scriptFunction, true);
return false;
}

Expand Down Expand Up @@ -1023,7 +1077,7 @@ bool ControllerEngine::isDeckPlaying(const QString& group) {

if (pPlay == nullptr) {
QString error = QString("Could not getControlObjectScript()");
scriptErrorDialog(error);
scriptErrorDialog(error, error);
return false;
}

Expand Down
11 changes: 6 additions & 5 deletions src/controllers/engine/controllerengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,24 @@ class ControllerEngine : public QObject {
void gracefulShutdown();
void scriptHasChanged(const QString&);

signals:
void initialized();

private slots:
void errorDialogButton(const QString& key, QMessageBox::StandardButton button);

private:
bool evaluateScriptFile(const QFileInfo& scriptFile);
void initializeScriptEngine();
void uninitializeScriptEngine();
void reloadScripts();

void scriptErrorDialog(const QString& detailedError, const QString& key, bool bFatal = false);
void generateScriptFunctions(const QString& code);
// Stops and removes all timers (for shutdown).
void stopAllTimers();

void callFunctionOnObjects(QList<QString>, const QString&, QJSValueList args = QJSValueList());
bool callFunctionOnObjects(QList<QString>,
const QString&,
QJSValueList args = QJSValueList(),
bool bFatalError = false);
// Convert a byteArray to a JS typed array over an ArrayBuffer
QJSValue byteArrayToScriptValue(const QByteArray byteArray);
QJSValue evaluateCodeString(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
Expand All @@ -175,7 +176,7 @@ class ControllerEngine : public QObject {

// Shows a UI dialog notifying of a script evaluation error.
// Precondition: QJSValue.isError() == true
void showScriptExceptionDialog(QJSValue evaluationResult);
void showScriptExceptionDialog(QJSValue evaluationResult, bool bFatal = false);
bool m_bDisplayingExceptionDialog;
QJSEngine* m_pScriptEngine;

Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.