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