liblo: lo_cpp.h Source File

liblo 0.29

lo_cpp.h
Go to the documentation of this file.
1
2 #ifndef _LO_CPP_H_
3 #define _LO_CPP_H_
4
5 #include <lo/lo.h>
6 #include <lo/lo_throw.h>
7
8 #include <functional>
9 #include <memory>
10 #include <list>
11 #include <algorithm>
12 #include <unordered_map>
13 #include <string>
14 #include <sstream>
15 #include <initializer_list>
16
40 #define LO_ADD_METHOD_RT(ht, argtypes, args, rt, r, r1, r2) \
41 template <typename H> \
42 Method add_method(const string_type path, const string_type types, \
43 H&& h, rt* _unused=0) \
44 { \
45 std::string key(path.s() + "," + types.s()); \
46 _handlers[key].push_front( \
47 std::unique_ptr<handler>(new handler_type<r ht>(h))); \
48 lo_method m = _add_method(path, types, \
49 [](const char *path, const char *types, \
50 lo_arg **argv, int argc, void *msg, \
51 void *data)->int \
52 { \
53 r1 (*static_cast<handler_type<r ht>*>(data)) args; \
54 r2; \
55 }, _handlers[key].front().get()); \
56 _handlers[key].front()->method = m; \
57 return m; \
58 }
59
60 #define RT_INT(argtypes) \
61 typename std::enable_if<std::is_same<decltype(h argtypes), int>::value, void>::type
62 #define RT_VOID(argtypes) \
63 typename std::enable_if<std::is_same<decltype(h argtypes), void>::value, void>::type
64
65 #define LO_ADD_METHOD(ht, argtypes, args) \
66 LO_ADD_METHOD_RT(ht, argtypes, args, \
67 RT_INT(argtypes), int, return,); \
68 LO_ADD_METHOD_RT(ht, argtypes, args, \
69 RT_VOID(argtypes), void, , return 0)
70
71 namespace lo {
72
73 // Helper classes to allow polymorphism on "const char *",
74 // "std::string", and "int".
75 class string_type {
76 public:
77 string_type(const char *s=0) { _s = s; }
78 string_type(const std::string &s) { _s = s.c_str(); }
79 operator const char*() const { return _s; }
80 std::string s() const { return _s?_s:""; }
81 const char *_s;
82 };
83
84 class num_string_type : public string_type {
85 public:
86 num_string_type(const char *s) : string_type(s) {}
87 num_string_type(const std::string &s) : string_type(s) {}
88 num_string_type(int n) { std::ostringstream ss; ss << n;
89 _p.reset(new std::string(ss.str())); _s = _p->c_str(); }
90 std::unique_ptr<std::string> _p;
91 };
92
93 class ServerThread;
94
96 class Method
97 {
98 public:
99 Method(lo_method m) : method(m) {}
100 operator lo_method() const
101 { return method; }
102 protected:
103 lo_method method;
104 };
105
108 class Address
109 {
110 public:
111 Address(const string_type &host, const num_string_type &port,
112 int proto=LO_UDP)
113 { address = lo_address_new_with_proto(proto, host, port); owned=true; }
114
115 Address(const string_type &url)
116 { address = lo_address_new_from_url(url); owned=true; }
117
118 Address(lo_address a, bool _owned=true)
119 { address = a; owned=_owned; }
120
121 ~Address()
122 { if (address && owned) lo_address_free(address); }
123
124 Address& operator=(Address b) { b.swap(*this); return *this; }
125 void swap(Address& b) throw () { std::swap(this->address, b.address); }
126
127 int ttl() const
128 { return lo_address_get_ttl(address); }
129
130 void set_ttl(int ttl)
131 { lo_address_set_ttl(address, ttl); }
132
133 int send(const string_type &path) const
134 { return lo_send(address, path, ""); }
135
136 // In these functions we append "$$" to the type string, which
137 // simply instructs lo_message_add_varargs() not to use
138 // LO_MARKER checking at the end of the argument list.
139 int send(const string_type &path, const string_type type, ...) const
140 {
141 va_list q;
142 va_start(q, type);
143 lo_message m = lo_message_new();
144 std::string t = type.s() + "$$";
145 lo_message_add_varargs(m, t.c_str(), q);
146 int r = lo_send_message(address, path, m);
147 lo_message_free(m);
148 return r;
149 }
150
151 int send(lo_timetag ts, const string_type &path,
152 const string_type type, ...) const
153 {
154 va_list q;
155 va_start(q, type);
156 lo_message m = lo_message_new();
157 std::string t = std::string(type) + "$$";
158 lo_message_add_varargs(m, t.c_str(), q);
159 lo_bundle b = lo_bundle_new(ts);
160 lo_bundle_add_message(b, path, m);
161 int r = lo_send_bundle(address, b);
162 lo_bundle_free_messages(b);
163 return r;
164 }
165
166 int send(const string_type &path, lo_message m) const
167 { return lo_send_message(address, path, m); }
168
169 int send(lo_bundle b)
170 { return lo_send_bundle(address, b); }
171
172 int send_from(lo::ServerThread &from, const string_type &path,
173 const string_type type, ...) const;
174
175 int send_from(lo_server from, const string_type &path,
176 const string_type type, ...) const
177 {
178 va_list q;
179 va_start(q, type);
180 lo_message m = lo_message_new();
181 std::string t = std::string(type) + "$$";
182 lo_message_add_varargs(m, t.c_str(), q);
183 int r = lo_send_message_from(address, from, path, m);
184 lo_message_free(m);
185 return r;
186 }
187
188 int send_from(lo_server from, lo_timetag ts,
189 const string_type &path,
190 const string_type type, ...) const
191 {
192 va_list q;
193 va_start(q, type);
194 lo_message m = lo_message_new();
195 std::string t = std::string(type) + "$$";
196 lo_message_add_varargs(m, t.c_str(), q);
197 lo_bundle b = lo_bundle_new(ts);
198 lo_bundle_add_message(b, path, m);
199 int r = lo_send_bundle_from(address, from, b);
200 lo_bundle_free_messages(b);
201 return r;
202 }
203
204 int send_from(lo_server from, const string_type &path, lo_message m) const
205 { return lo_send_message_from(address, from, path, m); }
206
207 int send_from(lo::ServerThread &from, lo_bundle b) const;
208
209 int send_from(lo_server from, lo_bundle b) const
210 { return lo_send_bundle_from(address, from, b); }
211
212 int get_errno() const
213 { return lo_address_errno(address); }
214
215 std::string errstr() const
216 { auto s(lo_address_errstr(address)); return std::string(s?s:""); }
217
218 std::string hostname() const
219 { auto s(lo_address_get_hostname(address)); return std::string(s?s:""); }
220
221 std::string port() const
222 { auto s(lo_address_get_port(address)); return std::string(s?s:""); }
223
224 int protocol() const
225 { return lo_address_get_protocol(address); }
226
227 std::string url() const
228 { auto s(lo_address_get_url(address)); return std::string(s?s:""); }
229
230 std::string iface() const
231 { auto s(lo_address_get_iface(address)); return std::string(s?s:""); }
232
233 void set_iface(const string_type &iface, const string_type &ip)
234 { lo_address_set_iface(address, iface, ip); }
235
236 int set_tcp_nodelay(int enable)
237 { return lo_address_set_tcp_nodelay(address, enable); }
238
239 int set_stream_slip(int enable)
240 { return lo_address_set_stream_slip(address, enable); }
241
242 operator lo_address() const
243 { return address; }
244
245 protected:
246 lo_address address;
247 bool owned;
248 };
249
251 class Message
252 {
253 public:
254 Message()
255 : message(lo_message_new()) { lo_message_incref(message); }
256
257 Message(lo_message m)
258 : message(m) { if (m) { lo_message_incref(m); } }
259
260 Message(const Message &m)
261 : message(m.message) { if (m.message)
262 lo_message_incref(m.message); }
263
264 Message(const string_type types, ...)
265 {
266 message = lo_message_new();
267 lo_message_incref(message);
268 va_list q;
269 va_start(q, types);
270 std::string t(std::string(types)+"$$");
271 add_varargs(t.c_str(), q);
272 }
273
274 ~Message()
275 { if (message) lo_message_free(message); }
276
277 Message& operator=(Message m) { m.swap(*this); return *this; }
278 void swap(Message& m) throw () { std::swap(this->message, m.message); }
279
280 int add(const string_type types, ...)
281 {
282 va_list q;
283 va_start(q, types);
284 std::string t(std::string(types)+"$$");
285 return add_varargs(t.c_str(), q);
286 }
287
288 int add_varargs(const string_type &types, va_list ap)
289 { return lo_message_add_varargs(message, types, ap); }
290
291 int add_int32(int32_t a)
292 { return lo_message_add_int32(message, a); }
293
294 int add_float(float a)
295 { return lo_message_add_float(message, a); }
296
297 int add_string(const string_type &a)
298 { return lo_message_add_string(message, a); }
299
300 int add_blob(lo_blob a)
301 { return lo_message_add_blob(message, a); }
302
303 int add_int64(int64_t a)
304 { return lo_message_add_int64(message, a); }
305
306 int add_timetag(lo_timetag a)
307 { return lo_message_add_timetag(message, a); }
308
309 int add_double(double a)
310 { return lo_message_add_double(message, a); }
311
312 int add_symbol(const string_type &a)
313 { return lo_message_add_symbol(message, a); }
314
315 int add_char(char a)
316 { return lo_message_add_char(message, a); }
317
318 int add_midi(uint8_t a[4])
319 { return lo_message_add_midi(message, a); }
320
321 int add_bool(bool b)
322 { if (b)
323 return lo_message_add_true(message);
324 else
325 return lo_message_add_false(message); }
326
327 int add_true()
328 { return lo_message_add_true(message); }
329
330 int add_false()
331 { return lo_message_add_false(message); }
332
333 int add_nil()
334 { return lo_message_add_nil(message); }
335
336 int add_infinitum()
337 { return lo_message_add_infinitum(message); }
338
339 // Note, for polymorphic versions of "add", below, we can't do
340 // this for "string" or "symbol" types, since it is ambiguous
341 // with "add(types, ...)" above.
342
343 int add(int32_t a)
344 { return lo_message_add_int32(message, a); }
345
346 int add(float a)
347 { return lo_message_add_float(message, a); }
348
349 int add(lo_blob a)
350 { return lo_message_add_blob(message, a); }
351
352 int add(int64_t a)
353 { return lo_message_add_int64(message, a); }
354
355 int add(lo_timetag a)
356 { return lo_message_add_timetag(message, a); }
357
358 int add(double a)
359 { return lo_message_add_double(message, a); }
360
361 int add(char a)
362 { return lo_message_add_char(message, a); }
363
364 int add(uint8_t a[4])
365 { return lo_message_add_midi(message, a); }
366
367 int add(bool b)
368 { if (b)
369 return lo_message_add_true(message);
370 else
371 return lo_message_add_false(message); }
372
373 Address source() const
374 { return Address(lo_message_get_source(message), false); }
375
376 lo_timetag timestamp() const
377 { return lo_message_get_timestamp(message); }
378
379 std::string types() const
380 { auto s(lo_message_get_types(message)); return std::string(s?s:""); }
381
382 int argc() const
383 { return lo_message_get_argc(message); }
384
385 lo_arg **argv() const
386 { return lo_message_get_argv(message); }
387
388 size_t length(const string_type &path) const
389 { return lo_message_length(message, path); }
390
391 void *serialise(const string_type &path, void *to, size_t *size) const
392 { return lo_message_serialise(message, path, to, size); }
393
394 typedef std::pair<int, Message> maybe;
395
396 static
397 maybe deserialise(void *data, size_t size)
398 { int result = 0;
399 lo_message m = lo_message_deserialise(data, size, &result);
400 return maybe(result, m); }
401
402 void print() const
403 { lo_message_pp(message); }
404
405 lo::Message clone() const
406 { return lo::Message(lo_message_clone(message)); }
407
408 operator lo_message() const
409 { return message; }
410
411 protected:
412 lo_message message;
413 };
414
416 class Server
417 {
418 public:
420 Server(lo_server s) : server(s) {}
421
423 template <typename E>
424 Server(const num_string_type &port, E&& e)
425 : Server(lo_server_new(port,
426 [](int num, const char *msg, const char *where){
427 auto h = static_cast<handler_error*>(lo_error_get_context());
428 if (h) (*h)(num, msg, where);
429 }))
430 {
431 if (server) {
432 lo_server_set_error_context(server,
433 (_error_handler = std::unique_ptr<handler>(
434 new handler_error(e))).get());
435 }
436 }
437
439 template <typename E>
440 Server(const num_string_type &port, int proto, E&& e=0)
441 : Server(lo_server_new_with_proto(port, proto,
442 [](int num, const char *msg, const char *where){
443 auto h = static_cast<handler_error*>(lo_error_get_context());
444 (*h)(num, msg, where);
445 }))
446 {
447 if (server) {
448 lo_server_set_error_context(server,
449 (_error_handler = std::unique_ptr<handler>(
450 new handler_error(e))).get());
451 }
452 }
453
456 template <typename E>
457 Server(const string_type &group, const num_string_type &port,
458 const string_type &iface=0, const string_type &ip=0, E&& e=0)
459 : Server((!iface._s || !ip._s)
460 ? lo_server_new_multicast_iface(group, port, iface, ip,
461 [](int num, const char *msg, const char *where){
462 auto h = static_cast<handler_error*>(lo_error_get_context());
463 (*h)(num, msg, where);
464 })
465 : lo_server_new_multicast(group, port,
466 [](int num, const char *msg, const char *where){
467 auto h = static_cast<handler_error*>(lo_error_get_context());
468 (*h)(num, msg, where);
469 }))
470 {
471 if (server) {
472 lo_server_set_error_context(server,
473 (_error_handler = std::unique_ptr<handler>(
474 new handler_error(e))).get());
475 }
476 }
477
479 Server(const num_string_type &port, lo_err_handler err_h=0)
480 : Server(lo_server_new(port, err_h)) {}
481
483 Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
484 : Server(lo_server_new_with_proto(port, proto, err_h)) {}
485
488 Server(const string_type &group, const num_string_type &port,
489 const string_type &iface="", const string_type &ip="", lo_err_handler err_h=0)
490 : Server((iface._s || ip._s)
491 ? lo_server_new_multicast_iface(group, port,
492 iface, ip, err_h)
493 : lo_server_new_multicast(group, port, err_h)) {}
494
496 virtual ~Server()
497 { if (server) lo_server_free(server); }
498
499 bool is_valid() const { return server!=nullptr; }
500
501 // Regular old liblo method handlers
502
505 Method add_method(const string_type &path, const string_type &types,
506 lo_method_handler h, void *data) const
507 { return _add_method(path, types, h, data); }
508
509 // Alternative callback prototypes
510
513 LO_ADD_METHOD( (const char*, const char*, lo_arg**, int),
514 ((char*)0, (char*)0, (lo_arg**)0, (int)0),
515 (path, types, argv, argc) );
516
519 LO_ADD_METHOD( (const char*, lo_arg**, int),
520 ((char*)0, (lo_arg**)0, (int)0),
521 (types, argv, argc) );
522 LO_ADD_METHOD( (const char*, lo_arg**, int, const Message&),
523 ((char*)0, (lo_arg**)0, (int)0, Message((lo_message)0)),
524 (types, argv, argc, Message(msg)) );
525 LO_ADD_METHOD( (const char*, const Message&),
526 ((char*)0, Message((lo_message)0)),
527 (path, Message(msg)) );
528 LO_ADD_METHOD( (lo_arg**, int), ((lo_arg**)0, (int)0), (argv, argc) )
529 LO_ADD_METHOD( (lo_arg**, int, const Message& ),
530 ((lo_arg**)0, (int)0, Message((lo_message)0)),
531 (argv, argc, Message(msg)) );
532 LO_ADD_METHOD( (const Message&),
533 (Message((lo_message)0)),
534 (Message(msg)) );
535 LO_ADD_METHOD( (), (), () );
536
537 int del_method(const string_type &path, const string_type &typespec)
538 {
539 _handlers.erase(path.s() + "," + typespec.s());
540 lo_server_del_method(server, path, typespec);
541 return 0;
542 }
543
544 int del_method(const lo_method& m)
545 {
546 for (auto &i : _handlers) {
547 std::remove_if(i.second.begin(), i.second.end(),
548 [&](std::unique_ptr<handler>& h){return h->method == m;});
549 }
550 return lo_server_del_lo_method(server, m);
551 }
552
553 int dispatch_data(void *data, size_t size)
554 { return lo_server_dispatch_data(server, data, size); }
555
556 int wait(int timeout)
557 { return lo_server_wait(server, timeout); }
558
559 int recv()
560 { return lo_server_recv(server); }
561
562 int recv(int timeout)
563 { return lo_server_recv_noblock(server, timeout); }
564
565 int add_bundle_handlers(lo_bundle_start_handler sh,
566 lo_bundle_end_handler eh,
567 void *user_data)
568 {
569 return lo_server_add_bundle_handlers(server, sh, eh, user_data);
570 }
571
572 template <typename S, typename E>
573 int add_bundle_handlers(S&& s, E&& e)
574 {
575 _bundle_handlers.reset(new std::pair<handler_bundle_start,
576 handler_bundle_end>(
577 handler_bundle_start(s),
578 handler_bundle_end(e)));
579 return lo_server_add_bundle_handlers(
580 server,
581 [](lo_timetag time, void *user_data)->int{
582 auto h = (std::pair<handler_bundle_start,
583 handler_bundle_end>*) user_data;
584 h->first(time);
585 return 0;
586 },
587 [](void *user_data)->int{
588 auto h = (std::pair<handler_bundle_start,
589 handler_bundle_end>*) user_data;
590 h->second();
591 return 0;
592 },
593 _bundle_handlers.get());
594 }
595
596 int socket_fd() const
597 { return lo_server_get_socket_fd(server); }
598
599 int port() const
600 { return lo_server_get_port(server); }
601
602 int protocol() const
603 { return lo_server_get_protocol(server); }
604
605 std::string url() const
606 { auto s(lo_server_get_url(server)); return std::string(s?s:""); }
607
608 int enable_queue(int queue_enabled,
609 int dispatch_remaining=1)
610 { return lo_server_enable_queue(server,
611 queue_enabled,
612 dispatch_remaining); }
613
614 int events_pending() const
615 { return lo_server_events_pending(server); }
616
617 double next_event_delay() const
618 { return lo_server_next_event_delay(server); }
619
620 operator lo_server() const
621 { return server; }
622
623 protected:
624 lo_server server;
625
626 friend class ServerThread;
627
628 struct handler { Method method; handler(Method m):method(m){} };
629 template <typename T>
630 class handler_type : public handler, public std::function<T> {
631 public: template<typename H>handler_type(H&& h, Method m=0)
632 : handler(m), std::function<T>(h) {}
633 };
634 typedef handler_type<void(int, const char *, const char *)> handler_error;
635 typedef handler_type<void(int, const std::string&, const std::string&)> handler_error_s;
636 typedef handler_type<void(lo_timetag)> handler_bundle_start;
637 typedef handler_type<void()> handler_bundle_end;
638
639 // Keep std::functions here so they are freed correctly
640 std::unordered_map<std::string,
641 std::list<std::unique_ptr<handler>>> _handlers;
642 std::unique_ptr<handler> _error_handler;
643 std::unique_ptr<std::pair<handler_bundle_start,
644 handler_bundle_end>> _bundle_handlers;
645
646 virtual Method _add_method(const char *path, const char *types,
647 lo_method_handler h, void *data) const
648 {
649 return lo_server_add_method(server, path, types, h, data);
650 }
651 };
652
654 class ServerThread : public Server
655 {
656 public:
657 ServerThread(const num_string_type &port, lo_err_handler err_h=0)
658 : Server(0)
659 { server_thread = lo_server_thread_new(port, err_h);
660 if (server_thread)
661 server = lo_server_thread_get_server(server_thread); }
662
663 template <typename E>
664 ServerThread(const num_string_type &port, E&& e)
665 : Server(0)
666 {
667 server_thread = lo_server_thread_new(port,
668 [](int num, const char *msg, const char *where){
669 auto h = static_cast<handler_error*>(lo_error_get_context());
670 // TODO: Can't call "e" yet since error context is not yet
671 // provided, port unavailable errors will not be reported!
672 if (h) (*h)(num, msg, where);});
673 if (server_thread) {
674 server = lo_server_thread_get_server(server_thread);
675 auto h = new handler_error(e);
676 _error_handler.reset(h);
677 lo_server_thread_set_error_context(server_thread, h);
678 lo_server_set_error_context(server,
679 (_error_handler = std::unique_ptr<handler>(
680 new handler_error(e))).get());
681 }
682 }
683
684 ServerThread(const num_string_type &port, int proto, lo_err_handler err_h)
685 : Server(0)
686 { server_thread = lo_server_thread_new_with_proto(port, proto, err_h);
687 if (server_thread)
688 server = lo_server_thread_get_server(server_thread); }
689
690 template <typename E>
691 ServerThread(const num_string_type &port, int proto, E&& e)
692 : Server(0)
693 {
694 server_thread = lo_server_thread_new_with_proto(port, proto,
695 [](int num, const char *msg, const char *where){
696 auto h = static_cast<handler_error*>(lo_error_get_context());
697 // TODO: Can't call "e" yet since error context is not yet
698 // provided, port unavailable errors will not be reported!
699 if (h) (*h)(num, msg, where);});
700 if (server_thread) {
701 server = lo_server_thread_get_server(server_thread);
702 auto h = new handler_error(e);
703 _error_handler.reset(h);
704 lo_server_thread_set_error_context(server_thread, h);
705 lo_server_set_error_context(server,
706 (_error_handler = std::unique_ptr<handler>(
707 new handler_error(e))).get());
708 }
709 }
710
711 virtual ~ServerThread()
712 { server = 0;
713 if (server_thread) lo_server_thread_free(server_thread); }
714
715 template <typename I, typename C>
716 auto set_callbacks(I&& init, C&& cleanup)
717 -> typename std::enable_if<
718 std::is_same<decltype(init()), int>::value, void>::type
719 {
720 if (server_thread) {
721 _cb_handlers.reset(new handler_cb_pair(init, cleanup));
722 lo_server_thread_set_callbacks(server_thread,
723 [](lo_server_thread s, void *c){
724 auto cb = (handler_cb_pair*)c;
725 return (cb->first)();
726 },
727 [](lo_server_thread s, void *c){
728 auto cb = (handler_cb_pair*)c;
729 (cb->second)();
730 }, _cb_handlers.get());
731 }
732 }
733
734 template <typename I, typename C>
735 auto set_callbacks(I&& init, C&& cleanup)
736 -> typename std::enable_if<
737 std::is_same<decltype(init()), void>::value, void>::type
738 {
739 if (server_thread) {
740 _cb_handlers.reset(
741 (handler_cb_pair*)new handler_cb_pair_void(init, cleanup));
742 lo_server_thread_set_callbacks(server_thread,
743 [](lo_server_thread s, void *c){
744 auto cb = (handler_cb_pair_void*)c;
745 (cb->first)(); return 0;
746 },
747 [](lo_server_thread s, void *c){
748 auto cb = (handler_cb_pair_void*)c;
749 (cb->second)();
750 }, _cb_handlers.get());
751 }
752 }
753
754 void start() { lo_server_thread_start(server_thread); }
755 void stop() { lo_server_thread_stop(server_thread); }
756
757 operator lo_server_thread() const
758 { return server_thread; }
759
760 protected:
761 lo_server_thread server_thread;
762
763 typedef std::pair<handler_type<int()>,handler_type<void()>> handler_cb_pair;
764 typedef std::pair<handler_type<void()>,handler_type<void()>> handler_cb_pair_void;
765 std::unique_ptr<handler_cb_pair> _cb_handlers;
766
767 // Regular old liblo method handlers
768 virtual Method _add_method(const char *path, const char *types,
769 lo_method_handler h, void *data) const
770 {
771 return lo_server_thread_add_method(server_thread, path, types, h, data);
772 }
773 };
774
775 // This function needed since lo::ServerThread doesn't
776 // properly auto-upcast to lo::Server -> lo_server. (Because
777 // both lo_server and lo_serverthread are typedef'd as void*)
778 inline
779 int Address::send_from(lo::ServerThread &from, const string_type &path,
780 const string_type type, ...) const
781 {
782 va_list q;
783 va_start(q, type);
784 lo_message m = lo_message_new();
785 std::string t = std::string(type) + "$$";
786 lo_message_add_varargs(m, t.c_str(), q);
787 lo_server s = static_cast<lo::Server&>(from);
788 int r = lo_send_message_from(address, s, path, m);
789 lo_message_free(m);
790 return r;
791 }
792
793 inline
794 int Address::send_from(lo::ServerThread &from, lo_bundle b) const
795 {
796 lo_server s = static_cast<lo::Server&>(from);
797 return lo_send_bundle_from(address, s, b);
798 }
799
801 class Blob
802 {
803 public:
804 Blob(int32_t size, const void *data=0)
805 : blob(lo_blob_new(size, data)) {}
806
807 template <typename T>
808 Blob(const T &t)
809 : blob(lo_blob_new(t.size()*sizeof(t[0]), &t[0])) {}
810
811 virtual ~Blob()
812 { lo_blob_free(blob); }
813
814 Blob& operator=(Blob b) { b.swap(*this); return *this; }
815 void swap(Blob& b) throw () { std::swap(this->blob, b.blob); }
816
817 uint32_t datasize() const
818 { return lo_blob_datasize(blob); }
819
820 void *dataptr() const
821 { return lo_blob_dataptr(blob); }
822
823 uint32_t size() const
824 { return lo_blobsize(blob); }
825
826 operator lo_blob() const
827 { return blob; };
828
829 protected:
830 lo_blob blob;
831 };
832
834 struct PathMsg
835 {
836 PathMsg() {}
837 PathMsg(const string_type _path, const Message& _msg)
838 : path(_path), msg(_msg) {}
839 std::string path;
840 Message msg;
841 };
842
844 class Bundle
845 {
846 public:
847 template <typename T>
848 struct ElementT
849 {
850 ElementT()
851 : type((lo_element_type)0), pm("", 0), bundle((lo_bundle)0) {}
852 ElementT(const string_type _path, const Message& _msg)
853 : type(LO_ELEMENT_MESSAGE),
854 pm(PathMsg(_path, _msg)),
855 bundle((lo_bundle)0) {}
856 ElementT(const T& _bundle)
857 : type(LO_ELEMENT_BUNDLE), pm("", 0), bundle(_bundle) {}
858 lo_element_type type;
859 PathMsg pm;
860 T bundle;
861 };
862 typedef ElementT<Bundle> Element;
863
864 Bundle() { bundle = lo_bundle_new(LO_TT_IMMEDIATE); lo_bundle_incref(bundle); }
865
866 Bundle(lo_timetag tt)
867 : bundle(lo_bundle_new(tt)) { lo_bundle_incref(bundle); }
868
869 Bundle(lo_bundle b)
870 : bundle(b) { if (b) { lo_bundle_incref(b); } }
871
872 Bundle(const string_type &path, lo_message m,
873 lo_timetag tt=LO_TT_IMMEDIATE)
874 : bundle(lo_bundle_new(tt))
875 {
876 lo_bundle_incref(bundle);
877 lo_bundle_add_message(bundle, path, m);
878 }
879
880 Bundle(const std::initializer_list<Element> &elements,
881 lo_timetag tt=LO_TT_IMMEDIATE)
882 : bundle(lo_bundle_new(tt))
883 {
884 lo_bundle_incref(bundle);
885 for (auto const &e : elements) {
886 if (e.type == LO_ELEMENT_MESSAGE) {
887 lo_bundle_add_message(bundle, e.pm.path.c_str(), e.pm.msg);
888 }
889 else if (e.type == LO_ELEMENT_BUNDLE) {
890 lo_bundle_add_bundle(bundle, e.bundle);
891 }
892 }
893 }
894
895 Bundle(const Bundle &b)
896 : Bundle((lo_bundle)b) {}
897
898 ~Bundle()
899 { if (bundle) lo_bundle_free_recursive(bundle); }
900
901 Bundle& operator=(Bundle b) { b.swap(*this); return *this; }
902 void swap(Bundle& b) throw () { std::swap(this->bundle, b.bundle); }
903
904 int add(const string_type &path, lo_message m)
905 { return lo_bundle_add_message(bundle, path, m); }
906
907 int add(const lo_bundle b)
908 { return lo_bundle_add_bundle(bundle, b); }
909
910 size_t length() const
911 { return lo_bundle_length(bundle); }
912
913 unsigned int count() const
914 { return lo_bundle_count(bundle); }
915
916 lo_message get_message(int index, const char **path=0) const
917 { return lo_bundle_get_message(bundle, index, path); }
918
919 Message get_message(int index, std::string &path) const
920 { const char *p;
921 lo_message m=lo_bundle_get_message(bundle, index, &p);
922 path = p?p:0;
923 return Message(m); }
924
925 PathMsg get_message(int index) const
926 { const char *p;
927 lo_message m = lo_bundle_get_message(bundle, index, &p);
928 return PathMsg(p?p:0, m); }
929
930 Bundle get_bundle(int index) const
931 { return lo_bundle_get_bundle(bundle, index); }
932
933 Element get_element(int index, const char **path=0) const
934 {
935 switch (lo_bundle_get_type(bundle, index)) {
936 case LO_ELEMENT_MESSAGE: {
937 const char *p;
938 lo_message m = lo_bundle_get_message(bundle, index, &p);
939 return Element(p, m);
940 }
941 case LO_ELEMENT_BUNDLE:
942 return Element(lo_bundle_get_bundle(bundle, index));
943 default:
944 return Element();
945 }
946 }
947
948 lo_timetag timestamp()
949 { return lo_bundle_get_timestamp(bundle); }
950
951 void *serialise(void *to, size_t *size) const
952 { return lo_bundle_serialise(bundle, to, size); }
953
954 void print() const
955 { lo_bundle_pp(bundle); }
956
957 operator lo_bundle() const
958 { return bundle; }
959
960 protected:
961 lo_bundle bundle;
962 };
963
965 inline std::string version() {
966 char str[32];
967 lo_version(str, 32, 0, 0, 0, 0, 0, 0, 0);
968 return std::string(str);
969 }
970
972 inline lo_timetag now() { lo_timetag tt; lo_timetag_now(&tt); return tt; }
973
975 inline lo_timetag immediate() { return LO_TT_IMMEDIATE; }
976 };
977
980 #endif // _LO_CPP_H_
lo::Method
Class representing an OSC method, proxy for lo_method.
Definition: lo_cpp.h:96
lo_server_new_multicast
lo_server lo_server_new_multicast(const char *group, const char *port, lo_err_handler err_h)
Create a new server instance, and join a UDP multicast group.
lo_bundle_get_message
lo_message lo_bundle_get_message(lo_bundle b, int index, const char **path)
Gets a message contained within a bundle.
lo::Message
Class representing an OSC message, proxy for lo_message.
Definition: lo_cpp.h:251
lo_bundle_free_messages
void lo_bundle_free_messages(lo_bundle b)
Obsolete, use lo_bundle_free_recursive instead.
lo_message_add_char
int lo_message_add_char(lo_message m, char a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_bundle_get_timestamp
lo_timetag lo_bundle_get_timestamp(lo_bundle b)
Get the timestamp associated with a bundle.
lo_message_get_timestamp
lo_timetag lo_message_get_timestamp(lo_message m)
Returns the timestamp (lo_timetag *) of a bundled incoming message.
lo_message_add_nil
int lo_message_add_nil(lo_message m)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_server_thread_new
lo_server_thread lo_server_thread_new(const char *port, lo_err_handler err_h)
Create a new server thread to handle incoming OSC messages.
lo_message_add_blob
int lo_message_add_blob(lo_message m, lo_blob a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_message_new
lo_message lo_message_new()
Create a new lo_message object.
lo_message_clone
lo_message lo_message_clone(lo_message m)
Create a new lo_message object by cloning an already existing one.
lo.h
lo_server_new
lo_server lo_server_new(const char *port, lo_err_handler err_h)
Create a new server instance.
lo_server_thread_set_callbacks
void lo_server_thread_set_callbacks(lo_server_thread st, lo_server_thread_init_callback init, lo_server_thread_cleanup_callback cleanup, void *user_data)
Set an init and/or a cleanup function to the specifed server thread.
lo::Blob
Class representing an OSC blob, proxy for lo_blob.
Definition: lo_cpp.h:801
lo_message_get_argc
int lo_message_get_argc(lo_message m)
Return the message argument count.
lo_arg
Union used to read values from incoming messages.
Definition: lo_osc_types.h:115
lo_server_add_bundle_handlers
int lo_server_add_bundle_handlers(lo_server s, lo_bundle_start_handler sh, lo_bundle_end_handler eh, void *user_data)
Add bundle notification handlers to the specified server.
lo_element_type
lo_element_type
An enumeration of bundle element types liblo can handle.
Definition: lo_osc_types.h:59
lo_bundle_get_type
lo_element_type lo_bundle_get_type(lo_bundle b, int index)
Gets the element type contained within a bundle.
lo_bundle_add_message
int lo_bundle_add_message(lo_bundle b, const char *path, lo_message m)
Adds an OSC message to an existing bundle.
lo_bundle_incref
void lo_bundle_incref(lo_bundle b)
Add one to a bundle&#39;s reference count.
lo_address_errstr
const char * lo_address_errstr(lo_address a)
Return the error string from the last failed lo_send() or lo_address_new() call.
lo_server_enable_queue
int lo_server_enable_queue(lo_server s, int queue_enabled, int dispatch_remaining)
Toggle event queue. If queueing is enabled, timetagged messages that are sent in advance of the curre...
lo_send_bundle
int lo_send_bundle(lo_address targ, lo_bundle b)
Send a lo_bundle object to address targ.
lo_timetag
A structure to store OSC TimeTag values.
Definition: lo_osc_types.h:46
lo_message_add_timetag
int lo_message_add_timetag(lo_message m, lo_timetag a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_server_thread_start
int lo_server_thread_start(lo_server_thread st)
Start the server thread.
lo_message_add_string
int lo_message_add_string(lo_message m, const char *a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_message_add_infinitum
int lo_message_add_infinitum(lo_message m)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_server_del_method
void lo_server_del_method(lo_server s, const char *path, const char *typespec)
Delete an OSC method from the specified server.
lo::Server::Server
Server(const num_string_type &port, int proto, E &&e=0)
Definition: lo_cpp.h:440
lo::ServerThread
Class representing a server thread, proxy for lo_server_thread.
Definition: lo_cpp.h:654
lo_message_get_source
lo_address lo_message_get_source(lo_message m)
Returns the source (lo_address) of an incoming message.
lo_send_bundle_from
int lo_send_bundle_from(lo_address targ, lo_server serv, lo_bundle b)
Send a lo_bundle object to address targ from address of serv.
lo_send_message_from
int lo_send_message_from(lo_address targ, lo_server serv, const char *path, lo_message msg)
Send a lo_message object to target targ from address of serv.
lo::Server::add_method
Method add_method(const string_type &path, const string_type &types, lo_method_handler h, void *data) const
Definition: lo_cpp.h:505
lo_blob_free
void lo_blob_free(lo_blob b)
Free the memory taken by a blob.
lo_message_free
void lo_message_free(lo_message m)
Free memory allocated by lo_message_new() and any subsequent lo_message_add_int32 lo_message_add*() c...
lo::Server::Server
Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
Definition: lo_cpp.h:483
lo_bundle_new
lo_bundle lo_bundle_new(lo_timetag tt)
Create a new bundle object.
lo_message_add_double
int lo_message_add_double(lo_message m, double a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_server_free
void lo_server_free(lo_server s)
Free up memory used by the lo_server object.
lo::now
lo_timetag now()
Return the current time in lo_timetag format.
Definition: lo_cpp.h:972
lo::Server::Server
Server(const num_string_type &port, lo_err_handler err_h=0)
Definition: lo_cpp.h:479
lo_bundle_start_handler
int(* lo_bundle_start_handler)(lo_timetag time, void *user_data)
A callback function to receive notification of a bundle being dispatched by the server or server thre...
Definition: lo_types.h:155
lo::Server::Server
Server(const string_type &group, const num_string_type &port, const string_type &iface=0, const string_type &ip=0, E &&e=0)
Definition: lo_cpp.h:457
lo_message_get_argv
lo_arg ** lo_message_get_argv(lo_message m)
Return the message arguments. Do not free the returned data.
lo::immediate
lo_timetag immediate()
Return the OSC timetag representing "immediately".
Definition: lo_cpp.h:975
lo_address_new_from_url
lo_address lo_address_new_from_url(const char *url)
Create a lo_address object from an OSC URL.
LO_TT_IMMEDIATE
#define LO_TT_IMMEDIATE
A timetag constant representing "now".
Definition: lo_osc_types.h:162
lo_bundle_pp
void lo_bundle_pp(lo_bundle b)
Pretty-print a lo_bundle object.
lo_address_new_with_proto
lo_address lo_address_new_with_proto(int proto, const char *host, const char *port)
Declare an OSC destination, given IP address and port number, specifying protocol.
lo::Address
Class representing an OSC destination address, proxy for lo_address.
Definition: lo_cpp.h:108
lo_address_get_port
const char * lo_address_get_port(lo_address a)
Return the port/service name of a lo_address object.
lo::Server::LO_ADD_METHOD
LO_ADD_METHOD((const char *, const char *, lo_arg **, int),((char *) 0,(char *) 0,(lo_arg **) 0,(int) 0),(path, types, argv, argc))
lo_address_get_protocol
int lo_address_get_protocol(lo_address a)
Return the protocol of a lo_address object.
lo_server_thread_add_method
lo_method lo_server_thread_add_method(lo_server_thread st, const char *path, const char *typespec, lo_method_handler h, const void *user_data)
Add an OSC method to the specifed server thread.
lo_message_length
size_t lo_message_length(lo_message m, const char *path)
Return the length of a message in bytes.
lo_server_new_multicast_iface
lo_server lo_server_new_multicast_iface(const char *group, const char *port, const char *iface, const char *ip, lo_err_handler err_h)
Create a new server instance, and join a UDP multicast group, optionally specifying which network int...
lo_send_message
int lo_send_message(lo_address targ, const char *path, lo_message msg)
Send a lo_message object to target targ.
lo_message_add_int64
int lo_message_add_int64(lo_message m, int64_t a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo
Definition: lo_cpp.h:71
lo_bundle_serialise
void * lo_bundle_serialise(lo_bundle b, void *to, size_t *size)
Serialise the bundle object to an area of memory and return a pointer to the serialised form...
lo_method_handler
int(* lo_method_handler)(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data)
A callback function to receive notification of matching message arriving in the server or server thre...
Definition: lo_types.h:134
lo_message_add_int32
int lo_message_add_int32(lo_message m, int32_t a)
Append a data item and typechar of the specified type to a message.
lo_address_set_stream_slip
int lo_address_set_stream_slip(lo_address t, int enable)
Set outgoing stream connections (e.g., TCP) to be transmitted using the SLIP packetizing protocol...
lo_bundle_get_bundle
lo_bundle lo_bundle_get_bundle(lo_bundle b, int index)
Gets a nested bundle contained within a bundle.
lo_address_get_iface
const char * lo_address_get_iface(lo_address t)
Get the name of the network interface assigned to an OSC address.
lo_address_set_tcp_nodelay
int lo_address_set_tcp_nodelay(lo_address t, int enable)
Set the TCP_NODELAY flag on outgoing TCP connections.
lo_message_deserialise
lo_message lo_message_deserialise(void *data, size_t size, int *result)
Deserialise a raw OSC message and return a new lo_message object. Opposite of lo_message_serialise()...
lo::PathMsg
Class representing an OSC path (std::string) and lo::Message pair.
Definition: lo_cpp.h:834
lo_address_get_ttl
int lo_address_get_ttl(lo_address t)
Get the Time-to-Live value for a given target address.
lo_address_get_hostname
const char * lo_address_get_hostname(lo_address a)
Return the hostname of a lo_address object.
lo_message_add_true
int lo_message_add_true(lo_message m)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo::Server::Server
Server(lo_server s)
Definition: lo_cpp.h:420
lo_server_recv_noblock
int lo_server_recv_noblock(lo_server s, int timeout)
Look for an OSC message waiting to be received.
lo_bundle_add_bundle
int lo_bundle_add_bundle(lo_bundle b, lo_bundle n)
Adds an OSC bundle to an existing bundle.
lo_blob
void * lo_blob
A object to store an opaque binary data object.
Definition: lo_types.h:52
lo_server_get_url
char * lo_server_get_url(lo_server s)
Return an OSC URL that can be used to contact the server.
lo_address
void * lo_address
A reference to an OSC service.
Definition: lo_types.h:45
lo_server_new_with_proto
lo_server lo_server_new_with_proto(const char *port, int proto, lo_err_handler err_h)
Create a new server instance, specifying protocol.
lo_server_get_port
int lo_server_get_port(lo_server s)
Return the port number that the server has bound to.
lo::Server
Class representing a local OSC server, proxy for lo_server.
Definition: lo_cpp.h:416
lo_address_set_ttl
void lo_address_set_ttl(lo_address t, int ttl)
Set the Time-to-Live value for a given target address.
lo_server_next_event_delay
double lo_server_next_event_delay(lo_server s)
Return the time in seconds until the next scheduled event.
lo_server_thread_get_server
lo_server lo_server_thread_get_server(lo_server_thread st)
Return the lo_server for a lo_server_thread.
lo_bundle_length
size_t lo_bundle_length(lo_bundle b)
Return the length of a bundle in bytes.
lo_message_add_midi
int lo_message_add_midi(lo_message m, uint8_t a[4])
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_message_add_varargs
int lo_message_add_varargs(lo_message m, const char *types, va_list ap)
Append a varargs list to a message.
lo_address_get_url
char * lo_address_get_url(lo_address a)
Return a URL representing an OSC address.
lo::Bundle
Class representing an OSC bundle, proxy for lo_bundle.
Definition: lo_cpp.h:844
lo_server_get_socket_fd
int lo_server_get_socket_fd(lo_server s)
Return the file descriptor of the server socket.
lo_server_thread_new_with_proto
lo_server_thread lo_server_thread_new_with_proto(const char *port, int proto, lo_err_handler err_h)
Create a new server thread to handle incoming OSC messages, specifying protocol.
lo::Server::~Server
virtual ~Server()
Definition: lo_cpp.h:496
lo_server_dispatch_data
int lo_server_dispatch_data(lo_server s, void *data, size_t size)
Dispatch a raw block of memory containing an OSC message.
lo_server_thread
void * lo_server_thread
An object representing a thread containing an OSC server.
Definition: lo_types.h:92
LO_ELEMENT_BUNDLE
Definition: lo_osc_types.h:63
lo_message
void * lo_message
A low-level object used to represent messages passed over OSC.
Definition: lo_types.h:60
lo_address_free
void lo_address_free(lo_address t)
Free the memory used by the lo_address object.
lo_server_del_lo_method
int lo_server_del_lo_method(lo_server s, lo_method m)
Delete a specific OSC method from the specified server.
lo_server_events_pending
int lo_server_events_pending(lo_server s)
Return true if there are scheduled events (eg. from bundles) waiting to be dispatched by the server...
lo::Server::Server
Server(const num_string_type &port, E &&e)
Definition: lo_cpp.h:424
lo_bundle_free_recursive
void lo_bundle_free_recursive(lo_bundle b)
Frees the memory taken by a bundle object and its messages and nested bundles recursively.
lo_err_handler
void(* lo_err_handler)(int num, const char *msg, const char *where)
A callback function to receive notification of an error in a server or server thread.
Definition: lo_types.h:105
lo_server_get_protocol
int lo_server_get_protocol(lo_server s)
Return the protocol that the server is using.
lo_server_thread_stop
int lo_server_thread_stop(lo_server_thread st)
Stop the server thread.
lo_blob_new
lo_blob lo_blob_new(int32_t size, const void *data)
Create a new OSC blob type.
lo_blob_datasize
uint32_t lo_blob_datasize(lo_blob b)
Return the amount of valid data in a lo_blob object.
lo_server_recv
int lo_server_recv(lo_server s)
Block, waiting for an OSC message to be received.
LO_ELEMENT_MESSAGE
Definition: lo_osc_types.h:61
lo::Server::Server
Server(const string_type &group, const num_string_type &port, const string_type &iface="", const string_type &ip="", lo_err_handler err_h=0)
Definition: lo_cpp.h:488
lo_server
void * lo_server
An object representing an instance of an OSC server.
Definition: lo_types.h:85
lo_message_incref
void lo_message_incref(lo_message m)
Add one to a message&#39;s reference count.
lo_bundle_end_handler
int(* lo_bundle_end_handler)(void *user_data)
A callback function to receive notification of a bundle dispatch being completed by the server or ser...
Definition: lo_types.h:166
lo_timetag_now
void lo_timetag_now(lo_timetag *t)
Return a timetag for the current time.
lo_address_set_iface
int lo_address_set_iface(lo_address t, const char *iface, const char *ip)
Set the network interface to use for a given target address.
lo_message_add_symbol
int lo_message_add_symbol(lo_message m, const char *a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_message_get_types
char * lo_message_get_types(lo_message m)
Return the message type tag string.
lo_version
void lo_version(char *verstr, int verstr_size, int *major, int *minor, char *extra, int extra_size, int *lt_major, int *lt_minor, int *lt_bug)
Get information on the version of liblo current in use.
lo_server_add_method
lo_method lo_server_add_method(lo_server s, const char *path, const char *typespec, lo_method_handler h, const void *user_data)
Add an OSC method to the specifed server.
lo_message_serialise
void * lo_message_serialise(lo_message m, const char *path, void *to, size_t *size)
Serialise the lo_message object to an area of memory and return a pointer to the serialised form...
lo_bundle_count
unsigned int lo_bundle_count(lo_bundle b)
Return the number of top-level elements in a bundle.
lo_message_add_false
int lo_message_add_false(lo_message m)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_server_wait
int lo_server_wait(lo_server s, int timeout)
Wait for an OSC message to be received.
lo_address_errno
int lo_address_errno(lo_address a)
Return the error number from the last failed lo_send() or lo_address_new() call.
lo_send
int lo_send(lo_address targ, const char *path, const char *type,...)
Send a OSC formatted message to the address specified.
lo_blob_dataptr
void * lo_blob_dataptr(lo_blob b)
Return a pointer to the start of the blob data to allow contents to be changed.
lo_blobsize
uint32_t lo_blobsize(lo_blob b)
A function to calculate the amount of OSC message space required by a lo_blob object.
lo_server_thread_free
void lo_server_thread_free(lo_server_thread st)
Free memory taken by a server thread.
lo_method
void * lo_method
An object representing an method on a server.
Definition: lo_types.h:77
lo_bundle
void * lo_bundle
A low-level object used to represent bundles of messages passed over OSC.
Definition: lo_types.h:69
lo_message_add_float
int lo_message_add_float(lo_message m, float a)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_message_pp
void lo_message_pp(lo_message m)
Pretty-print a lo_message object.
lo::version
std::string version()
Return the library version as an std::string.
Definition: lo_cpp.h:965