1 /* Calf DSP Library
2 * Open Sound Control primitives
3 *
4 * Copyright (C) 2007 Krzysztof Foltman
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 #ifndef __CALF_OSCTL_H
23 #define __CALF_OSCTL_H
24
25 #include <string>
26 #include <vector>
27 #include <string.h>
28 #include <errno.h>
29 #include <iostream>
30 #ifndef _MSC_VER
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #endif
34
35 namespace osctl
36 {
37
38 enum osc_type
39 {
40 osc_i32 = 'i',
41 osc_f32 = 'f',
42 osc_string = 's',
43 osc_blob = 'b',
44
45 // unsupported
46 osc_i64 = 'h',
47 osc_ts = 't',
48 osc_f64 = 'd',
49 osc_string_alt = 'S',
50 osc_char = 'c',
51 osc_rgba = 'r',
52 osc_midi = 'm',
53 osc_true = 'T',
54 osc_false = 'F',
55 osc_nil = 'N',
56 osc_inf = 'I',
57 osc_start_array = '[',
58 osc_end_array = ']'
59 };
60
61 extern const char *osc_type_name(osc_type type);
62
63 struct osc_exception: public std::exception
64 {
whatosc_exception65 virtual const char *what() const throw() { return "OSC parsing error"; }
66 };
67
68 struct osc_read_exception: public std::exception
69 {
whatosc_read_exception70 virtual const char *what() const throw() { return "OSC buffer underflow"; }
71 };
72
73 struct osc_write_exception: public std::exception
74 {
whatosc_write_exception75 virtual const char *what() const throw() { return "OSC buffer overflow"; }
76 };
77
78 struct null_buffer
79 {
readnull_buffer80 static bool read(uint8_t *dest, uint32_t bytes)
81 {
82 return false;
83 }
writenull_buffer84 static bool write(uint8_t *dest, uint32_t bytes)
85 {
86 return true;
87 }
clearnull_buffer88 static void clear()
89 {
90 }
91 };
92
93 struct raw_buffer
94 {
95 uint8_t *ptr;
96 uint32_t pos, count, size;
97
raw_bufferraw_buffer98 raw_buffer()
99 {
100 ptr = NULL;
101 pos = count = size = 0;
102 }
raw_bufferraw_buffer103 raw_buffer(uint8_t *_ptr, uint32_t _count, uint32_t _size)
104 {
105 set(_ptr, _count, _size);
106 }
setraw_buffer107 inline void set(uint8_t *_ptr, uint32_t _count, uint32_t _size)
108 {
109 ptr = _ptr;
110 pos = 0;
111 count = _count;
112 size = _size;
113 }
readraw_buffer114 bool read(uint8_t *dest, uint32_t bytes)
115 {
116 if (pos + bytes > count)
117 return false;
118 memcpy(dest, ptr + pos, bytes);
119 pos += bytes;
120 return true;
121 }
writeraw_buffer122 bool write(const uint8_t *src, uint32_t bytes)
123 {
124 if (count + bytes > size)
125 return false;
126 memcpy(ptr + count, src, bytes);
127 count += bytes;
128 return true;
129 }
read_leftraw_buffer130 int read_left()
131 {
132 return count - pos;
133 }
write_leftraw_buffer134 int write_left()
135 {
136 return size - count;
137 }
write_misalignmentraw_buffer138 inline int write_misalignment()
139 {
140 return 4 - (count & 3);
141 }
clearraw_buffer142 void clear()
143 {
144 pos = 0;
145 count = 0;
146 }
tellraw_buffer147 int tell()
148 {
149 return pos;
150 }
seekraw_buffer151 void seek(int _pos)
152 {
153 pos = _pos;
154 }
155 };
156
157 struct string_buffer
158 {
159 std::string data;
160 uint32_t pos, size;
161
string_bufferstring_buffer162 string_buffer()
163 {
164 pos = 0;
165 size = 1048576;
166 }
167 string_buffer(std::string _data, int _size = 1048576)
168 {
169 data = _data;
170 pos = 0;
171 size = _size;
172 }
readstring_buffer173 bool read(uint8_t *dest, uint32_t bytes)
174 {
175 if (pos + bytes > data.length())
176 return false;
177 memcpy(dest, &data[pos], bytes);
178 pos += bytes;
179 return true;
180 }
writestring_buffer181 bool write(const uint8_t *src, uint32_t bytes)
182 {
183 if (data.length() + bytes > size)
184 return false;
185 uint32_t wpos = data.length();
186 data.resize(wpos + bytes);
187 memcpy(&data[wpos], src, bytes);
188 return true;
189 }
read_leftstring_buffer190 inline int read_left()
191 {
192 return data.length() - pos;
193 }
write_leftstring_buffer194 inline int write_left()
195 {
196 return size - data.length();
197 }
write_misalignmentstring_buffer198 inline int write_misalignment()
199 {
200 return 4 - (data.length() & 3);
201 }
clearstring_buffer202 void clear()
203 {
204 data.clear();
205 pos = 0;
206 }
tellstring_buffer207 int tell()
208 {
209 return pos;
210 }
seekstring_buffer211 void seek(int _pos)
212 {
213 pos = _pos;
214 }
215 };
216
217 template<class Buffer, class TypeBuffer = null_buffer, bool Throw = true>
218 struct osc_stream
219 {
220 Buffer &buffer;
221 TypeBuffer *type_buffer;
222 bool error;
223
osc_streamosc_stream224 osc_stream(Buffer &_buffer) : buffer(_buffer), type_buffer(NULL), error(false) {}
osc_streamosc_stream225 osc_stream(Buffer &_buffer, TypeBuffer &_type_buffer) : buffer(_buffer), type_buffer(&_type_buffer), error(false) {}
padosc_stream226 inline void pad()
227 {
228 uint32_t zero = 0;
229 write(&zero, buffer.write_misalignment());
230 }
readosc_stream231 inline void read(void *dest, uint32_t bytes)
232 {
233 if (!buffer.read((uint8_t *)dest, bytes))
234 {
235 if (Throw)
236 throw osc_read_exception();
237 else
238 {
239 error = true;
240 memset(dest, 0, bytes);
241 }
242 }
243 }
writeosc_stream244 inline void write(const void *src, uint32_t bytes)
245 {
246 if (!buffer.write((const uint8_t *)src, bytes))
247 {
248 if (Throw)
249 throw osc_write_exception();
250 else
251 error = true;
252 }
253 }
clearosc_stream254 inline void clear()
255 {
256 buffer.clear();
257 if (type_buffer)
258 type_buffer->clear();
259 }
write_typeosc_stream260 inline void write_type(char ch)
261 {
262 if (type_buffer)
263 type_buffer->write((uint8_t *)&ch, 1);
264 }
265 };
266
267 typedef osc_stream<string_buffer> osc_strstream;
268 typedef osc_stream<string_buffer, string_buffer> osc_typed_strstream;
269
270 struct osc_inline_strstream: public string_buffer, public osc_strstream
271 {
osc_inline_strstreamosc_inline_strstream272 osc_inline_strstream()
273 : string_buffer(), osc_strstream(static_cast<string_buffer &>(*this))
274 {
275 }
276 };
277
278 struct osc_str_typed_buffer_pair
279 {
280 string_buffer buf_data, buf_types;
281 };
282
283 struct osc_inline_typed_strstream: public osc_str_typed_buffer_pair, public osc_typed_strstream
284 {
osc_inline_typed_strstreamosc_inline_typed_strstream285 osc_inline_typed_strstream()
286 : osc_str_typed_buffer_pair(), osc_typed_strstream(buf_data, buf_types)
287 {
288 }
289 };
290
291 template<class Buffer, class TypeBuffer>
292 inline osc_stream<Buffer, TypeBuffer> &
293 operator <<(osc_stream<Buffer, TypeBuffer> &s, uint32_t val)
294 {
295 val = htonl(val);
296 s.write(&val, 4);
297 s.write_type(osc_i32);
298 return s;
299 }
300
301 template<class Buffer, class TypeBuffer>
302 inline osc_stream<Buffer, TypeBuffer> &
303 operator >>(osc_stream<Buffer, TypeBuffer> &s, uint32_t &val)
304 {
305 s.read(&val, 4);
306 val = htonl(val);
307 return s;
308 }
309
310 template<class Buffer, class TypeBuffer>
311 inline osc_stream<Buffer, TypeBuffer> &
312 operator >>(osc_stream<Buffer, TypeBuffer> &s, int32_t &val)
313 {
314 s.read(&val, 4);
315 val = htonl(val);
316 return s;
317 }
318
319 template<class Buffer, class TypeBuffer>
320 inline osc_stream<Buffer, TypeBuffer> &
321 operator <<(osc_stream<Buffer, TypeBuffer> &s, float val)
322 {
323 union { float v; uint32_t i; } val2;
324 val2.v = val;
325 val2.i = htonl(val2.i);
326 s.write(&val2.i, 4);
327 s.write_type(osc_f32);
328 return s;
329 }
330
331 template<class Buffer, class TypeBuffer>
332 inline osc_stream<Buffer, TypeBuffer> &
333 operator >>(osc_stream<Buffer, TypeBuffer> &s, float &val)
334 {
335 union { float v; uint32_t i; } val2;
336 s.read(&val2.i, 4);
337 val2.i = htonl(val2.i);
338 val = val2.v;
339 return s;
340 }
341
342 template<class Buffer, class TypeBuffer>
343 inline osc_stream<Buffer, TypeBuffer> &
344 operator <<(osc_stream<Buffer, TypeBuffer> &s, const std::string &str)
345 {
346 s.write(&str[0], str.length());
347 s.pad();
348 s.write_type(osc_string);
349 return s;
350 }
351
352 template<class Buffer, class TypeBuffer>
353 inline osc_stream<Buffer, TypeBuffer> &
354 operator >>(osc_stream<Buffer, TypeBuffer> &s, std::string &str)
355 {
356 // inefficient...
357 char five[5];
358 five[4] = '\0';
359 str.resize(0);
360 while(1)
361 {
362 s.read(five, 4);
363 if (five[0] == '\0')
364 break;
365 str += five;
366 if (!five[1] || !five[2] || !five[3])
367 break;
368 }
369 return s;
370 }
371
372 template<class Buffer, class TypeBuffer, class DestBuffer>
373 inline osc_stream<Buffer, TypeBuffer> &
read_buffer_from_osc_stream(osc_stream<Buffer,TypeBuffer> & s,DestBuffer & buf)374 read_buffer_from_osc_stream(osc_stream<Buffer, TypeBuffer> &s, DestBuffer &buf)
375 {
376 uint32_t nlen = 0;
377 s.read(&nlen, 4);
378 uint32_t len = htonl(nlen);
379 // write length in network order
380 for (uint32_t i = 0; i < len; i += 1024)
381 {
382 uint8_t tmp[1024];
383 uint32_t part = std::min((uint32_t)1024, len - i);
384 s.read(tmp, part);
385 buf.write(tmp, part);
386 }
387 // pad
388 s.read(&nlen, 4 - (len & 3));
389 return s;
390 }
391
392 template<class Buffer, class TypeBuffer, class SrcBuffer>
393 inline osc_stream<Buffer, TypeBuffer> &
write_buffer_to_osc_stream(osc_stream<Buffer,TypeBuffer> & s,SrcBuffer & buf)394 write_buffer_to_osc_stream(osc_stream<Buffer, TypeBuffer> &s, SrcBuffer &buf)
395 {
396 uint32_t len = buf.read_left();
397 uint32_t nlen = ntohl(len);
398 s.write(&nlen, 4);
399 // write length in network order
400 for (uint32_t i = 0; i < len; i += 1024)
401 {
402 uint8_t tmp[1024];
403 uint32_t part = std::min((uint32_t)1024, len - i);
404 buf.read(tmp, part);
405 s.write(tmp, part);
406 }
407 s.pad();
408 s.write_type(osc_blob);
409 return s;
410 }
411
412 template<class Buffer, class TypeBuffer>
413 inline osc_stream<Buffer, TypeBuffer> &
414 operator >>(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
415 {
416 return read_buffer_from_osc_stream(s, str);
417 }
418
419 template<class Buffer, class TypeBuffer>
420 inline osc_stream<Buffer, TypeBuffer> &
421 operator >>(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
422 {
423 return read_buffer_from_osc_stream(s, str);
424 }
425
426 template<class Buffer, class TypeBuffer>
427 inline osc_stream<Buffer, TypeBuffer> &
428 operator <<(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
429 {
430 return write_buffer_to_osc_stream(s, str);
431 }
432
433 template<class Buffer, class TypeBuffer>
434 inline osc_stream<Buffer, TypeBuffer> &
435 operator <<(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
436 {
437 return write_buffer_to_osc_stream(s, str);
438 }
439
440 // XXXKF: I don't support reading binary blobs yet
441
442 struct osc_net_bad_address: public std::exception
443 {
444 std::string addr, error_msg;
osc_net_bad_addressosc_net_bad_address445 osc_net_bad_address(const char *_addr)
446 {
447 addr = _addr;
448 error_msg = "Incorrect OSC URI: " + addr;
449 }
whatosc_net_bad_address450 virtual const char *what() const throw() { return error_msg.c_str(); }
~osc_net_bad_addressosc_net_bad_address451 virtual ~osc_net_bad_address() throw () {}
452 };
453
454 struct osc_net_exception: public std::exception
455 {
456 int net_errno;
457 std::string command, error_msg;
458 osc_net_exception(const char *cmd, int _errno = errno)
459 {
460 command = cmd;
461 net_errno = _errno;
462 error_msg = "OSC error in "+command+": "+strerror(_errno);
463 }
whatosc_net_exception464 virtual const char *what() const throw() { return error_msg.c_str(); }
~osc_net_exceptionosc_net_exception465 virtual ~osc_net_exception() throw () {}
466 };
467 #ifdef _MSC_VER
468 //TODO: add replacement for osc_net_dns_exception
469 #else
470 struct osc_net_dns_exception: public std::exception
471 {
472 int net_errno;
473 std::string command, error_msg;
474 osc_net_dns_exception(const char *cmd, int _errno = h_errno)
475 {
476 command = cmd;
477 net_errno = _errno;
478 error_msg = "OSC error in "+command+": "+hstrerror(_errno);
479 }
whatosc_net_dns_exception480 virtual const char *what() const throw() { return error_msg.c_str(); }
~osc_net_dns_exceptionosc_net_dns_exception481 virtual ~osc_net_dns_exception() throw () {}
482 };
483 #endif
484 template<class OscStream>
485 struct osc_message_sink
486 {
487 virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)=0;
~osc_message_sinkosc_message_sink488 virtual ~osc_message_sink() {}
489 };
490
491 template<class OscStream, class DumpStream>
492 struct osc_message_dump: public osc_message_sink<OscStream>
493 {
494 DumpStream &stream;
osc_message_dumposc_message_dump495 osc_message_dump(DumpStream &_stream) : stream(_stream) {}
496
receive_osc_messageosc_message_dump497 virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)
498 {
499 int pos = buffer.buffer.tell();
500 stream << "address: " << address << ", type tag: " << type_tag << std::endl;
501 for (unsigned int i = 0; i < type_tag.size(); i++)
502 {
503 stream << "Argument " << i << " is ";
504 switch(type_tag[i])
505 {
506 case 'i':
507 {
508 uint32_t val;
509 buffer >> val;
510 stream << val;
511 break;
512 }
513 case 'f':
514 {
515 float val;
516 buffer >> val;
517 stream << val;
518 break;
519 }
520 case 's':
521 {
522 std::string val;
523 buffer >> val;
524 stream << val;
525 break;
526 }
527 case 'b':
528 {
529 osctl::string_buffer val;
530 buffer >> val;
531 stream << "blob (" << val.data.length() << " bytes)";
532 break;
533 }
534 default:
535 {
536 stream << "unknown - cannot parse more arguments" << std::endl;
537 i = type_tag.size();
538 break;
539 }
540 }
541 stream << std::endl;
542 }
543 stream << std::flush;
544 buffer.buffer.seek(pos);
545 }
546 };
547
548 };
549
550 #endif
551