arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
OSCData.h
1#pragma once
2#include <stdint.h>
3#include <string.h>
4#include "AudioTools/CoreAudio/AudioBasic/Collections/Vector.h"
5
6namespace audio_tools {
7
16 uint8_t *data = nullptr;
17 size_t len = 0;
18 OSCBinaryData(uint8_t *data, int len) {
19 this->data = data;
20 this->len = len;
21 }
22 OSCBinaryData() = default;
23};
24
25enum class OSCCompare { Matches, Equals, StartsWith, EndsWith, Contains };
26
56class OSCData {
57 public:
59 OSCData() = default;
61 OSCData(uint8_t *data, uint32_t maxlen) {
62 binary_content.data = data;
63 binary_content.len = maxlen;
64 }
65
67 void setAddress(const char *address) {
68 int adr_len = OSCData::oscSize(address);
69 memset(binary_content.data, 0, adr_len);
70 strcpy((char *)binary_content.data, address);
71 write_pos = adr_len;
72 }
73
75 void setFormat(const char *format) {
76 int fmt_len = OSCData::oscFormatSize(strlen(format));
77 memset(binary_content.data + write_pos, 0, fmt_len);
78 binary_content.data[write_pos] = ',';
79 read_format_start = binary_content.data + write_pos + 1;
80 strcpy((char *)read_format_start, format);
81 write_pos += fmt_len;
82 read_data = binary_content.data + write_pos;
83 }
84
86 bool write(int32_t number) {
87 int32_t number_net = htonl(number);
88 if (write_pos + sizeof(int32_t) > binary_content.len) {
89 return false;
90 }
91 memcpy(binary_content.data + write_pos, &number_net, sizeof(int32_t));
92 write_pos += sizeof(int32_t);
93 return true;
94 }
95
97 bool write(int64_t number) {
98 if (write_pos + sizeof(int64_t) > binary_content.len) {
99 return false;
100 }
101 int64_t number_net = htonll(number);
102 memcpy(binary_content.data + write_pos, &number_net, sizeof(int64_t));
103 write_pos += sizeof(int64_t);
104 return true;
105 }
106
107#ifndef IS_DESKTOP
108
110 bool write(unsigned long number) { return write((uint64_t)number); }
111
112#endif
113
115 bool write(uint64_t number) {
116 if (write_pos + sizeof(uint64_t) > binary_content.len) {
117 return false;
118 }
119 uint64_t number_net = htonll(number);
120 memcpy(binary_content.data + write_pos, &number_net, sizeof(uint64_t));
121 write_pos += sizeof(uint64_t);
122 return true;
123 }
124
126 bool write(double fp64) { return write(*(int64_t *)&fp64); }
127
129 bool write(const char *str) {
130 int str_len = OSCData::oscSize(str);
131 if (write_pos + str_len > binary_content.len) {
132 return false;
133 }
134 memset(binary_content.data + write_pos, 0, str_len);
135 strcpy((char *)binary_content.data + write_pos, str);
136 write_pos += str_len;
137 return true;
138 }
139
141 bool write(OSCBinaryData &data) { return write(data.data, data.len); }
142
144 bool write(const uint8_t *dataArg, int len) {
145 uint32_t size = OSCData::oscSize(len) + sizeof(int32_t);
146 if (write_pos + size > binary_content.len) {
147 return false;
148 }
149 memset(binary_content.data + write_pos, 0, size);
150 int32_t len_net = htonl(len);
151 memcpy((binary_content.data + write_pos), &len_net, sizeof(int32_t));
152 memcpy((binary_content.data + write_pos + sizeof(int32_t)), dataArg, len);
153 write_pos += size;
154 return true;
155 }
156
158 void clear() {
159 write_pos = 0;
160 read_format_start = nullptr;
161 read_data = nullptr;
162 binary_content.data = nullptr;
163 binary_content.len = 0;
164 callbacks.clear();
165 }
166
169 uint8_t *data() { return binary_content.data; }
170
172 int size() { return write_pos; }
173
175 bool parse(uint8_t *data, size_t len) {
176 // store data
177 binary_content.data = data;
178 binary_content.len = len;
179
180 // to support size()
181 write_pos = len;
182
183 // Print frist 20 digits
184 if (is_log_active) logMsg(data, 20);
185
186 if (data[0] != '/') return false;
187
188 // determine address length 4 byte aligned
189 int addr_len = OSCData::oscSize((char *)binary_content.data);
190
191 // determine start of format
192 read_format_start = (uint8_t *)getAddress() + addr_len;
193
194 // check start of format
195 if (*read_format_start != ',') {
196 return false;
197 }
198
199 int format_len =
200 OSCData::oscFormatSize(strlen((char *)read_format_start + 1));
201
202 // determine start of data
203 read_data = read_format_start + format_len;
204
205 // move past ,
206 read_format_start++;
207
209 if (callbacks.size() > 0) {
210 for (auto &cb : callbacks) {
211 if (compare(cb.compare, cb.address, getAddress())) {
212 if (cb.callback != nullptr) {
213 if (cb.callback(*this, reference)) {
214 return true;
215 }
216 }
217 }
218 }
219 // return false if no callback was called successfully
220 return false;
221 }
222
223 return true;
224 }
225
226 void logMsg(uint8_t *data, int len) {
227 Serial.print("OSCData: ");
228 for (int i = 0; i < len; i++) {
229 Serial.print((char)data[i]);
230 }
231#ifndef IS_DESKTOP
232 Serial.println();
233 Serial.print("Hex Data: ");
234 for (int i = 0; i < len; i++) {
235 Serial.print(data[i], HEX);
236 }
237 Serial.println();
238#endif
239 }
240
242 const char *getAddress() { return (const char *)binary_content.data; }
243
245 const char *getFormat() { return (const char *)read_format_start; }
246
248 float readFloat() {
249 int64_t number = readInt32();
250 return *((float *)&number);
251 }
252
254 int32_t readInt32() {
255 int32_t number;
256 memcpy(&number, read_data, sizeof(int32_t));
257 read_data += sizeof(int32_t);
258 return ntohl(number);
259 }
260
262 int64_t readInt64() {
263 int64_t number;
264 memcpy(&number, read_data, sizeof(int64_t));
265 read_data += sizeof(int64_t);
266 return ntohll(number);
267 }
268
270 uint64_t readTime() { return (uint64_t)readInt64(); }
271
273 double readDouble() {
274 int64_t number = readInt64();
275 return *((double *)&number);
276 }
277
279 const char *readString() {
280 const char *str = (const char *)read_data;
281 int str_len = OSCData::oscSize(str);
282 read_data += str_len;
283 return str;
284 }
285
288 OSCBinaryData result;
289 int32_t len = 0;
290 memcpy(&len, read_data, sizeof(int32_t));
291 result.len = ntohl(len);
292 result.data = read_data + sizeof(int32_t);
293 read_data += (OSCData::oscSize(result.len) + sizeof(int32_t));
294 return result;
295 }
296
298 void setLogActive(bool active) { is_log_active = active; }
299
302 OSCBinaryData &messageData() { return binary_content; }
303
305 static int oscSize(int len) {
306 if (len % 4 == 0) return len;
307 int padding = 4 - (len % 4);
308 return len + padding;
309 }
310
313 return sizeof(uint32_t) + OSCData::oscSize(data.len);
314 }
315
317 static int oscSize(const char *str) {
318 // +1 for trailing 0
319 return OSCData::oscSize(strlen(str) + 1);
320 }
321
323 static int oscFormatSize(int len) {
324 //+2 for , and trailing 0
325 return oscSize(len + 2);
326 }
327
329 static int oscFormatSize(const char *str) {
330 return oscFormatSize(strlen(str));
331 }
332
334 void setReference(void *ref) { reference = ref; }
335
337 bool addCallback(const char *address,
338 bool (*callback)(OSCData &data, void *ref),
339 OSCCompare compare = OSCCompare::Matches) {
340 if (address == nullptr || callback == nullptr) return false;
341
343 for (auto &cb : callbacks) {
344 if (cb.address != nullptr && strcmp(cb.address, address) == 0) {
345 cb.callback = callback;
346 cb.compare = compare;
347 return true;
348 }
349 }
350 // add new entry
351 Callback cb;
352 cb.address = address;
353 cb.callback = callback;
354 callbacks.push_back(cb);
355 return true;
356 }
357
358 protected:
359 int write_pos = 0;
360 uint8_t *read_format_start = nullptr;
361 uint8_t *read_data = nullptr;
362 bool is_log_active = false;
363 OSCBinaryData binary_content;
364 void *reference = nullptr;
365
366 struct Callback {
367 const char *address = nullptr;
368 bool (*callback)(OSCData &data, void *ref) = nullptr;
369 OSCCompare compare;
370 };
371 Vector<Callback> callbacks;
372
373 bool compare(OSCCompare compare, const char *strRef, const char *strCompare) {
374 switch (compare) {
375 case OSCCompare::Matches:
376 return StrView(strRef).matches(strCompare);
377 case OSCCompare::Equals:
378 return StrView(strRef).equals(strCompare);
379 case OSCCompare::StartsWith:
380 return StrView(strRef).startsWith(strCompare);
381 case OSCCompare::EndsWith:
382 return StrView(strRef).endsWith(strCompare);
383 case OSCCompare::Contains:
384 return StrView(strRef).contains(strCompare);
385 }
386 return false;
387 }
388
389 uint8_t *getEnd() { return binary_content.data + binary_content.len; }
390};
391
392} // namespace audio_tools
A simple OSC Data composer and parser. A OSC data starts with an address string followed by a format ...
Definition OSCData.h:56
bool write(const uint8_t *dataArg, int len)
write a binary blob (b)
Definition OSCData.h:144
bool write(int32_t number)
write an int32_t number (i)
Definition OSCData.h:86
uint64_t readTime()
reads the next attribute as uint64_t
Definition OSCData.h:270
bool write(const char *str)
write a string (s)
Definition OSCData.h:129
const char * getAddress()
provides the address: after calling parse
Definition OSCData.h:242
bool parse(uint8_t *data, size_t len)
parse the data to start for reading
Definition OSCData.h:175
OSCData()=default
Data for receiving:
const OSCBinaryData readData()
reads the next attribute as binary data blob.
Definition OSCData.h:287
OSCData(uint8_t *data, uint32_t maxlen)
Data for sending.
Definition OSCData.h:61
bool write(int64_t number)
write an int64_t number
Definition OSCData.h:97
int64_t readInt64()
reads the next attribute as long
Definition OSCData.h:262
static int oscSize(OSCBinaryData data)
storage size (multiple of 4) for binary blob data
Definition OSCData.h:312
bool write(uint64_t number)
write a timetag (t) data type
Definition OSCData.h:115
bool write(double fp64)
write a 64bit double number (d)
Definition OSCData.h:126
bool addCallback(const char *address, bool(*callback)(OSCData &data, void *ref), OSCCompare compare=OSCCompare::Matches)
register a parsing callback for a specific address matching string
Definition OSCData.h:337
double readDouble()
reads the next attribute as double
Definition OSCData.h:273
static int oscSize(int len)
storage size (multiple of 4)
Definition OSCData.h:305
uint8_t * data()
Definition OSCData.h:169
void setReference(void *ref)
store a reference object (for callback)
Definition OSCData.h:334
const char * readString()
reads the next string
Definition OSCData.h:279
float readFloat()
reads the next attributes as float
Definition OSCData.h:248
static int oscFormatSize(const char *str)
storage size (multiple of 4) for format string (w/o the leading ,)
Definition OSCData.h:329
void setFormat(const char *format)
Defines the format string (e.g. ,iif)
Definition OSCData.h:75
static int oscFormatSize(int len)
storage size (multiple of 4) for format string (w/o the leading ,)
Definition OSCData.h:323
OSCBinaryData & messageData()
Definition OSCData.h:302
void clear()
clears all data
Definition OSCData.h:158
void setAddress(const char *address)
Defines the address string (e.g. /test)
Definition OSCData.h:67
static int oscSize(const char *str)
storage size (multiple of 4) for string
Definition OSCData.h:317
int32_t readInt32()
reads the next attribute as int32
Definition OSCData.h:254
bool write(OSCBinaryData &data)
write a binary blob (b)
Definition OSCData.h:141
void setLogActive(bool active)
Log the beginning of the received messages.
Definition OSCData.h:298
int size()
returns the number of bytes written (or parsed)
Definition OSCData.h:172
const char * getFormat()
provides the format string: after calling parse
Definition OSCData.h:245
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition StrView.h:28
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition StrView.h:165
virtual bool endsWith(const char *str)
checks if the string ends with the indicated substring
Definition StrView.h:178
virtual bool startsWith(const char *str)
checks if the string starts with the indicated substring
Definition StrView.h:171
virtual bool contains(const char *str)
checks if the string contains a substring
Definition StrView.h:280
virtual bool matches(const char *pattern)
Definition StrView.h:193
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Simple structure to hold binary data.
Definition OSCData.h:15
Definition OSCData.h:366