Skip to content
63 changes: 47 additions & 16 deletions src/control/controlobjectscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,71 @@ ControlObjectScript::ControlObjectScript(const ConfigKey& key, QObject* pParent)
: ControlProxy(key, pParent) {
}

void ControlObjectScript::connectScriptFunction(
const ControllerEngineConnection& conn) {
if (m_connectedScriptFunctions.isEmpty()) {
// we connect the slots only, if there will be actually a script
// connected
bool ControlObjectScript::addScriptConnection(const ScriptConnection& conn) {
if (m_scriptConnections.isEmpty()) {
// Only connect the slots when they are actually needed
// by script connections.
connect(m_pControl.data(), SIGNAL(valueChanged(double, QObject*)),
this, SLOT(slotValueChanged(double,QObject*)),
Qt::QueuedConnection);
connect(this, SIGNAL(trigger(double, QObject*)),
this, SLOT(slotValueChanged(double,QObject*)),
Qt::QueuedConnection);
}
m_connectedScriptFunctions.append(conn);

for (const auto& priorConnection: m_scriptConnections) {
if (conn == priorConnection) {
qWarning() << "Connection " + conn.id.toString() +
" already connected to (" +
conn.key.group + ", " + conn.key.item +
"). Ignoring attempt to connect again.";
return false;
}
}

m_scriptConnections.append(conn);
controllerDebug("Connected (" +
conn.key.group + ", " + conn.key.item +
") to connection " + conn.id.toString());
return true;
}

bool ControlObjectScript::disconnectScriptFunction(
const ControllerEngineConnection& conn) {
bool ret = m_connectedScriptFunctions.removeAll(conn) > 0;
if (m_connectedScriptFunctions.isEmpty()) {
// no script left, we can disconnected
void ControlObjectScript::removeScriptConnection(const ScriptConnection& conn) {
bool success = m_scriptConnections.removeOne(conn);
if (success) {
controllerDebug("Disconnected (" +
conn.key.group + ", " + conn.key.item +
") from connection " + conn.id.toString());
} else {
qWarning() << "Failed to disconnect (" +
conn.key.group + ", " + conn.key.item +
") from connection " + conn.id.toString();
}
if (m_scriptConnections.isEmpty()) {
// no ScriptConnections left, so disconnect signals
disconnect(m_pControl.data(), SIGNAL(valueChanged(double, QObject*)),
this, SLOT(slotValueChanged(double,QObject*)));
disconnect(this, SIGNAL(trigger(double, QObject*)),
this, SLOT(slotValueChanged(double,QObject*)));
}
return ret;
}

void ControlObjectScript::disconnectAllConnectionsToFunction(const QScriptValue& function) {
// Make a local copy of m_scriptConnections because items are removed within the loop.
QList<ScriptConnection> connections = m_scriptConnections;
for (const auto& conn: connections) {
if (conn.callback.strictlyEquals(function)) {
removeScriptConnection(conn);
}
}
}

void ControlObjectScript::slotValueChanged(double value, QObject*) {
// Make a local copy of m_connectedScriptFunctions fist.
// This allows a script to disconnect a callback from the callback
// itself. Otherwise the this may crash since the disconnect call
// Make a local copy of m_connectedScriptFunctions first.
// This allows a script to disconnect a callback from inside the
// the callback. Otherwise the this may crash since the disconnect call
// happens during conn.function.call() in the middle of the loop below.
QList<ControllerEngineConnection> connections = m_connectedScriptFunctions;
QList<ScriptConnection> connections = m_scriptConnections;
for (auto&& conn: connections) {
conn.executeCallback(value);
}
Expand Down
17 changes: 11 additions & 6 deletions src/control/controlobjectscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define CONTROLOBJECTSCRIPT_H

#include "controllers/controllerengine.h"

#include "controllers/controllerdebug.h"
#include "control/controlproxy.h"

// this is used for communicate with controller scripts
Expand All @@ -11,11 +11,16 @@ class ControlObjectScript : public ControlProxy {
public:
explicit ControlObjectScript(const ConfigKey& key, QObject* pParent = nullptr);

void connectScriptFunction(
const ControllerEngineConnection& conn);
bool addScriptConnection(const ScriptConnection& conn);

void removeScriptConnection(const ScriptConnection& conn);

bool disconnectScriptFunction(
const ControllerEngineConnection& conn);
// Required for legacy behavior of ControllerEngine::connectControl
inline int countConnections() {
return m_scriptConnections.size(); };
inline ScriptConnection firstConnection() {
return m_scriptConnections.first(); };
void disconnectAllConnectionsToFunction(const QScriptValue& function);

// Called from update();
void emitValueChanged() override {
Expand All @@ -31,7 +36,7 @@ class ControlObjectScript : public ControlProxy {
void slotValueChanged(double v, QObject*);

private:
QList<ControllerEngineConnection> m_connectedScriptFunctions;
QList<ScriptConnection> m_scriptConnections;
};

#endif // CONTROLOBJECTSCRIPT_H
Loading