1// Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net>
2// Copyright (C) 2016 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qoscmessage_p.h"
6#include "qtuio_p.h"
7
8#include <QDebug>
9#include <QtEndian>
10#include <QLoggingCategory>
11
12QT_BEGIN_NAMESPACE
13
14Q_LOGGING_CATEGORY(lcTuioMessage, "qt.qpa.tuio.message")
15
16QOscMessage::QOscMessage() {}
17
18// TUIO packets are transmitted using the OSC protocol, located at:
19// http://opensoundcontrol.org/specification
20// Snippets of this specification have been pasted into the source as a means of
21// easily communicating requirements.
22
23QOscMessage::QOscMessage(const QByteArray &data)
24 : m_isValid(false)
25{
26 qCDebug(lcTuioMessage) << data.toHex();
27 quint32 parsedBytes = 0;
28
29 // "An OSC message consists of an OSC Address Pattern"
30 QByteArray addressPattern;
31 if (!qt_readOscString(source: data, dest&: addressPattern, pos&: parsedBytes) || addressPattern.size() == 0)
32 return;
33
34 // "followed by an OSC Type Tag String"
35 QByteArray typeTagString;
36 if (!qt_readOscString(source: data, dest&: typeTagString, pos&: parsedBytes))
37 return;
38
39 // "Note: some older implementations of OSC may omit the OSC Type Tag string.
40 // Until all such implementations are updated, OSC implementations should be
41 // robust in the case of a missing OSC Type Tag String."
42 //
43 // (although, the editor notes one may question how exactly the hell one is
44 // supposed to be robust when the behavior is unspecified.)
45 if (typeTagString.size() == 0 || typeTagString.at(i: 0) != ',')
46 return;
47
48 QList<QVariant> arguments;
49
50 // "followed by zero or more OSC Arguments."
51 for (int i = 1; i < typeTagString.size(); ++i) {
52 char typeTag = typeTagString.at(i);
53 if (typeTag == 's') { // osc-string
54 QByteArray aString;
55 if (!qt_readOscString(source: data, dest&: aString, pos&: parsedBytes))
56 return;
57 arguments.append(t: aString);
58 } else if (typeTag == 'i') { // int32
59 if (parsedBytes > (quint32)data.size() || data.size() - parsedBytes < qsizetype(sizeof(quint32)))
60 return;
61
62 quint32 anInt = qFromBigEndian<quint32>(src: data.constData() + parsedBytes);
63 parsedBytes += sizeof(quint32);
64
65 // TODO: is int32 in OSC signed, or unsigned?
66 arguments.append(t: (int)anInt);
67 } else if (typeTag == 'f') { // float32
68 if (parsedBytes > (quint32)data.size() || data.size() - parsedBytes < qsizetype(sizeof(quint32)))
69 return;
70
71 static_assert(sizeof(float) == sizeof(quint32));
72 union {
73 quint32 u;
74 float f;
75 } value;
76 value.u = qFromBigEndian<quint32>(src: data.constData() + parsedBytes);
77 parsedBytes += sizeof(quint32);
78 arguments.append(t: value.f);
79 } else {
80 qCWarning(lcTuioMessage) << "Reading argument of unknown type " << typeTag;
81 return;
82 }
83 }
84
85 m_isValid = true;
86 m_addressPattern = addressPattern;
87 m_arguments = arguments;
88
89 qCDebug(lcTuioMessage) << "Message with address pattern: " << addressPattern << " arguments: " << arguments;
90}
91
92QT_END_NAMESPACE
93
94

source code of qtbase/src/plugins/generic/tuiotouch/qoscmessage.cpp