+ Filter: implement drawing optimization
[calf.git] / src / calf / osctl.h
blobed46a4f0dcd9812ba3d743144930eab0829bd16d
1 /* Calf DSP Library
2 * Open Sound Control primitives
4 * Copyright (C) 2007 Krzysztof Foltman
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.
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.
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., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #ifndef __CALF_OSCTL_H
23 #define __CALF_OSCTL_H
25 #include <string>
26 #include <vector>
27 #include <string.h>
28 #include <errno.h>
29 #include <netinet/in.h>
30 #include <netdb.h>
31 #include <iostream>
33 namespace osctl
36 enum osc_type
38 osc_i32 = 'i',
39 osc_f32 = 'f',
40 osc_string = 's',
41 osc_blob = 'b',
43 // unsupported
44 osc_i64 = 'h',
45 osc_ts = 't',
46 osc_f64 = 'd',
47 osc_string_alt = 'S',
48 osc_char = 'c',
49 osc_rgba = 'r',
50 osc_midi = 'm',
51 osc_true = 'T',
52 osc_false = 'F',
53 osc_nil = 'N',
54 osc_inf = 'I',
55 osc_start_array = '[',
56 osc_end_array = ']'
59 extern const char *osc_type_name(osc_type type);
61 struct osc_exception: public std::exception
63 virtual const char *what() const throw() { return "OSC parsing error"; }
66 struct osc_read_exception: public std::exception
68 virtual const char *what() const throw() { return "OSC buffer underflow"; }
71 struct osc_write_exception: public std::exception
73 virtual const char *what() const throw() { return "OSC buffer overflow"; }
76 struct null_buffer
78 static bool read(uint8_t *dest, uint32_t bytes)
80 return false;
82 static bool write(uint8_t *dest, uint32_t bytes)
84 return true;
86 static void clear()
91 struct raw_buffer
93 uint8_t *ptr;
94 uint32_t pos, count, size;
96 raw_buffer()
98 ptr = NULL;
99 pos = count = size = 0;
101 raw_buffer(uint8_t *_ptr, uint32_t _count, uint32_t _size)
103 set(_ptr, _count, _size);
105 inline void set(uint8_t *_ptr, uint32_t _count, uint32_t _size)
107 ptr = _ptr;
108 pos = 0;
109 count = _count;
110 size = _size;
112 bool read(uint8_t *dest, uint32_t bytes)
114 if (pos + bytes > count)
115 return false;
116 memcpy(dest, ptr + pos, bytes);
117 pos += bytes;
118 return true;
120 bool write(const uint8_t *src, uint32_t bytes)
122 if (count + bytes > size)
123 return false;
124 memcpy(ptr + count, src, bytes);
125 count += bytes;
126 return true;
128 int read_left()
130 return count - pos;
132 int write_left()
134 return size - count;
136 inline int write_misalignment()
138 return 4 - (count & 3);
140 void clear()
142 pos = 0;
143 count = 0;
145 int tell()
147 return pos;
149 void seek(int _pos)
151 pos = _pos;
155 struct string_buffer
157 std::string data;
158 uint32_t pos, size;
160 string_buffer()
162 pos = 0;
163 size = 1048576;
165 string_buffer(std::string _data, int _size = 1048576)
167 data = _data;
168 pos = 0;
169 size = _size;
171 bool read(uint8_t *dest, uint32_t bytes)
173 if (pos + bytes > data.length())
174 return false;
175 memcpy(dest, &data[pos], bytes);
176 pos += bytes;
177 return true;
179 bool write(const uint8_t *src, uint32_t bytes)
181 if (data.length() + bytes > size)
182 return false;
183 uint32_t wpos = data.length();
184 data.resize(wpos + bytes);
185 memcpy(&data[wpos], src, bytes);
186 return true;
188 inline int read_left()
190 return data.length() - pos;
192 inline int write_left()
194 return size - data.length();
196 inline int write_misalignment()
198 return 4 - (data.length() & 3);
200 void clear()
202 data.clear();
203 pos = 0;
205 int tell()
207 return pos;
209 void seek(int _pos)
211 pos = _pos;
215 template<class Buffer, class TypeBuffer = null_buffer, bool Throw = true>
216 struct osc_stream
218 Buffer &buffer;
219 TypeBuffer *type_buffer;
220 bool error;
222 osc_stream(Buffer &_buffer) : buffer(_buffer), type_buffer(NULL), error(false) {}
223 osc_stream(Buffer &_buffer, TypeBuffer &_type_buffer) : buffer(_buffer), type_buffer(&_type_buffer), error(false) {}
224 inline void pad()
226 uint32_t zero = 0;
227 write(&zero, buffer.write_misalignment());
229 inline void read(void *dest, uint32_t bytes)
231 if (!buffer.read((uint8_t *)dest, bytes))
233 if (Throw)
234 throw osc_read_exception();
235 else
237 error = true;
238 memset(dest, 0, bytes);
242 inline void write(const void *src, uint32_t bytes)
244 if (!buffer.write((const uint8_t *)src, bytes))
246 if (Throw)
247 throw osc_write_exception();
248 else
249 error = true;
252 inline void clear()
254 buffer.clear();
255 if (type_buffer)
256 type_buffer->clear();
258 inline void write_type(char ch)
260 if (type_buffer)
261 type_buffer->write((uint8_t *)&ch, 1);
265 typedef osc_stream<string_buffer> osc_strstream;
266 typedef osc_stream<string_buffer, string_buffer> osc_typed_strstream;
268 struct osc_inline_strstream: public string_buffer, public osc_strstream
270 osc_inline_strstream()
271 : string_buffer(), osc_strstream(static_cast<string_buffer &>(*this))
276 struct osc_str_typed_buffer_pair
278 string_buffer buf_data, buf_types;
281 struct osc_inline_typed_strstream: public osc_str_typed_buffer_pair, public osc_typed_strstream
283 osc_inline_typed_strstream()
284 : osc_str_typed_buffer_pair(), osc_typed_strstream(buf_data, buf_types)
289 template<class Buffer, class TypeBuffer>
290 inline osc_stream<Buffer, TypeBuffer> &
291 operator <<(osc_stream<Buffer, TypeBuffer> &s, uint32_t val)
293 val = htonl(val);
294 s.write(&val, 4);
295 s.write_type(osc_i32);
296 return s;
299 template<class Buffer, class TypeBuffer>
300 inline osc_stream<Buffer, TypeBuffer> &
301 operator >>(osc_stream<Buffer, TypeBuffer> &s, uint32_t &val)
303 s.read(&val, 4);
304 val = htonl(val);
305 return s;
308 template<class Buffer, class TypeBuffer>
309 inline osc_stream<Buffer, TypeBuffer> &
310 operator >>(osc_stream<Buffer, TypeBuffer> &s, int32_t &val)
312 s.read(&val, 4);
313 val = htonl(val);
314 return s;
317 template<class Buffer, class TypeBuffer>
318 inline osc_stream<Buffer, TypeBuffer> &
319 operator <<(osc_stream<Buffer, TypeBuffer> &s, float val)
321 union { float v; uint32_t i; } val2;
322 val2.v = val;
323 val2.i = htonl(val2.i);
324 s.write(&val2.i, 4);
325 s.write_type(osc_f32);
326 return s;
329 template<class Buffer, class TypeBuffer>
330 inline osc_stream<Buffer, TypeBuffer> &
331 operator >>(osc_stream<Buffer, TypeBuffer> &s, float &val)
333 union { float v; uint32_t i; } val2;
334 s.read(&val2.i, 4);
335 val2.i = htonl(val2.i);
336 val = val2.v;
337 return s;
340 template<class Buffer, class TypeBuffer>
341 inline osc_stream<Buffer, TypeBuffer> &
342 operator <<(osc_stream<Buffer, TypeBuffer> &s, const std::string &str)
344 s.write(&str[0], str.length());
345 s.pad();
346 s.write_type(osc_string);
347 return s;
350 template<class Buffer, class TypeBuffer>
351 inline osc_stream<Buffer, TypeBuffer> &
352 operator >>(osc_stream<Buffer, TypeBuffer> &s, std::string &str)
354 // inefficient...
355 char five[5];
356 five[4] = '\0';
357 str.resize(0);
358 while(1)
360 s.read(five, 4);
361 if (five[0] == '\0')
362 break;
363 str += five;
364 if (!five[1] || !five[2] || !five[3])
365 break;
367 return s;
370 template<class Buffer, class TypeBuffer, class DestBuffer>
371 inline osc_stream<Buffer, TypeBuffer> &
372 read_buffer_from_osc_stream(osc_stream<Buffer, TypeBuffer> &s, DestBuffer &buf)
374 uint32_t nlen = 0;
375 s.read(&nlen, 4);
376 uint32_t len = htonl(nlen);
377 // write length in network order
378 for (uint32_t i = 0; i < len; i += 1024)
380 uint8_t tmp[1024];
381 uint32_t part = std::min((uint32_t)1024, len - i);
382 s.read(tmp, part);
383 buf.write(tmp, part);
385 // pad
386 s.read(&nlen, 4 - (len & 3));
387 return s;
390 template<class Buffer, class TypeBuffer, class SrcBuffer>
391 inline osc_stream<Buffer, TypeBuffer> &
392 write_buffer_to_osc_stream(osc_stream<Buffer, TypeBuffer> &s, SrcBuffer &buf)
394 uint32_t len = buf.read_left();
395 uint32_t nlen = ntohl(len);
396 s.write(&nlen, 4);
397 // write length in network order
398 for (uint32_t i = 0; i < len; i += 1024)
400 uint8_t tmp[1024];
401 uint32_t part = std::min((uint32_t)1024, len - i);
402 buf.read(tmp, part);
403 s.write(tmp, part);
405 s.pad();
406 s.write_type(osc_blob);
407 return s;
410 template<class Buffer, class TypeBuffer>
411 inline osc_stream<Buffer, TypeBuffer> &
412 operator >>(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
414 return read_buffer_from_osc_stream(s, str);
417 template<class Buffer, class TypeBuffer>
418 inline osc_stream<Buffer, TypeBuffer> &
419 operator >>(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
421 return read_buffer_from_osc_stream(s, str);
424 template<class Buffer, class TypeBuffer>
425 inline osc_stream<Buffer, TypeBuffer> &
426 operator <<(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
428 return write_buffer_to_osc_stream(s, str);
431 template<class Buffer, class TypeBuffer>
432 inline osc_stream<Buffer, TypeBuffer> &
433 operator <<(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
435 return write_buffer_to_osc_stream(s, str);
438 // XXXKF: I don't support reading binary blobs yet
440 struct osc_net_bad_address: public std::exception
442 std::string addr, error_msg;
443 osc_net_bad_address(const char *_addr)
445 addr = _addr;
446 error_msg = "Incorrect OSC URI: " + addr;
448 virtual const char *what() const throw() { return error_msg.c_str(); }
449 virtual ~osc_net_bad_address() throw () {}
452 struct osc_net_exception: public std::exception
454 int net_errno;
455 std::string command, error_msg;
456 osc_net_exception(const char *cmd, int _errno = errno)
458 command = cmd;
459 net_errno = _errno;
460 error_msg = "OSC error in "+command+": "+strerror(_errno);
462 virtual const char *what() const throw() { return error_msg.c_str(); }
463 virtual ~osc_net_exception() throw () {}
466 struct osc_net_dns_exception: public std::exception
468 int net_errno;
469 std::string command, error_msg;
470 osc_net_dns_exception(const char *cmd, int _errno = h_errno)
472 command = cmd;
473 net_errno = _errno;
474 error_msg = "OSC error in "+command+": "+hstrerror(_errno);
476 virtual const char *what() const throw() { return error_msg.c_str(); }
477 virtual ~osc_net_dns_exception() throw () {}
480 template<class OscStream>
481 struct osc_message_sink
483 virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)=0;
484 virtual ~osc_message_sink() {}
487 template<class OscStream, class DumpStream>
488 struct osc_message_dump: public osc_message_sink<OscStream>
490 DumpStream &stream;
491 osc_message_dump(DumpStream &_stream) : stream(_stream) {}
493 virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)
495 int pos = buffer.buffer.tell();
496 stream << "address: " << address << ", type tag: " << type_tag << std::endl;
497 for (unsigned int i = 0; i < type_tag.size(); i++)
499 stream << "Argument " << i << " is ";
500 switch(type_tag[i])
502 case 'i':
504 uint32_t val;
505 buffer >> val;
506 stream << val;
507 break;
509 case 'f':
511 float val;
512 buffer >> val;
513 stream << val;
514 break;
516 case 's':
518 std::string val;
519 buffer >> val;
520 stream << val;
521 break;
523 case 'b':
525 osctl::string_buffer val;
526 buffer >> val;
527 stream << "blob (" << val.data.length() << " bytes)";
528 break;
530 default:
532 stream << "unknown - cannot parse more arguments" << std::endl;
533 i = type_tag.size();
534 break;
537 stream << std::endl;
539 stream << std::flush;
540 buffer.buffer.seek(pos);
546 #endif