Showing the changes to interface/src/scripting/OSCScriptingInterface.cpp (1 of 4 files). Show all
Unified · Split
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "OSCScriptingInterface.h" |
| 18 | 18 | |
| 19 | 19 | |
| 20 | −Q_LOGGING_CATEGORY(osc, "overte.osc") | |
| 20 | +Q_LOGGING_CATEGORY(osc, "osc") | |
| 21 | 21 | |
| 22 | 22 | enum OSCTag: char { |
| 23 | 23 | Int = 'i', |
| @@ -26,7 +26,7 @@ enum OSCTag: char { · 2 unmodified lines | ||
| 26 | 26 | Blob = 'b', |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | −static const QRegularExpression invalidCharacters = QRegularExpression("([ #*,/?\\[\\]{}])"); | |
| 29 | +static const QRegularExpression invalidCharacters = QRegularExpression("([ #*,?\\[\\]{}])"); | |
| 30 | 30 | static const QMap<QChar, QVariant::Type> typeNameMap = { |
| 31 | 31 | { OSCTag::Int, QVariant::Int }, |
| 32 | 32 | { OSCTag::Float, QVariant::Double }, |
| @@ -35,8 +35,8 @@ static const QMap<QChar, QVariant::Type> typeNameMap = { · 2 unmodified lines | ||
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | 37 | |
| 38 | −OSCScriptingInterface::OSCScriptingInterface(ScriptManager* parent) : | |
| 39 | − _scriptManager(parent), | |
| 38 | +OSCScriptingInterface::OSCScriptingInterface(QObject* parent) : | |
| 39 | + QObject(parent), | |
| 40 | 40 | _receivePort("osc/receivePort", 9000), |
| 41 | 41 | _receiveHost("osc/receiveHost", "127.0.0.1"), |
| 42 | 42 | _sendPort("osc/sendPort", 9001), |
| @@ -63,7 +63,14 @@ void OSCScriptingInterface::receivePacket() { · 20 unmodified lines | ||
| 63 | 63 | void OSCScriptingInterface::sendMessage(const QString& address, const QString &argumentTypes, const QVariantList& arguments) { |
| 64 | 64 | Q_ASSERT(_socket); |
| 65 | 65 | |
| 66 | − auto scriptEngine = _scriptManager->engine(); | |
| 66 | + // FIXME: how do you get the script engine??? | |
| 67 | + struct HackRemoveThis { | |
| 68 | + void raiseException(QString msg) { | |
| 69 | + qCCritical(osc) << msg; | |
| 70 | + } | |
| 71 | + }; | |
| 72 | + | |
| 73 | + auto scriptEngine = std::make_unique<HackRemoveThis>(); //_scriptManager->engine(); | |
| 67 | 74 | |
| 68 | 75 | if (address.length() < 2 || address[0] != '/') { |
| 69 | 76 | scriptEngine->raiseException("address must be at least two characters and start with '/'"); |
| @@ -76,14 +83,19 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 6 unmodified lines | ||
| 76 | 83 | } |
| 77 | 84 | |
| 78 | 85 | if (argumentTypes.length() != arguments.length()) { |
| 79 | − scriptEngine->raiseException(QString("argumentTypes.length (%1) does not match arguments.length (%2)").arg(argumentTypes.length()).arg(argumentTypes.length())); | |
| 86 | + scriptEngine->raiseException(QString("argumentTypes.length (%1) does not match arguments.length (%2)").arg(argumentTypes.length()).arg(arguments.length())); | |
| 80 | 87 | return; |
| 81 | 88 | } |
| 82 | 89 | |
| 90 | + auto pad4 = [](QByteArray& array) { | |
| 91 | + array.append((4 - array.length() % 4) % 4, 0); | |
| 92 | + }; | |
| 93 | + | |
| 83 | 94 | QByteArray bytes = address.toUtf8(); |
| 84 | 95 | |
| 85 | 96 | // pad to 4-byte boundary with at least one zero for the address string |
| 86 | − bytes.append((bytes.length() + 1) % 4, 0); | |
| 97 | + bytes.append('\x00'); | |
| 98 | + pad4(bytes); | |
| 87 | 99 | |
| 88 | 100 | // comma at the start of the argument list, even if empty |
| 89 | 101 | bytes.append(','); |
| @@ -99,19 +111,23 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 9 unmodified lines | ||
| 99 | 111 | } |
| 100 | 112 | |
| 101 | 113 | auto expectedType = typeNameMap[argumentTypes[i]]; |
| 102 | − if (expectedType != arg.type()) { | |
| 114 | + if ( | |
| 115 | + expectedType != arg.type() && | |
| 116 | + // JS doesn't have ints, so allow doubles to be interpreted as ints | |
| 117 | + arg.type() != QVariant::Double | |
| 118 | + ) { | |
| 103 | 119 | scriptEngine->raiseException(QString("Specified argument type '%1' does not match value of type '%2'").arg(QVariant::typeToName(expectedType)).arg(arg.typeName())); |
| 104 | 120 | return; |
| 105 | 121 | } |
| 106 | 122 | |
| 107 | − switch (arg.type()) { | |
| 123 | + switch (expectedType) { | |
| 108 | 124 | case QVariant::Int: { |
| 109 | 125 | bytes.append(OSCTag::Int); |
| 110 | 126 | |
| 111 | 127 | auto* ptr = bodyBytes.data() + bodyBytes.length(); |
| 112 | 128 | bodyBytes.append(4, 0); |
| 113 | 129 | |
| 114 | − qToBigEndian(static_cast<qint32>(arg.toInt()), ptr); | |
| 130 | + qToBigEndian(static_cast<qint32>(arg.toDouble()), ptr); | |
| 115 | 131 | } break; |
| 116 | 132 | |
| 117 | 133 | case QVariant::Double: { |
| @@ -121,7 +137,7 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 3 unmodified lines | ||
| 121 | 137 | bodyBytes.append(4, 0); |
| 122 | 138 | |
| 123 | 139 | // FIXME: use std::bit_cast instead of this hack once c++20 is in |
| 124 | − auto tmp = arg.toFloat(); | |
| 140 | + auto tmp = static_cast<float>(arg.toDouble()); | |
| 125 | 141 | qToBigEndian(*reinterpret_cast<quint32*>(&tmp), ptr); |
| 126 | 142 | } break; |
| 127 | 143 | |
| @@ -136,8 +152,10 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 8 unmodified lines | ||
| 136 | 152 | } |
| 137 | 153 | |
| 138 | 154 | bodyBytes.append(stringArg.toUtf8()); |
| 155 | + | |
| 139 | 156 | // pad to 4-byte boundary with at least one zero for the string |
| 140 | − bodyBytes.append((bodyBytes.length() + 1) % 4, 0); | |
| 157 | + bodyBytes.append('\x00'); | |
| 158 | + pad4(bodyBytes); | |
| 141 | 159 | } break; |
| 142 | 160 | |
| 143 | 161 | case QVariant::ByteArray: { |
| @@ -153,8 +171,8 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 9 unmodified lines | ||
| 153 | 171 | // write body |
| 154 | 172 | bodyBytes.append(bytesArg); |
| 155 | 173 | |
| 156 | − // pad to 4-byte boundary with at least one zero for the string | |
| 157 | − bodyBytes.append((bodyBytes.length() + 1) % 4, 0); | |
| 174 | + // pad to 4-byte boundary | |
| 175 | + pad4(bodyBytes); | |
| 158 | 176 | } break; |
| 159 | 177 | |
| 160 | 178 | // unreachable |
| @@ -164,11 +182,14 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 3 unmodified lines | ||
| 164 | 182 | } |
| 165 | 183 | } |
| 166 | 184 | |
| 167 | − // pad to 4-byte boundary with at least one zero for the argument list string | |
| 168 | − bytes.append((bytes.length() + 1) % 4, 0); | |
| 185 | + // pad argument type string to 4-byte boundary with at least one zero | |
| 186 | + bytes.append('\x00'); | |
| 187 | + pad4(bytes); | |
| 169 | 188 | |
| 170 | 189 | // pack the header + body data together for the datagram |
| 171 | 190 | bytes.append(bodyBytes); |
| 172 | 191 | |
| 173 | 192 | _socket->writeDatagram(bytes, QHostAddress(_sendHost.get()), _sendPort.get()); |
| 193 | + | |
| 194 | + qCDebug(osc) << QHostAddress(_sendHost.get()) << _sendPort.get() << ":" << bytes.toHex(' '); | |
| 174 | 195 | } |