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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02111-1307, USA.
22 #ifndef __CALF_OSCTL_H
23 #define __CALF_OSCTL_H
29 #include <netinet/in.h>
55 osc_start_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"; }
78 static bool read(uint8_t *dest
, uint32_t bytes
)
82 static bool write(uint8_t *dest
, uint32_t bytes
)
94 uint32_t pos
, count
, size
;
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
)
112 bool read(uint8_t *dest
, uint32_t bytes
)
114 if (pos
+ bytes
> count
)
116 memcpy(dest
, ptr
+ pos
, bytes
);
120 bool write(const uint8_t *src
, uint32_t bytes
)
122 if (count
+ bytes
> size
)
124 memcpy(ptr
+ count
, src
, bytes
);
136 inline int write_misalignment()
138 return 4 - (count
& 3);
165 string_buffer(std::string _data
, int _size
= 1048576)
171 bool read(uint8_t *dest
, uint32_t bytes
)
173 if (pos
+ bytes
> data
.length())
175 memcpy(dest
, &data
[pos
], bytes
);
179 bool write(const uint8_t *src
, uint32_t bytes
)
181 if (data
.length() + bytes
> size
)
183 uint32_t wpos
= data
.length();
184 data
.resize(wpos
+ bytes
);
185 memcpy(&data
[wpos
], src
, bytes
);
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);
215 template<class Buffer
, class TypeBuffer
= null_buffer
, bool Throw
= true>
219 TypeBuffer
*type_buffer
;
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) {}
227 write(&zero
, buffer
.write_misalignment());
229 inline void read(void *dest
, uint32_t bytes
)
231 if (!buffer
.read((uint8_t *)dest
, bytes
))
234 throw osc_read_exception();
238 memset(dest
, 0, bytes
);
242 inline void write(const void *src
, uint32_t bytes
)
244 if (!buffer
.write((const uint8_t *)src
, bytes
))
247 throw osc_write_exception();
256 type_buffer
->clear();
258 inline void write_type(char ch
)
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
)
295 s
.write_type(osc_i32
);
299 template<class Buffer
, class TypeBuffer
>
300 inline osc_stream
<Buffer
, TypeBuffer
> &
301 operator >>(osc_stream
<Buffer
, TypeBuffer
> &s
, uint32_t &val
)
308 template<class Buffer
, class TypeBuffer
>
309 inline osc_stream
<Buffer
, TypeBuffer
> &
310 operator >>(osc_stream
<Buffer
, TypeBuffer
> &s
, int32_t &val
)
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
;
323 val2
.i
= htonl(val2
.i
);
325 s
.write_type(osc_f32
);
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
;
335 val2
.i
= htonl(val2
.i
);
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());
346 s
.write_type(osc_string
);
350 template<class Buffer
, class TypeBuffer
>
351 inline osc_stream
<Buffer
, TypeBuffer
> &
352 operator >>(osc_stream
<Buffer
, TypeBuffer
> &s
, std::string
&str
)
364 if (!five
[1] || !five
[2] || !five
[3])
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
)
376 uint32_t len
= htonl(nlen
);
377 // write length in network order
378 for (uint32_t i
= 0; i
< len
; i
+= 1024)
381 uint32_t part
= std::min((uint32_t)1024, len
- i
);
383 buf
.write(tmp
, part
);
386 s
.read(&nlen
, 4 - (len
& 3));
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
);
397 // write length in network order
398 for (uint32_t i
= 0; i
< len
; i
+= 1024)
401 uint32_t part
= std::min((uint32_t)1024, len
- i
);
406 s
.write_type(osc_blob
);
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
)
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
455 std::string command
, error_msg
;
456 osc_net_exception(const char *cmd
, int _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
469 std::string command
, error_msg
;
470 osc_net_dns_exception(const char *cmd
, int _errno
= h_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
>
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 ";
525 osctl::string_buffer val
;
527 stream
<< "blob (" << val
.data
.length() << " bytes)";
532 stream
<< "unknown - cannot parse more arguments" << std::endl
;
539 stream
<< std::flush
;
540 buffer
.buffer
.seek(pos
);