History

Kinda working OSC packet sending

Ada committed 10 months ago

Commit 81c80e71 parent 2faebb94 files · +46 −20Browse files

Showing the changes to interface/src/scripting/OSCScriptingInterface.cpp (1 of 4 files). Show all

Unified · Split

interface/src/scripting/OSCScriptingInterface.cpp+37−16
@@ -17,7 +17,7 @@ · 16 unmodified lines
17#include "OSCScriptingInterface.h"17#include "OSCScriptingInterface.h"
18 18
19 19
20Q_LOGGING_CATEGORY(osc, "overte.osc")20Q_LOGGING_CATEGORY(osc, "osc")
21 21
22enum OSCTag: char {22enum OSCTag: char {
23 Int = 'i',23 Int = 'i',
@@ -26,7 +26,7 @@ enum OSCTag: char { · 2 unmodified lines
26 Blob = 'b',26 Blob = 'b',
27};27};
28 28
29static const QRegularExpression invalidCharacters = QRegularExpression("([ #*,/?\\[\\]{}])");29static const QRegularExpression invalidCharacters = QRegularExpression("([ #*,?\\[\\]{}])");
30static const QMap<QChar, QVariant::Type> typeNameMap = {30static const QMap<QChar, QVariant::Type> typeNameMap = {
31 { OSCTag::Int, QVariant::Int },31 { OSCTag::Int, QVariant::Int },
32 { OSCTag::Float, QVariant::Double },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
38OSCScriptingInterface::OSCScriptingInterface(ScriptManager* parent) :38OSCScriptingInterface::OSCScriptingInterface(QObject* parent) :
39 _scriptManager(parent),39 QObject(parent),
40 _receivePort("osc/receivePort", 9000),40 _receivePort("osc/receivePort", 9000),
41 _receiveHost("osc/receiveHost", "127.0.0.1"),41 _receiveHost("osc/receiveHost", "127.0.0.1"),
42 _sendPort("osc/sendPort", 9001),42 _sendPort("osc/sendPort", 9001),
@@ -63,7 +63,14 @@ void OSCScriptingInterface::receivePacket() { · 20 unmodified lines
63void OSCScriptingInterface::sendMessage(const QString& address, const QString &argumentTypes, const QVariantList& arguments) {63void OSCScriptingInterface::sendMessage(const QString& address, const QString &argumentTypes, const QVariantList& arguments) {
64 Q_ASSERT(_socket);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 if (address.length() < 2 || address[0] != '/') {75 if (address.length() < 2 || address[0] != '/') {
69 scriptEngine->raiseException("address must be at least two characters and start with '/'");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 if (argumentTypes.length() != arguments.length()) {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 return;87 return;
81 }88 }
82 89
90 auto pad4 = [](QByteArray& array) {
91 array.append((4 - array.length() % 4) % 4, 0);
92 };
93
83 QByteArray bytes = address.toUtf8();94 QByteArray bytes = address.toUtf8();
84 95
85 // pad to 4-byte boundary with at least one zero for the address string96 // 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 // comma at the start of the argument list, even if empty100 // comma at the start of the argument list, even if empty
89 bytes.append(',');101 bytes.append(',');
@@ -99,19 +111,23 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 9 unmodified lines
99 }111 }
100 112
101 auto expectedType = typeNameMap[argumentTypes[i]];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 scriptEngine->raiseException(QString("Specified argument type '%1' does not match value of type '%2'").arg(QVariant::typeToName(expectedType)).arg(arg.typeName()));119 scriptEngine->raiseException(QString("Specified argument type '%1' does not match value of type '%2'").arg(QVariant::typeToName(expectedType)).arg(arg.typeName()));
104 return;120 return;
105 }121 }
106 122
107 switch (arg.type()) {123 switch (expectedType) {
108 case QVariant::Int: {124 case QVariant::Int: {
109 bytes.append(OSCTag::Int);125 bytes.append(OSCTag::Int);
110 126
111 auto* ptr = bodyBytes.data() + bodyBytes.length();127 auto* ptr = bodyBytes.data() + bodyBytes.length();
112 bodyBytes.append(4, 0);128 bodyBytes.append(4, 0);
113 129
114 qToBigEndian(static_cast<qint32>(arg.toInt()), ptr);130 qToBigEndian(static_cast<qint32>(arg.toDouble()), ptr);
115 } break;131 } break;
116 132
117 case QVariant::Double: {133 case QVariant::Double: {
@@ -121,7 +137,7 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 3 unmodified lines
121 bodyBytes.append(4, 0);137 bodyBytes.append(4, 0);
122 138
123 // FIXME: use std::bit_cast instead of this hack once c++20 is in139 // 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 qToBigEndian(*reinterpret_cast<quint32*>(&tmp), ptr);141 qToBigEndian(*reinterpret_cast<quint32*>(&tmp), ptr);
126 } break;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 bodyBytes.append(stringArg.toUtf8());154 bodyBytes.append(stringArg.toUtf8());
155
139 // pad to 4-byte boundary with at least one zero for the string156 // 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 } break;159 } break;
142 160
143 case QVariant::ByteArray: {161 case QVariant::ByteArray: {
@@ -153,8 +171,8 @@ void OSCScriptingInterface::sendMessage(const QString& address, const QString &a · 9 unmodified lines
153 // write body171 // write body
154 bodyBytes.append(bytesArg);172 bodyBytes.append(bytesArg);
155 173
156 // pad to 4-byte boundary with at least one zero for the string174 // pad to 4-byte boundary
157 bodyBytes.append((bodyBytes.length() + 1) % 4, 0);175 pad4(bodyBytes);
158 } break;176 } break;
159 177
160 // unreachable178 // 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 string185 // pad argument type string to 4-byte boundary with at least one zero
168 bytes.append((bytes.length() + 1) % 4, 0);186 bytes.append('\x00');
187 pad4(bytes);
169 188
170 // pack the header + body data together for the datagram189 // pack the header + body data together for the datagram
171 bytes.append(bodyBytes);190 bytes.append(bodyBytes);
172 191
173 _socket->writeDatagram(bytes, QHostAddress(_sendHost.get()), _sendPort.get());192 _socket->writeDatagram(bytes, QHostAddress(_sendHost.get()), _sendPort.get());
193
194 qCDebug(osc) << QHostAddress(_sendHost.get()) << _sendPort.get() << ":" << bytes.toHex(' ');
174}195}