liblo 0.31
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
71namespace 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/*
94 * Error handling:
95 *
96 * Define LO_USE_EXCEPTIONS to throw the following exceptions instead
97 * of aborting on error. The alternative (and default) is that
98 * assert() will crash your program in debug mode, and you should
99 * check is_valid() before operations that might break the assertion.
100 *
101 * Note that in the latter case, the program may return a C++ class
102 * that will not contain a valid liblo object, this is why
103 * LO_CHECK_AFTER does not do anything; it is up to user code to check
104 * is_valid() after constructing Server() and ServerThread(). On the
105 * contrary, when LO_USE_EXCEPTIONS is enabled, an Error exception
106 * will be thrown if the object was not successfully created.
107 *
108 * Rules:
109 *
110 * - Constructors that create underlying liblo objects shall either
111 * fail silently, depending on calling code to check is_valid(), or
112 * throw lo::Error() in the case of LO_USE_EXCEPTIONS.
113 *
114 * - Constructors that receive an existing liblo object do not throw
115 * any exceptions if the passed in object is nullptr.
116 *
117 * - All other functions shall assert() or throw lo::Invalid() if the
118 * underlying liblo object is not valid.
119 *
120 */
121
122#ifdef LO_USE_EXCEPTIONS
123 struct Invalid {};
124 struct Error {};
125#define LO_CHECK_BEFORE if (!is_valid()) throw Invalid();
126#define LO_CHECK_AFTER if (!is_valid()) throw Error();
127#else
128#include <cassert>
129#define LO_CHECK_BEFORE assert(is_valid());
130#define LO_CHECK_AFTER
131#endif
132
133 class ServerThread;
134
136 class Method
137 {
138 public:
139 Method(lo_method m) : method(m) {}
140 operator lo_method() const
141 { return method; }
142 protected:
143 lo_method method;
144 };
145
149 {
150 public:
151 Address(const string_type &host, const num_string_type &port,
152 int proto=LO_UDP)
153 { address = lo_address_new_with_proto(proto, host, port); owned=true;
154 LO_CHECK_AFTER; }
155
156 Address(const string_type &url)
157 { address = lo_address_new_from_url(url); owned=true; LO_CHECK_AFTER; }
158
159 Address(lo_address a, bool _owned=true)
160 { address = a; owned=_owned; LO_CHECK_AFTER; }
161
162 ~Address()
163 { if (address && owned) lo_address_free(address); }
164
165 Address& operator=(Address b) { b.swap(*this); return *this; }
166 void swap(Address& b) throw () { std::swap(this->address, b.address); }
167
168 bool is_valid() const { return address!=nullptr; }
169
170 int ttl() const
171 { LO_CHECK_BEFORE; return lo_address_get_ttl(address); }
172
173 void set_ttl(int ttl)
174 { LO_CHECK_BEFORE; lo_address_set_ttl(address, ttl); }
175
176 int send(const string_type &path) const
177 { LO_CHECK_BEFORE; return lo_send(address, path, ""); }
178
179 // In these functions we append "$$" to the type string, which
180 // simply instructs lo_message_add_varargs() not to use
181 // LO_MARKER checking at the end of the argument list.
182 int send(const string_type &path, const string_type type, ...) const
183 {
184 LO_CHECK_BEFORE;
185 va_list q;
186 va_start(q, type);
188 std::string t = type.s() + "$$";
189 lo_message_add_varargs(m, t.c_str(), q);
190 int r = lo_send_message(address, path, m);
192 va_end(q);
193 return r;
194 }
195
196 int send(lo_timetag ts, const string_type &path,
197 const string_type type, ...) const
198 {
199 LO_CHECK_BEFORE;
200 va_list q;
201 va_start(q, type);
203 std::string t = std::string(type) + "$$";
204 lo_message_add_varargs(m, t.c_str(), q);
205 lo_bundle b = lo_bundle_new(ts);
206 lo_bundle_add_message(b, path, m);
207 int r = lo_send_bundle(address, b);
209 va_end(q);
210 return r;
211 }
212
213 int send(const string_type &path, lo_message m) const
214 { LO_CHECK_BEFORE; return lo_send_message(address, path, m); }
215
216 int send(lo_bundle b)
217 { LO_CHECK_BEFORE; return lo_send_bundle(address, b); }
218
219 int send_from(lo::ServerThread &from, const string_type &path,
220 const string_type type, ...) const;
221
222 int send_from(lo_server from, const string_type &path,
223 const string_type type, ...) const
224 {
225 LO_CHECK_BEFORE;
226 va_list q;
227 va_start(q, type);
229 std::string t = std::string(type) + "$$";
230 lo_message_add_varargs(m, t.c_str(), q);
231 int r = lo_send_message_from(address, from, path, m);
233 va_end(q);
234 return r;
235 }
236
237 int send_from(lo_server from, lo_timetag ts,
238 const string_type &path,
239 const string_type type, ...) const
240 {
241 LO_CHECK_BEFORE;
242 va_list q;
243 va_start(q, type);
245 std::string t = std::string(type) + "$$";
246 lo_message_add_varargs(m, t.c_str(), q);
247 lo_bundle b = lo_bundle_new(ts);
248 lo_bundle_add_message(b, path, m);
249 int r = lo_send_bundle_from(address, from, b);
251 va_end(q);
252 return r;
253 }
254
255 int send_from(lo_server from, const string_type &path, lo_message m) const
256 { LO_CHECK_BEFORE; return lo_send_message_from(address, from, path, m); }
257
258 int send_from(lo::ServerThread &from, lo_bundle b) const;
259
260 int send_from(lo_server from, lo_bundle b) const
261 { LO_CHECK_BEFORE; return lo_send_bundle_from(address, from, b); }
262
263 int get_errno() const
264 { LO_CHECK_BEFORE; return lo_address_errno(address); }
265
266 std::string errstr() const
267 { LO_CHECK_BEFORE; auto s(lo_address_errstr(address)); return std::string(s?s:""); }
268
269 std::string hostname() const
270 { LO_CHECK_BEFORE; auto s(lo_address_get_hostname(address)); return std::string(s?s:""); }
271
272 std::string port() const
273 { LO_CHECK_BEFORE; auto s(lo_address_get_port(address)); return std::string(s?s:""); }
274
275 int protocol() const
276 { LO_CHECK_BEFORE; return lo_address_get_protocol(address); }
277
278 std::string url() const
279 {
280 LO_CHECK_BEFORE;
281 char* s(lo_address_get_url(address));
282 std::string result(s?s:"");
283 free(s);
284 return result;
285 }
286
287 std::string iface() const
288 { LO_CHECK_BEFORE; auto s(lo_address_get_iface(address)); return std::string(s?s:""); }
289
290 void set_iface(const string_type &iface, const string_type &ip)
291 { LO_CHECK_BEFORE; lo_address_set_iface(address, iface, ip); }
292
293 int set_tcp_nodelay(int enable)
294 { LO_CHECK_BEFORE; return lo_address_set_tcp_nodelay(address, enable); }
295
296 int set_stream_slip(int enable)
297 { LO_CHECK_BEFORE; return lo_address_set_stream_slip(address, enable); }
298
299 operator lo_address() const
300 { return address; }
301
302 protected:
303 lo_address address;
304 bool owned;
305 };
306
309 {
310 public:
311 Message()
312 : message(lo_message_new()) { if (message) lo_message_incref(message); LO_CHECK_AFTER; }
313
315 : message(m) { if (m) { lo_message_incref(m); } }
316
317 Message(const Message &m)
318 : message(m.message) { if (m.message)
319 lo_message_incref(m.message); }
320
321 Message(const string_type types, ...)
322 {
323 message = lo_message_new();
324 if (message) {
325 lo_message_incref(message);
326 va_list q;
327 va_start(q, types);
328 std::string t(std::string(types)+"$$");
329 add_varargs(t.c_str(), q);
330 va_end(q);
331 }
332 LO_CHECK_AFTER;
333 }
334
335 ~Message()
336 { if (message) lo_message_free(message); }
337
338 Message& operator=(Message m) { m.swap(*this); return *this; }
339 void swap(Message& m) throw () { std::swap(this->message, m.message); }
340
341 bool is_valid() const { return message!=nullptr; }
342
343 int add(const string_type types, ...)
344 {
345 LO_CHECK_BEFORE;
346 va_list q;
347 va_start(q, types);
348 std::string t(std::string(types)+"$$");
349 int ret = add_varargs(t.c_str(), q);
350 va_end(q);
351 return ret;
352 }
353
354 int add_varargs(const string_type &types, va_list ap)
355 { LO_CHECK_BEFORE; return lo_message_add_varargs(message, types, ap); }
356
357 int add_int32(int32_t a)
358 { LO_CHECK_BEFORE; return lo_message_add_int32(message, a); }
359
360 int add_float(float a)
361 { LO_CHECK_BEFORE; return lo_message_add_float(message, a); }
362
363 int add_string(const string_type &a)
364 { LO_CHECK_BEFORE; return lo_message_add_string(message, a); }
365
366 int add_blob(lo_blob a)
367 { LO_CHECK_BEFORE; return lo_message_add_blob(message, a); }
368
369 int add_int64(int64_t a)
370 { LO_CHECK_BEFORE; return lo_message_add_int64(message, a); }
371
372 int add_timetag(lo_timetag a)
373 { LO_CHECK_BEFORE; return lo_message_add_timetag(message, a); }
374
375 int add_double(double a)
376 { LO_CHECK_BEFORE; return lo_message_add_double(message, a); }
377
378 int add_symbol(const string_type &a)
379 { LO_CHECK_BEFORE; return lo_message_add_symbol(message, a); }
380
381 int add_char(char a)
382 { LO_CHECK_BEFORE; return lo_message_add_char(message, a); }
383
384 int add_midi(uint8_t a[4])
385 { LO_CHECK_BEFORE; return lo_message_add_midi(message, a); }
386
387 int add_bool(bool b)
388 { LO_CHECK_BEFORE;
389 if (b)
390 return lo_message_add_true(message);
391 else
392 return lo_message_add_false(message); }
393
394 int add_true()
395 { LO_CHECK_BEFORE; return lo_message_add_true(message); }
396
397 int add_false()
398 { LO_CHECK_BEFORE; return lo_message_add_false(message); }
399
400 int add_nil()
401 { LO_CHECK_BEFORE; return lo_message_add_nil(message); }
402
403 int add_infinitum()
404 { LO_CHECK_BEFORE; return lo_message_add_infinitum(message); }
405
406 // Note, for polymorphic versions of "add", below, we can't do
407 // this for "string" or "symbol" types, since it is ambiguous
408 // with "add(types, ...)" above.
409
410 int add(int32_t a)
411 { LO_CHECK_BEFORE; return lo_message_add_int32(message, a); }
412
413 int add(float a)
414 { LO_CHECK_BEFORE; return lo_message_add_float(message, a); }
415
416 int add(lo_blob a)
417 { LO_CHECK_BEFORE; return lo_message_add_blob(message, a); }
418
419 int add(int64_t a)
420 { LO_CHECK_BEFORE; return lo_message_add_int64(message, a); }
421
422 int add(lo_timetag a)
423 { LO_CHECK_BEFORE; return lo_message_add_timetag(message, a); }
424
425 int add(double a)
426 { LO_CHECK_BEFORE; return lo_message_add_double(message, a); }
427
428 int add(char a)
429 { LO_CHECK_BEFORE; return lo_message_add_char(message, a); }
430
431 int add(uint8_t a[4])
432 { LO_CHECK_BEFORE; return lo_message_add_midi(message, a); }
433
434 int add(bool b)
435 { LO_CHECK_BEFORE;
436 if (b)
437 return lo_message_add_true(message);
438 else
439 return lo_message_add_false(message); }
440
441 Address source() const
442 { LO_CHECK_BEFORE; return Address(lo_message_get_source(message), false); }
443
444 lo_timetag timestamp() const
445 { LO_CHECK_BEFORE; return lo_message_get_timestamp(message); }
446
447 std::string types() const
448 { LO_CHECK_BEFORE;
449 auto s(lo_message_get_types(message)); return std::string(s?s:""); }
450
451 int argc() const
452 { LO_CHECK_BEFORE; return lo_message_get_argc(message); }
453
454 lo_arg **argv() const
455 { LO_CHECK_BEFORE; return lo_message_get_argv(message); }
456
457 size_t length(const string_type &path) const
458 { LO_CHECK_BEFORE; return lo_message_length(message, path); }
459
460 void *serialise(const string_type &path, void *to, size_t *size) const
461 { LO_CHECK_BEFORE; return lo_message_serialise(message, path, to, size); }
462
463 typedef std::pair<int, Message> maybe;
464
465 static
466 maybe deserialise(void *data, size_t size)
467 { int result = 0;
468 lo_message m = lo_message_deserialise(data, size, &result);
469 return maybe(result, m); }
470
471 void print() const
472 { LO_CHECK_BEFORE; lo_message_pp(message); }
473
474 lo::Message clone() const
475 { LO_CHECK_BEFORE; return lo::Message(lo_message_clone(message)); }
476
477 operator lo_message() const
478 { return message; }
479
480 protected:
481 lo_message message;
482 };
483
485 class Server
486 {
487 public:
489 Server(lo_server s) : server(s) {}
490
492 template <typename E>
493 Server(const num_string_type &port, E&& e)
494 : Server(lo_server_new(port,
495 [](int num, const char *msg, const char *where){
496 auto h = static_cast<handler_error*>(lo_error_get_context());
497 if (h) (*h)(num, msg, where);
498 }))
499 {
500 if (server) {
501 lo_server_set_error_context(server,
502 (_error_handler = std::unique_ptr<handler>(
503 new handler_error(e))).get());
504 }
505 LO_CHECK_AFTER;
506 }
507
509 template <typename E>
510 Server(const num_string_type &port, int proto, E&& e=0)
511 : Server(lo_server_new_with_proto(port, proto,
512 [](int num, const char *msg, const char *where){
513 auto h = static_cast<handler_error*>(lo_error_get_context());
514 (*h)(num, msg, where);
515 }))
516 {
517 if (server) {
518 lo_server_set_error_context(server,
519 (_error_handler = std::unique_ptr<handler>(
520 new handler_error(e))).get());
521 }
522 LO_CHECK_AFTER;
523 }
524
527 template <typename E>
528 Server(const string_type &group, const num_string_type &port,
529 const string_type &iface=0, const string_type &ip=0, E&& e=0)
530 : Server((!iface._s || !ip._s)
531 ? lo_server_new_multicast_iface(group, port, iface, ip,
532 [](int num, const char *msg, const char *where){
533 auto h = static_cast<handler_error*>(lo_error_get_context());
534 (*h)(num, msg, where);
535 })
536 : lo_server_new_multicast(group, port,
537 [](int num, const char *msg, const char *where){
538 auto h = static_cast<handler_error*>(lo_error_get_context());
539 (*h)(num, msg, where);
540 }))
541 {
542 if (server) {
543 lo_server_set_error_context(server,
544 (_error_handler = std::unique_ptr<handler>(
545 new handler_error(e))).get());
546 }
547 LO_CHECK_AFTER;
548 }
549
551 Server(const num_string_type &port, lo_err_handler err_h=0)
552 : Server(lo_server_new(port, err_h)) { LO_CHECK_AFTER; }
553
555 Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
556 : Server(lo_server_new_with_proto(port, proto, err_h))
557 { LO_CHECK_AFTER; }
558
561 Server(const string_type &group, const num_string_type &port,
562 const string_type &iface="", const string_type &ip="", lo_err_handler err_h=0)
563 : Server((iface._s || ip._s)
564 ? lo_server_new_multicast_iface(group, port,
565 iface, ip, err_h)
566 : lo_server_new_multicast(group, port, err_h))
567 { LO_CHECK_AFTER; }
568
570 virtual ~Server()
571 { if (server) lo_server_free(server); }
572
573 bool is_valid() const { return server!=nullptr; }
574
575 // Regular old liblo method handlers
576
579 Method add_method(const string_type &path, const string_type &types,
580 lo_method_handler h, void *data) const
581 { LO_CHECK_BEFORE; return _add_method(path, types, h, data); }
582
583 // Alternative callback prototypes
584
587 LO_ADD_METHOD( (const char*, const char*, lo_arg**, int),
588 ((char*)0, (char*)0, (lo_arg**)0, (int)0),
589 (path, types, argv, argc) );
590
593 LO_ADD_METHOD( (const char*, lo_arg**, int),
594 ((char*)0, (lo_arg**)0, (int)0),
595 (types, argv, argc) );
596 LO_ADD_METHOD( (const char*, lo_arg**, int, const Message&),
597 ((char*)0, (lo_arg**)0, (int)0, Message((lo_message)0)),
598 (types, argv, argc, Message(msg)) );
599 LO_ADD_METHOD( (const char*, const Message&),
600 ((char*)0, Message((lo_message)0)),
601 (path, Message(msg)) );
602 LO_ADD_METHOD( (lo_arg**, int), ((lo_arg**)0, (int)0), (argv, argc) )
603 LO_ADD_METHOD( (lo_arg**, int, const Message& ),
604 ((lo_arg**)0, (int)0, Message((lo_message)0)),
605 (argv, argc, Message(msg)) );
606 LO_ADD_METHOD( (const Message&),
607 (Message((lo_message)0)),
608 (Message(msg)) );
609 LO_ADD_METHOD( (), (), () );
610
611 int del_method(const string_type &path, const string_type &typespec)
612 {
613 LO_CHECK_BEFORE;
614 _handlers.erase(path.s() + "," + typespec.s());
615 lo_server_del_method(server, path, typespec);
616 return 0;
617 }
618
619 int del_method(const lo_method& m)
620 {
621 LO_CHECK_BEFORE;
622 for (auto &i : _handlers) {
623 std::remove_if(i.second.begin(), i.second.end(),
624 [&](std::unique_ptr<handler>& h){return h->method == m;});
625 }
626 return lo_server_del_lo_method(server, m);
627 }
628
629 int dispatch_data(void *data, size_t size)
630 { LO_CHECK_BEFORE; return lo_server_dispatch_data(server, data, size); }
631
632 int wait(int timeout)
633 { LO_CHECK_BEFORE; return lo_server_wait(server, timeout); }
634
635 int recv()
636 { LO_CHECK_BEFORE; return lo_server_recv(server); }
637
638 int recv(int timeout)
639 { LO_CHECK_BEFORE; return lo_server_recv_noblock(server, timeout); }
640
641 int add_bundle_handlers(lo_bundle_start_handler sh,
643 void *user_data)
644 {
645 LO_CHECK_BEFORE;
646 return lo_server_add_bundle_handlers(server, sh, eh, user_data);
647 }
648
649 template <typename S, typename E>
650 int add_bundle_handlers(S&& s, E&& e)
651 {
652 _bundle_handlers.reset(new std::pair<handler_bundle_start,
653 handler_bundle_end>(
654 handler_bundle_start(s),
655 handler_bundle_end(e)));
657 server,
658 [](lo_timetag time, void *user_data)->int{
659 auto h = (std::pair<handler_bundle_start,
660 handler_bundle_end>*) user_data;
661 h->first(time);
662 return 0;
663 },
664 [](void *user_data)->int{
665 auto h = (std::pair<handler_bundle_start,
666 handler_bundle_end>*) user_data;
667 h->second();
668 return 0;
669 },
670 _bundle_handlers.get());
671 }
672
673 int socket_fd() const
674 { LO_CHECK_BEFORE; return lo_server_get_socket_fd(server); }
675
676 int port() const
677 { LO_CHECK_BEFORE; return lo_server_get_port(server); }
678
679 int protocol() const
680 { LO_CHECK_BEFORE; return lo_server_get_protocol(server); }
681
682 std::string url() const
683 {
684 LO_CHECK_BEFORE;
685 char* s(lo_server_get_url(server));
686 std::string result(s?s:"");
687 free(s);
688 return result;
689 }
690
691 int enable_queue(int queue_enabled,
692 int dispatch_remaining=1)
693 { LO_CHECK_BEFORE;
694 return lo_server_enable_queue(server,
695 queue_enabled,
696 dispatch_remaining); }
697
698 int events_pending() const
699 { LO_CHECK_BEFORE; return lo_server_events_pending(server); }
700
701 double next_event_delay() const
702 { LO_CHECK_BEFORE; return lo_server_next_event_delay(server); }
703
704 operator lo_server() const
705 { return server; }
706
707 protected:
708 lo_server server;
709
710 friend class ServerThread;
711
712 struct handler { Method method; handler(Method m):method(m){} };
713 template <typename T>
714 class handler_type : public handler, public std::function<T> {
715 public: template<typename H>handler_type(H&& h, Method m=0)
716 : handler(m), std::function<T>(h) {}
717 };
718 typedef handler_type<void(int, const char *, const char *)> handler_error;
719 typedef handler_type<void(int, const std::string&, const std::string&)> handler_error_s;
720 typedef handler_type<void(lo_timetag)> handler_bundle_start;
721 typedef handler_type<void()> handler_bundle_end;
722
723 // Keep std::functions here so they are freed correctly
724 std::unordered_map<std::string,
725 std::list<std::unique_ptr<handler>>> _handlers;
726 std::unique_ptr<handler> _error_handler;
727 std::unique_ptr<std::pair<handler_bundle_start,
728 handler_bundle_end>> _bundle_handlers;
729
730 virtual Method _add_method(const char *path, const char *types,
731 lo_method_handler h, void *data) const
732 {
733 LO_CHECK_BEFORE;
734 return lo_server_add_method(server, path, types, h, data);
735 }
736 };
737
739 class ServerThread : public Server
740 {
741 public:
742 ServerThread(const num_string_type &port, lo_err_handler err_h=0)
743 : Server(0)
744 { server_thread = lo_server_thread_new(port, err_h);
745 if (server_thread)
746 server = lo_server_thread_get_server(server_thread); }
747
748 template <typename E>
749 ServerThread(const num_string_type &port, E&& e)
750 : Server(0)
751 {
752 server_thread = lo_server_thread_new(port,
753 [](int num, const char *msg, const char *where){
754 auto h = static_cast<handler_error*>(lo_error_get_context());
755 // TODO: Can't call "e" yet since error context is not yet
756 // provided, port unavailable errors will not be reported!
757 if (h) (*h)(num, msg, where);});
758 if (server_thread) {
759 server = lo_server_thread_get_server(server_thread);
760 auto h = new handler_error(e);
761 _error_handler.reset(h);
762 lo_server_thread_set_error_context(server_thread, h);
763 lo_server_set_error_context(server,
764 (_error_handler = std::unique_ptr<handler>(
765 new handler_error(e))).get());
766 }
767 LO_CHECK_AFTER;
768 }
769
770 ServerThread(const num_string_type &port, int proto, lo_err_handler err_h)
771 : Server(0)
772 { server_thread = lo_server_thread_new_with_proto(port, proto, err_h);
773 if (server_thread)
774 server = lo_server_thread_get_server(server_thread);
775 LO_CHECK_AFTER;
776 }
777
778 template <typename E>
779 ServerThread(const num_string_type &port, int proto, E&& e)
780 : Server(0)
781 {
782 server_thread = lo_server_thread_new_with_proto(port, proto,
783 [](int num, const char *msg, const char *where){
784 auto h = static_cast<handler_error*>(lo_error_get_context());
785 // TODO: Can't call "e" yet since error context is not yet
786 // provided, port unavailable errors will not be reported!
787 if (h) (*h)(num, msg, where);});
788 if (server_thread) {
789 server = lo_server_thread_get_server(server_thread);
790 auto h = new handler_error(e);
791 _error_handler.reset(h);
792 lo_server_thread_set_error_context(server_thread, h);
793 lo_server_set_error_context(server,
794 (_error_handler = std::unique_ptr<handler>(
795 new handler_error(e))).get());
796 }
797 LO_CHECK_AFTER;
798 }
799
800 ServerThread(const string_type &group, const num_string_type &port,
801 const string_type &iface, const string_type &ip,
802 lo_err_handler err_h=0) : Server(0)
803 { if (iface._s || ip._s)
804 server_thread = lo_server_thread_new_multicast_iface(group, port,
805 iface, ip, err_h);
806 else
807 server_thread = lo_server_thread_new_multicast(group, port, err_h);
808 if (server_thread)
809 server = lo_server_thread_get_server(server_thread);
810 LO_CHECK_AFTER;
811 }
812
813 virtual ~ServerThread()
814 { server = 0;
815 if (server_thread) lo_server_thread_free(server_thread); }
816
817 template <typename I, typename C>
818 auto set_callbacks(I&& init, C&& cleanup)
819 -> typename std::enable_if<
820 std::is_same<decltype(init()), int>::value, void>::type
821 {
822 LO_CHECK_BEFORE;
823 if (server_thread) {
824 _cb_handlers.reset(new handler_cb_pair(init, cleanup));
825 lo_server_thread_set_callbacks(server_thread,
826 [](lo_server_thread s, void *c){
827 auto cb = (handler_cb_pair*)c;
828 return (cb->first)();
829 },
830 [](lo_server_thread s, void *c){
831 auto cb = (handler_cb_pair*)c;
832 (cb->second)();
833 }, _cb_handlers.get());
834 }
835 }
836
837 template <typename I, typename C>
838 auto set_callbacks(I&& init, C&& cleanup)
839 -> typename std::enable_if<
840 std::is_same<decltype(init()), void>::value, void>::type
841 {
842 if (server_thread) {
843 _cb_handlers.reset(
844 (handler_cb_pair*)new handler_cb_pair_void(init, cleanup));
845 lo_server_thread_set_callbacks(server_thread,
846 [](lo_server_thread s, void *c){
847 auto cb = (handler_cb_pair_void*)c;
848 (cb->first)(); return 0;
849 },
850 [](lo_server_thread s, void *c){
851 auto cb = (handler_cb_pair_void*)c;
852 (cb->second)();
853 }, _cb_handlers.get());
854 }
855 }
856
857 void start() { LO_CHECK_BEFORE; lo_server_thread_start(server_thread); }
858 void stop() { LO_CHECK_BEFORE; lo_server_thread_stop(server_thread); }
859
860 operator lo_server_thread() const
861 { return server_thread; }
862
863 protected:
864 lo_server_thread server_thread;
865
866 typedef std::pair<handler_type<int()>,handler_type<void()>> handler_cb_pair;
867 typedef std::pair<handler_type<void()>,handler_type<void()>> handler_cb_pair_void;
868 std::unique_ptr<handler_cb_pair> _cb_handlers;
869
870 // Regular old liblo method handlers
871 virtual Method _add_method(const char *path, const char *types,
872 lo_method_handler h, void *data) const
873 {
874 LO_CHECK_BEFORE;
875 return lo_server_thread_add_method(server_thread, path, types, h, data);
876 }
877 };
878
879 // This function needed since lo::ServerThread doesn't
880 // properly auto-upcast to lo::Server -> lo_server. (Because
881 // both lo_server and lo_serverthread are typedef'd as void*)
882 inline
883 int Address::send_from(lo::ServerThread &from, const string_type &path,
884 const string_type type, ...) const
885 {
886 LO_CHECK_BEFORE;
887 va_list q;
888 va_start(q, type);
890 std::string t = std::string(type) + "$$";
891 lo_message_add_varargs(m, t.c_str(), q);
892 lo_server s = static_cast<lo::Server&>(from);
893 int r = lo_send_message_from(address, s, path, m);
895 va_end(q);
896 return r;
897 }
898
899 inline
900 int Address::send_from(lo::ServerThread &from, lo_bundle b) const
901 {
902 LO_CHECK_BEFORE;
903 lo_server s = static_cast<lo::Server&>(from);
904 return lo_send_bundle_from(address, s, b);
905 }
906
908 class Blob
909 {
910 public:
911 Blob(int32_t size, const void *data=0)
912 : blob(lo_blob_new(size, data)) { LO_CHECK_AFTER; }
913
914 template <typename T>
915 Blob(const T &t)
916 : blob(lo_blob_new(t.size()*sizeof(t[0]), &t[0])) { LO_CHECK_AFTER; }
917
918 virtual ~Blob()
919 { lo_blob_free(blob); }
920
921 Blob& operator=(Blob b) { b.swap(*this); return *this; }
922 void swap(Blob& b) throw () { std::swap(this->blob, b.blob); }
923
924 bool is_valid() const { return blob!=nullptr; }
925
926 uint32_t datasize() const
927 { LO_CHECK_BEFORE; return lo_blob_datasize(blob); }
928
929 void *dataptr() const
930 { LO_CHECK_BEFORE; return lo_blob_dataptr(blob); }
931
932 uint32_t size() const
933 { LO_CHECK_BEFORE; return lo_blobsize(blob); }
934
935 operator lo_blob() const
936 { return blob; };
937
938 protected:
939 lo_blob blob;
940 };
941
943 struct PathMsg
944 {
945 PathMsg() {}
946 PathMsg(const string_type _path, const Message& _msg)
947 : path(_path), msg(_msg) {}
948 std::string path;
949 Message msg;
950 };
951
953 class Bundle
954 {
955 public:
956 template <typename T>
957 struct ElementT
958 {
959 ElementT()
960 : type((lo_element_type)0), pm("", 0), bundle((lo_bundle)0) {}
961 ElementT(const string_type _path, const Message& _msg)
962 : type(LO_ELEMENT_MESSAGE),
963 pm(PathMsg(_path, _msg)),
964 bundle((lo_bundle)0) {}
965 ElementT(const T& _bundle)
966 : type(LO_ELEMENT_BUNDLE), pm("", 0), bundle(_bundle) {}
967 lo_element_type type;
968 PathMsg pm;
969 T bundle;
970 };
971 typedef ElementT<Bundle> Element;
972
974 if (bundle) lo_bundle_incref(bundle);
975 LO_CHECK_AFTER; }
976
978 : bundle(lo_bundle_new(tt)) { if (bundle) lo_bundle_incref(bundle);
979 LO_CHECK_AFTER; }
980
982 : bundle(b) { if (b) { lo_bundle_incref(b); } }
983
984 Bundle(const string_type &path, lo_message m,
986 : bundle(lo_bundle_new(tt))
987 {
988 if (bundle) {
989 lo_bundle_incref(bundle);
990 lo_bundle_add_message(bundle, path, m);
991 }
992 LO_CHECK_AFTER;
993 }
994
995 Bundle(const std::initializer_list<Element> &elements,
997 : bundle(lo_bundle_new(tt))
998 {
999 if (bundle) {
1000 lo_bundle_incref(bundle);
1001 for (auto const &e : elements) {
1002 if (e.type == LO_ELEMENT_MESSAGE) {
1003 lo_bundle_add_message(bundle, e.pm.path.c_str(), e.pm.msg);
1004 }
1005 else if (e.type == LO_ELEMENT_BUNDLE) {
1006 lo_bundle_add_bundle(bundle, e.bundle);
1007 }
1008 }
1009 }
1010 LO_CHECK_AFTER;
1011 }
1012
1013 Bundle(const Bundle &b)
1014 : Bundle((lo_bundle)b) {}
1015
1016 ~Bundle()
1017 { if (bundle) lo_bundle_free_recursive(bundle); }
1018
1019 Bundle& operator=(Bundle b) { b.swap(*this); return *this; }
1020 void swap(Bundle& b) throw () { std::swap(this->bundle, b.bundle); }
1021
1022 bool is_valid() const { return bundle!=nullptr; }
1023
1024 int add(const string_type &path, lo_message m)
1025 { LO_CHECK_BEFORE; return lo_bundle_add_message(bundle, path, m); }
1026
1027 int add(const lo_bundle b)
1028 { LO_CHECK_BEFORE; return lo_bundle_add_bundle(bundle, b); }
1029
1030 size_t length() const
1031 { LO_CHECK_BEFORE; return lo_bundle_length(bundle); }
1032
1033 unsigned int count() const
1034 { LO_CHECK_BEFORE; return lo_bundle_count(bundle); }
1035
1036 lo_message get_message(int index, const char **path=0) const
1037 { LO_CHECK_BEFORE; return lo_bundle_get_message(bundle, index, path); }
1038
1039 Message get_message(int index, std::string &path) const
1040 { LO_CHECK_BEFORE;
1041 const char *p;
1042 lo_message m=lo_bundle_get_message(bundle, index, &p);
1043 path = p?p:0;
1044 return Message(m); }
1045
1046 PathMsg get_message(int index) const
1047 { LO_CHECK_BEFORE;
1048 const char *p;
1049 lo_message m = lo_bundle_get_message(bundle, index, &p);
1050 return PathMsg(p?p:0, m); }
1051
1052 Bundle get_bundle(int index) const
1053 { LO_CHECK_BEFORE; return lo_bundle_get_bundle(bundle, index); }
1054
1055 Element get_element(int index, const char **path=0) const
1056 {
1057 LO_CHECK_BEFORE;
1058 switch (lo_bundle_get_type(bundle, index)) {
1059 case LO_ELEMENT_MESSAGE: {
1060 const char *p;
1061 lo_message m = lo_bundle_get_message(bundle, index, &p);
1062 return Element(p, m);
1063 }
1064 case LO_ELEMENT_BUNDLE:
1065 return Element(lo_bundle_get_bundle(bundle, index));
1066 default:
1067 return Element();
1068 }
1069 }
1070
1071 lo_timetag timestamp()
1072 { LO_CHECK_BEFORE; return lo_bundle_get_timestamp(bundle); }
1073
1074 void *serialise(void *to, size_t *size) const
1075 { LO_CHECK_BEFORE; return lo_bundle_serialise(bundle, to, size); }
1076
1077 void print() const
1078 { LO_CHECK_BEFORE; lo_bundle_pp(bundle); }
1079
1080 operator lo_bundle() const
1081 { return bundle; }
1082
1083 protected:
1084 lo_bundle bundle;
1085 };
1086
1088 inline std::string version() {
1089 char str[32];
1090 lo_version(str, 32, 0, 0, 0, 0, 0, 0, 0);
1091 return std::string(str);
1092 }
1093
1095 inline lo_timetag now() { lo_timetag tt; lo_timetag_now(&tt); return tt; }
1096
1099};
1100
1103#endif // _LO_CPP_H_
Class representing an OSC destination address, proxy for lo_address.
Definition lo_cpp.h:149
Class representing an OSC blob, proxy for lo_blob.
Definition lo_cpp.h:909
Class representing an OSC bundle, proxy for lo_bundle.
Definition lo_cpp.h:954
Class representing an OSC message, proxy for lo_message.
Definition lo_cpp.h:309
Class representing an OSC method, proxy for lo_method.
Definition lo_cpp.h:137
Class representing a server thread, proxy for lo_server_thread.
Definition lo_cpp.h:740
Class representing a local OSC server, proxy for lo_server.
Definition lo_cpp.h:486
virtual ~Server()
Definition lo_cpp.h:570
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:561
Server(const num_string_type &port, lo_err_handler err_h=0)
Definition lo_cpp.h:551
Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
Definition lo_cpp.h:555
Server(const num_string_type &port, int proto, E &&e=0)
Definition lo_cpp.h:510
Server(const num_string_type &port, E &&e)
Definition lo_cpp.h:493
LO_ADD_METHOD((const char *, lo_arg **, int),((char *) 0,(lo_arg **) 0,(int) 0),(types, argv, argc))
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:528
LO_ADD_METHOD((const char *, const char *, lo_arg **, int),((char *) 0,(char *) 0,(lo_arg **) 0,(int) 0),(path, types, argv, argc))
Server(lo_server s)
Definition lo_cpp.h:489
Method add_method(const string_type &path, const string_type &types, lo_method_handler h, void *data) const
Definition lo_cpp.h:579
lo_element_type
An enumeration of bundle element types liblo can handle.
lo_address lo_address_new_from_url(const char *url)
Create a lo_address object from an OSC URL.
int lo_address_get_ttl(lo_address t)
Get the Time-to-Live value for a given target address.
int lo_address_errno(lo_address a)
Return the error number from the last failed lo_send() or lo_address_new() call.
void lo_address_free(lo_address t)
Free the memory used by the lo_address object.
void lo_blob_free(lo_blob b)
Free the memory taken by a blob.
uint32_t lo_blob_datasize(lo_blob b)
Return the amount of valid data in a lo_blob object.
void * lo_blob_dataptr(lo_blob b)
Return a pointer to the start of the blob data to allow contents to be changed.
void lo_address_set_ttl(lo_address t, int ttl)
Set the Time-to-Live value for a given target address.
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.
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.
int lo_send(lo_address targ, const char *path, const char *type,...)
Send a OSC formatted message to the address specified.
#define LO_TT_IMMEDIATE
A timetag constant representing "now".
const char * lo_address_errstr(lo_address a)
Return the error string from the last failed lo_send() or lo_address_new() call.
lo_blob lo_blob_new(int32_t size, const void *data)
Create a new OSC blob type.
@ LO_ELEMENT_BUNDLE
@ LO_ELEMENT_MESSAGE
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....
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...
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.
size_t lo_message_length(lo_message m, const char *path)
Return the length of a message in bytes.
const char * lo_address_get_hostname(lo_address a)
Return the hostname of a lo_address object.
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_timetag lo_message_get_timestamp(lo_message m)
Returns the timestamp (lo_timetag *) of a bundled incoming message.
int lo_send_message(lo_address targ, const char *path, lo_message msg)
Send a lo_message object to target targ.
char * lo_server_get_url(lo_server s)
Return an OSC URL that can be used to contact the server.
lo_message lo_bundle_get_message(lo_bundle b, int index, const char **path)
Gets a message contained within a bundle.
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...
int lo_bundle_add_message(lo_bundle b, const char *path, lo_message m)
Adds an OSC message to an existing bundle.
lo_message lo_message_new(void)
Create a new lo_message object.
lo_address lo_message_get_source(lo_message m)
Returns the source (lo_address) of an incoming message.
uint32_t lo_blobsize(lo_blob b)
A function to calculate the amount of OSC message space required by a lo_blob object.
void lo_bundle_free_messages(lo_bundle b)
Obsolete, use lo_bundle_free_recursive instead.
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...
char * lo_message_get_types(lo_message m)
Return the message type tag string.
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_bundle lo_bundle_new(lo_timetag tt)
Create a new bundle object.
int lo_server_wait(lo_server s, int timeout)
Wait for an OSC message to be received.
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...
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_server lo_server_new_with_proto(const char *port, int proto, lo_err_handler err_h)
Create a new server instance, specifying protocol.
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...
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...
int lo_server_get_port(lo_server s)
Return the port number that the server has bound to.
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.
int lo_message_get_argc(lo_message m)
Return the message argument count.
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_arg ** lo_message_get_argv(lo_message m)
Return the message arguments. Do not free the returned data.
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.
double lo_server_next_event_delay(lo_server s)
Return the time in seconds until the next scheduled event.
int lo_server_recv_noblock(lo_server s, int timeout)
Look for an OSC message waiting to be received.
lo_server lo_server_new(const char *port, lo_err_handler err_h)
Create a new server instance.
unsigned int lo_bundle_count(lo_bundle b)
Return the number of top-level elements in a bundle.
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_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_element_type lo_bundle_get_type(lo_bundle b, int index)
Gets the element type contained within a bundle.
lo_message lo_message_clone(lo_message m)
Create a new lo_message object by cloning an already existing one.
void lo_bundle_free_recursive(lo_bundle b)
Frees the memory taken by a bundle object and its messages and nested bundles recursively.
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...
const char * lo_address_get_iface(lo_address t)
Get the name of the network interface assigned to an OSC address.
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...
int lo_message_add_varargs(lo_message m, const char *types, va_list ap)
Append a varargs list to a message.
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.
int lo_address_set_tcp_nodelay(lo_address t, int enable)
Set the TCP_NODELAY flag on outgoing TCP connections.
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...
int lo_server_dispatch_data(lo_server s, void *data, size_t size)
Dispatch a raw block of memory containing an OSC message.
size_t lo_bundle_length(lo_bundle b)
Return the length of a bundle in bytes.
int lo_address_get_protocol(lo_address a)
Return the protocol of a lo_address object.
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_bundle lo_bundle_get_bundle(lo_bundle b, int index)
Gets a nested bundle contained within a bundle.
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...
int lo_server_get_protocol(lo_server s)
Return the protocol that the server is using.
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.
int lo_server_del_lo_method(lo_server s, lo_method m)
Delete a specific OSC method from the specified server.
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...
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...
const char * lo_address_get_port(lo_address a)
Return the port/service name of a lo_address object.
char * lo_address_get_url(lo_address a)
Return a URL representing an OSC address.
int lo_send_bundle(lo_address targ, lo_bundle b)
Send a lo_bundle object to address targ.
int lo_bundle_add_bundle(lo_bundle b, lo_bundle n)
Adds an OSC bundle to an existing bundle.
void lo_server_free(lo_server s)
Free up memory used by the lo_server object.
void lo_timetag_now(lo_timetag *t)
Return a timetag for the current time.
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 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...
int lo_server_get_socket_fd(lo_server s)
Return the file descriptor of the server socket.
void lo_message_incref(lo_message m)
Add one to a message's reference count.
int lo_server_recv(lo_server s)
Block, waiting for an OSC message to be received.
lo_timetag lo_bundle_get_timestamp(lo_bundle b)
Get the timestamp associated with a bundle.
void lo_bundle_incref(lo_bundle b)
Add one to a bundle's reference count.
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.
void lo_server_del_method(lo_server s, const char *path, const char *typespec)
Delete an OSC method from the specified server.
void lo_message_pp(lo_message m)
Pretty-print a lo_message object.
void lo_bundle_pp(lo_bundle b)
Pretty-print a lo_bundle object.
lo_timetag immediate()
Return the OSC timetag representing "immediately".
Definition lo_cpp.h:1098
lo_timetag now()
Return the current time in lo_timetag format.
Definition lo_cpp.h:1095
std::string version()
Return the library version as an std::string.
Definition lo_cpp.h:1088
int lo_server_thread_stop(lo_server_thread st)
Stop the server thread.
lo_server_thread lo_server_thread_new_multicast(const char *group, const char *port, lo_err_handler err_h)
Create a new server thread to handle incoming OSC messages, and join a UDP multicast group.
int lo_server_thread_start(lo_server_thread st)
Start the server thread.
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.
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_server lo_server_thread_get_server(lo_server_thread st)
Return the lo_server for a lo_server_thread.
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_server_thread lo_server_thread_new_multicast_iface(const char *group, const char *port, const char *iface, const char *ip, lo_err_handler err_h)
Create a new server thread instance, and join a UDP multicast group, optionally specifying which netw...
void lo_server_thread_free(lo_server_thread st)
Free memory taken by a server thread.
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.
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
void * lo_server_thread
An object representing a thread containing an OSC server.
Definition lo_types.h:92
void * lo_server
An object representing an instance of an OSC server.
Definition lo_types.h:85
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
void * lo_method
An object representing an method on a server.
Definition lo_types.h:77
void * lo_blob
A object to store an opaque binary data object.
Definition lo_types.h:52
void * lo_bundle
A low-level object used to represent bundles of messages passed over OSC.
Definition lo_types.h:69
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
void * lo_address
A reference to an OSC service.
Definition lo_types.h:45
void * lo_message
A low-level object used to represent messages passed over OSC.
Definition lo_types.h:60
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
Class representing an OSC path (std::string) and lo::Message pair.
Definition lo_cpp.h:944
A structure to store OSC TimeTag values.
Union used to read values from incoming messages.