liblo 0.35
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
25
44
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
162 class Address
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
322 class Message
323 {
324 public:
325 Message()
326 : message(lo_message_new()) { if (message) lo_message_incref(message); LO_CHECK_AFTER; }
327
328 Message(lo_message m)
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 Message& clear()
492 { lo_message_clear(message); return *this; }
493
494 operator lo_message() const
495 { return message; }
496
497 protected:
498 lo_message message;
499 };
500
502 class Server
503 {
504 public:
506 Server(lo_server s) : server(s) {}
507
509 template <typename E>
510 Server(const num_string_type &port, E&& e)
511 : Server(lo_server_new(port,
512 [](int num, const char *msg, const char *where){
513 auto h = static_cast<handler_error*>(lo_error_get_context());
514 if (h) (*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
526 template <typename E>
527 Server(const num_string_type &port, int proto, E&& e=0)
528 : Server(lo_server_new_with_proto(port, proto,
529 [](int num, const char *msg, const char *where){
530 auto h = static_cast<handler_error*>(lo_error_get_context());
531 (*h)(num, msg, where);
532 }))
533 {
534 if (server) {
535 lo_server_set_error_context(server,
536 (_error_handler = std::unique_ptr<handler>(
537 new handler_error(e))).get());
538 }
539 LO_CHECK_AFTER;
540 }
541
544 template <typename E>
545 Server(const string_type &group, const num_string_type &port,
546 const string_type &iface=0, const string_type &ip=0, E&& e=0)
547 : Server((!iface._s || !ip._s)
548 ? lo_server_new_multicast_iface(group, port, iface, ip,
549 [](int num, const char *msg, const char *where){
550 auto h = static_cast<handler_error*>(lo_error_get_context());
551 (*h)(num, msg, where);
552 })
553 : lo_server_new_multicast(group, port,
554 [](int num, const char *msg, const char *where){
555 auto h = static_cast<handler_error*>(lo_error_get_context());
556 (*h)(num, msg, where);
557 }))
558 {
559 if (server) {
560 lo_server_set_error_context(server,
561 (_error_handler = std::unique_ptr<handler>(
562 new handler_error(e))).get());
563 }
564 LO_CHECK_AFTER;
565 }
566
568 Server(const num_string_type &port, lo_err_handler err_h=0)
569 : Server(lo_server_new(port, err_h)) { LO_CHECK_AFTER; }
570
572 Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
573 : Server(lo_server_new_with_proto(port, proto, err_h))
574 { LO_CHECK_AFTER; }
575
578 Server(const string_type &group, const num_string_type &port,
579 const string_type &iface="", const string_type &ip="", lo_err_handler err_h=0)
580 : Server((iface._s || ip._s)
581 ? lo_server_new_multicast_iface(group, port,
582 iface, ip, err_h)
583 : lo_server_new_multicast(group, port, err_h))
584 { LO_CHECK_AFTER; }
585
587 virtual ~Server()
588 { if (server) lo_server_free(server); }
589
590 bool is_valid() const { return server!=nullptr; }
591
592 // Regular old liblo method handlers
593
596 Method add_method(const string_type &path, const string_type &types,
597 lo_method_handler h, void *data) const
598 { LO_CHECK_BEFORE; return _add_method(path, types, h, data); }
599
600 // Alternative callback prototypes
601
604 LO_ADD_METHOD( (const char*, const char*, lo_arg**, int),
605 ((char*)0, (char*)0, (lo_arg**)0, (int)0),
606 (path, types, argv, argc) );
607
610 LO_ADD_METHOD( (const char*, lo_arg**, int),
611 ((char*)0, (lo_arg**)0, (int)0),
612 (types, argv, argc) );
613 LO_ADD_METHOD( (const char*, lo_arg**, int, const Message&),
614 ((char*)0, (lo_arg**)0, (int)0, Message((lo_message)0)),
615 (types, argv, argc, Message(msg)) );
616 LO_ADD_METHOD( (const char*, const Message&),
617 ((char*)0, Message((lo_message)0)),
618 (path, Message(msg)) );
619 LO_ADD_METHOD( (lo_arg**, int), ((lo_arg**)0, (int)0), (argv, argc) )
620 LO_ADD_METHOD( (lo_arg**, int, const Message& ),
621 ((lo_arg**)0, (int)0, Message((lo_message)0)),
622 (argv, argc, Message(msg)) );
623 LO_ADD_METHOD( (const Message&),
624 (Message((lo_message)0)),
625 (Message(msg)) );
626 LO_ADD_METHOD( (), (), () );
627
628 int del_method(const string_type &path, const string_type &typespec)
629 {
630 LO_CHECK_BEFORE;
631 _handlers.erase(path.s() + "," + typespec.s());
632 lo_server_del_method(server, path, typespec);
633 return 0;
634 }
635
636 int del_method(const lo_method& m)
637 {
638 LO_CHECK_BEFORE;
639 for (auto &i : _handlers) {
640 auto it = std::remove_if(i.second.begin(), i.second.end(),
641 [&](std::unique_ptr<handler>& h){return h->method == m;});
642 i.second.erase(it, i.second.end());
643 }
644 return lo_server_del_lo_method(server, m);
645 }
646
647 int dispatch_data(void *data, size_t size)
648 { LO_CHECK_BEFORE; return lo_server_dispatch_data(server, data, size); }
649
650 int wait(int timeout)
651 { LO_CHECK_BEFORE; return lo_server_wait(server, timeout); }
652
653 int recv()
654 { LO_CHECK_BEFORE; return lo_server_recv(server); }
655
656 int recv(int timeout)
657 { LO_CHECK_BEFORE; return lo_server_recv_noblock(server, timeout); }
658
659 int add_bundle_handlers(lo_bundle_start_handler sh,
661 void *user_data)
662 {
663 LO_CHECK_BEFORE;
664 return lo_server_add_bundle_handlers(server, sh, eh, user_data);
665 }
666
667 template <typename S, typename E>
668 int add_bundle_handlers(S&& s, E&& e)
669 {
670 _bundle_handlers.reset(new std::pair<handler_bundle_start,
671 handler_bundle_end>(
672 handler_bundle_start(s),
673 handler_bundle_end(e)));
675 server,
676 [](lo_timetag time, void *user_data)->int{
677 auto h = (std::pair<handler_bundle_start,
678 handler_bundle_end>*) user_data;
679 h->first(time);
680 return 0;
681 },
682 [](void *user_data)->int{
683 auto h = (std::pair<handler_bundle_start,
684 handler_bundle_end>*) user_data;
685 h->second();
686 return 0;
687 },
688 _bundle_handlers.get());
689 }
690
691 int socket_fd() const
692 { LO_CHECK_BEFORE; return lo_server_get_socket_fd(server); }
693
694 int port() const
695 { LO_CHECK_BEFORE; return lo_server_get_port(server); }
696
697 int protocol() const
698 { LO_CHECK_BEFORE; return lo_server_get_protocol(server); }
699
700 std::string url() const
701 {
702 LO_CHECK_BEFORE;
703 char* s(lo_server_get_url(server));
704 std::string result(s?s:"");
705 free(s);
706 return result;
707 }
708
709 int enable_queue(int queue_enabled,
710 int dispatch_remaining=1)
711 { LO_CHECK_BEFORE;
712 return lo_server_enable_queue(server,
713 queue_enabled,
714 dispatch_remaining); }
715
716 int events_pending() const
717 { LO_CHECK_BEFORE; return lo_server_events_pending(server); }
718
719 double next_event_delay() const
720 { LO_CHECK_BEFORE; return lo_server_next_event_delay(server); }
721
722 operator lo_server() const
723 { return server; }
724
725 protected:
726 lo_server server;
727
728 friend class ServerThread;
729
730 struct handler { Method method; handler(Method m):method(m){} };
731 template <typename T>
732 class handler_type : public handler, public std::function<T> {
733 public: template<typename H>handler_type(H&& h, Method m=0)
734 : handler(m), std::function<T>(h) {}
735 };
736 typedef handler_type<void(int, const char *, const char *)> handler_error;
737 typedef handler_type<void(int, const std::string&, const std::string&)> handler_error_s;
738 typedef handler_type<void(lo_timetag)> handler_bundle_start;
739 typedef handler_type<void()> handler_bundle_end;
740
741 // Keep std::functions here so they are freed correctly
742 std::unordered_map<std::string,
743 std::list<std::unique_ptr<handler>>> _handlers;
744 std::unique_ptr<handler> _error_handler;
745 std::unique_ptr<std::pair<handler_bundle_start,
746 handler_bundle_end>> _bundle_handlers;
747
748 virtual Method _add_method(const char *path, const char *types,
749 lo_method_handler h, void *data) const
750 {
751 LO_CHECK_BEFORE;
752 return lo_server_add_method(server, path, types, h, data);
753 }
754 };
755
757 class ServerThread : public Server
758 {
759 public:
760 ServerThread(const num_string_type &port, lo_err_handler err_h=0)
761 : Server(0)
762 { server_thread = lo_server_thread_new(port, err_h);
763 if (server_thread)
764 server = lo_server_thread_get_server(server_thread);
765 LO_CHECK_AFTER; }
766
767 template <typename E>
768 ServerThread(const num_string_type &port, E&& e)
769 : Server(0)
770 {
771 server_thread = lo_server_thread_new(port,
772 [](int num, const char *msg, const char *where){
773 auto h = static_cast<handler_error*>(lo_error_get_context());
774 // TODO: Can't call "e" yet since error context is not yet
775 // provided, port unavailable errors will not be reported!
776 if (h) (*h)(num, msg, where);});
777 if (server_thread) {
778 server = lo_server_thread_get_server(server_thread);
779 auto h = new handler_error(e);
780 _error_handler.reset(h);
781 lo_server_thread_set_error_context(server_thread, h);
782 lo_server_set_error_context(server,
783 (_error_handler = std::unique_ptr<handler>(
784 new handler_error(e))).get());
785 }
786 LO_CHECK_AFTER;
787 }
788
789 ServerThread(const num_string_type &port, int proto, lo_err_handler err_h)
790 : Server(0)
791 { server_thread = lo_server_thread_new_with_proto(port, proto, err_h);
792 if (server_thread)
793 server = lo_server_thread_get_server(server_thread);
794 LO_CHECK_AFTER;
795 }
796
797 template <typename E>
798 ServerThread(const num_string_type &port, int proto, E&& e)
799 : Server(0)
800 {
801 server_thread = lo_server_thread_new_with_proto(port, proto,
802 [](int num, const char *msg, const char *where){
803 auto h = static_cast<handler_error*>(lo_error_get_context());
804 // TODO: Can't call "e" yet since error context is not yet
805 // provided, port unavailable errors will not be reported!
806 if (h) (*h)(num, msg, where);});
807 if (server_thread) {
808 server = lo_server_thread_get_server(server_thread);
809 auto h = new handler_error(e);
810 _error_handler.reset(h);
811 lo_server_thread_set_error_context(server_thread, h);
812 lo_server_set_error_context(server,
813 (_error_handler = std::unique_ptr<handler>(
814 new handler_error(e))).get());
815 }
816 LO_CHECK_AFTER;
817 }
818
819 ServerThread(const string_type &group, const num_string_type &port,
820 const string_type &iface, const string_type &ip,
821 lo_err_handler err_h=0) : Server(0)
822 { if (iface._s || ip._s)
823 server_thread = lo_server_thread_new_multicast_iface(group, port,
824 iface, ip, err_h);
825 else
826 server_thread = lo_server_thread_new_multicast(group, port, err_h);
827 if (server_thread)
828 server = lo_server_thread_get_server(server_thread);
829 LO_CHECK_AFTER;
830 }
831
832 virtual ~ServerThread()
833 { server = 0;
834 if (server_thread) lo_server_thread_free(server_thread); }
835
836 template <typename I, typename C>
837 auto set_callbacks(I&& init, C&& cleanup)
838 -> typename std::enable_if<
839 std::is_same<decltype(init()), int>::value, void>::type
840 {
841 LO_CHECK_BEFORE;
842 if (server_thread) {
843 _cb_handlers.reset(new handler_cb_pair(init, cleanup));
844 lo_server_thread_set_callbacks(server_thread,
845 [](lo_server_thread s, void *c){
846 auto cb = (handler_cb_pair*)c;
847 return (cb->first)();
848 },
849 [](lo_server_thread s, void *c){
850 auto cb = (handler_cb_pair*)c;
851 (cb->second)();
852 }, _cb_handlers.get());
853 }
854 }
855
856 template <typename I, typename C>
857 auto set_callbacks(I&& init, C&& cleanup)
858 -> typename std::enable_if<
859 std::is_same<decltype(init()), void>::value, void>::type
860 {
861 if (server_thread) {
862 _cb_handlers.reset(
863 (handler_cb_pair*)new handler_cb_pair_void(init, cleanup));
864 lo_server_thread_set_callbacks(server_thread,
865 [](lo_server_thread s, void *c){
866 auto cb = (handler_cb_pair_void*)c;
867 (cb->first)(); return 0;
868 },
869 [](lo_server_thread s, void *c){
870 auto cb = (handler_cb_pair_void*)c;
871 (cb->second)();
872 }, _cb_handlers.get());
873 }
874 }
875
876 void start() { LO_CHECK_BEFORE; lo_server_thread_start(server_thread); }
877 void stop() { LO_CHECK_BEFORE; lo_server_thread_stop(server_thread); }
878
879 operator lo_server_thread() const
880 { return server_thread; }
881
882 protected:
883 lo_server_thread server_thread;
884
885 typedef std::pair<handler_type<int()>,handler_type<void()>> handler_cb_pair;
886 typedef std::pair<handler_type<void()>,handler_type<void()>> handler_cb_pair_void;
887 std::unique_ptr<handler_cb_pair> _cb_handlers;
888
889 // Regular old liblo method handlers
890 virtual Method _add_method(const char *path, const char *types,
891 lo_method_handler h, void *data) const
892 {
893 LO_CHECK_BEFORE;
894 return lo_server_thread_add_method(server_thread, path, types, h, data);
895 }
896 };
897
898 // This function needed since lo::ServerThread doesn't
899 // properly auto-upcast to lo::Server -> lo_server. (Because
900 // both lo_server and lo_serverthread are typedef'd as void*)
901 inline
902 int Address::send_from(lo::ServerThread &from, const string_type &path,
903 const string_type type, ...) const
904 {
905 LO_CHECK_BEFORE;
906 va_list q;
907 va_start(q, type);
909 std::string t = std::string(type) + "$$";
910 lo_message_add_varargs(m, t.c_str(), q);
911 lo_server s = static_cast<lo::Server&>(from);
912 int r = lo_send_message_from(address, s, path, m);
914 va_end(q);
915 return r;
916 }
917
918 inline
919 int Address::send_from(lo::ServerThread &from, lo_bundle b) const
920 {
921 LO_CHECK_BEFORE;
922 lo_server s = static_cast<lo::Server&>(from);
923 return lo_send_bundle_from(address, s, b);
924 }
925
927 class Blob
928 {
929 public:
930 Blob(int32_t size, const void *data=0)
931 : blob(lo_blob_new(size, data)) { LO_CHECK_AFTER; }
932
933 template <typename T>
934 Blob(const T &t)
935 : blob(lo_blob_new(t.size()*sizeof(t[0]), &t[0])) { LO_CHECK_AFTER; }
936
937 virtual ~Blob()
938 { lo_blob_free(blob); }
939
940 Blob& operator=(Blob b) { b.swap(*this); return *this; }
941 void swap(Blob& b) throw () { std::swap(this->blob, b.blob); }
942
943 bool is_valid() const { return blob!=nullptr; }
944
945 uint32_t datasize() const
946 { LO_CHECK_BEFORE; return lo_blob_datasize(blob); }
947
948 void *dataptr() const
949 { LO_CHECK_BEFORE; return lo_blob_dataptr(blob); }
950
951 uint32_t size() const
952 { LO_CHECK_BEFORE; return lo_blobsize(blob); }
953
954 operator lo_blob() const
955 { return blob; };
956
957 protected:
958 lo_blob blob;
959 };
960
962 struct PathMsg
963 {
964 PathMsg() {}
965 PathMsg(const string_type _path, const Message& _msg)
966 : path(_path), msg(_msg) {}
967 std::string path;
968 Message msg;
969 };
970
972 class Bundle
973 {
974 public:
975 template <typename T>
976 struct ElementT
977 {
978 ElementT()
979 : type((lo_element_type)0), pm("", 0), bundle((lo_bundle)0) {}
980 ElementT(const string_type _path, const Message& _msg)
981 : type(LO_ELEMENT_MESSAGE),
982 pm(PathMsg(_path, _msg)),
983 bundle((lo_bundle)0) {}
984 ElementT(const T& _bundle)
985 : type(LO_ELEMENT_BUNDLE), pm("", 0), bundle(_bundle) {}
986 lo_element_type type;
987 PathMsg pm;
988 T bundle;
989 };
990 typedef ElementT<Bundle> Element;
991
992 Bundle() { bundle = lo_bundle_new(LO_TT_IMMEDIATE);
993 if (bundle) lo_bundle_incref(bundle);
994 LO_CHECK_AFTER; }
995
996 Bundle(lo_timetag tt)
997 : bundle(lo_bundle_new(tt)) { if (bundle) lo_bundle_incref(bundle);
998 LO_CHECK_AFTER; }
999
1000 Bundle(lo_bundle b)
1001 : bundle(b) { if (b) { lo_bundle_incref(b); } }
1002
1003 Bundle(const string_type &path, lo_message m,
1005 : bundle(lo_bundle_new(tt))
1006 {
1007 if (bundle) {
1008 lo_bundle_incref(bundle);
1009 lo_bundle_add_message(bundle, path, m);
1010 }
1011 LO_CHECK_AFTER;
1012 }
1013
1014 Bundle(const std::initializer_list<Element> &elements,
1016 : bundle(lo_bundle_new(tt))
1017 {
1018 if (bundle) {
1019 lo_bundle_incref(bundle);
1020 for (auto const &e : elements) {
1021 if (e.type == LO_ELEMENT_MESSAGE) {
1022 lo_bundle_add_message(bundle, e.pm.path.c_str(), e.pm.msg);
1023 }
1024 else if (e.type == LO_ELEMENT_BUNDLE) {
1025 lo_bundle_add_bundle(bundle, e.bundle);
1026 }
1027 }
1028 }
1029 LO_CHECK_AFTER;
1030 }
1031
1032 Bundle(const Bundle &b)
1033 : Bundle((lo_bundle)b) {}
1034
1035 ~Bundle()
1036 { if (bundle) lo_bundle_free_recursive(bundle); }
1037
1038 Bundle& operator=(Bundle b) { b.swap(*this); return *this; }
1039 void swap(Bundle& b) throw () { std::swap(this->bundle, b.bundle); }
1040
1041 bool is_valid() const { return bundle!=nullptr; }
1042
1043 int add(const string_type &path, lo_message m)
1044 { LO_CHECK_BEFORE; return lo_bundle_add_message(bundle, path, m); }
1045
1046 int add(const lo_bundle b)
1047 { LO_CHECK_BEFORE; return lo_bundle_add_bundle(bundle, b); }
1048
1049 size_t length() const
1050 { LO_CHECK_BEFORE; return lo_bundle_length(bundle); }
1051
1052 unsigned int count() const
1053 { LO_CHECK_BEFORE; return lo_bundle_count(bundle); }
1054
1055 lo_message get_message(int index, const char **path=0) const
1056 { LO_CHECK_BEFORE; return lo_bundle_get_message(bundle, index, path); }
1057
1058 Message get_message(int index, std::string &path) const
1059 { LO_CHECK_BEFORE;
1060 const char *p;
1061 lo_message m=lo_bundle_get_message(bundle, index, &p);
1062 path = p?p:0;
1063 return Message(m); }
1064
1065 PathMsg get_message(int index) const
1066 { LO_CHECK_BEFORE;
1067 const char *p;
1068 lo_message m = lo_bundle_get_message(bundle, index, &p);
1069 return PathMsg(p?p:0, m); }
1070
1071 Bundle get_bundle(int index) const
1072 { LO_CHECK_BEFORE; return lo_bundle_get_bundle(bundle, index); }
1073
1074 Element get_element(int index, const char **path=0) const
1075 {
1076 LO_CHECK_BEFORE;
1077 switch (lo_bundle_get_type(bundle, index)) {
1078 case LO_ELEMENT_MESSAGE: {
1079 const char *p;
1080 lo_message m = lo_bundle_get_message(bundle, index, &p);
1081 return Element(p, m);
1082 }
1083 case LO_ELEMENT_BUNDLE:
1084 return Element(lo_bundle_get_bundle(bundle, index));
1085 default:
1086 return Element();
1087 }
1088 }
1089
1090 lo_timetag timestamp()
1091 { LO_CHECK_BEFORE; return lo_bundle_get_timestamp(bundle); }
1092
1093 Bundle& set_timestamp(lo_timetag t)
1094 { LO_CHECK_BEFORE; lo_bundle_set_timestamp(bundle, t); return *this; }
1095
1096 void *serialise(void *to, size_t *size) const
1097 { LO_CHECK_BEFORE; return lo_bundle_serialise(bundle, to, size); }
1098
1099 void print() const
1100 { LO_CHECK_BEFORE; lo_bundle_pp(bundle); }
1101
1102 operator lo_bundle() const
1103 { return bundle; }
1104
1105 Bundle& clear()
1106 { LO_CHECK_BEFORE; lo_bundle_clear(bundle); return *this; }
1107
1108 protected:
1109 lo_bundle bundle;
1110 };
1111
1113 inline std::string version() {
1114 char str[32];
1115 lo_version(str, 32, 0, 0, 0, 0, 0, 0, 0);
1116 return std::string(str);
1117 }
1118
1120 inline lo_timetag now() { lo_timetag tt; lo_timetag_now(&tt); return tt; }
1121
1124};
1125
1127
1128#endif // _LO_CPP_H_
Class representing an OSC destination address, proxy for lo_address.
Definition lo_cpp.h:163
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:758
Class representing a local OSC server, proxy for lo_server.
Definition lo_cpp.h:503
virtual ~Server()
Definition lo_cpp.h:587
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:578
Server(const num_string_type &port, lo_err_handler err_h=0)
Definition lo_cpp.h:568
Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
Definition lo_cpp.h:572
Server(const num_string_type &port, int proto, E &&e=0)
Definition lo_cpp.h:527
Server(const num_string_type &port, E &&e)
Definition lo_cpp.h:510
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:545
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:506
Method add_method(const string_type &path, const string_type &types, lo_method_handler h, void *data) const
Definition lo_cpp.h:596
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.
void lo_bundle_clear(lo_bundle b)
Clear elements from a lo_bundle but do not free allocated memory.
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...
void lo_bundle_set_timestamp(lo_bundle b, lo_timetag t)
Get the timestamp associated with a bundle.
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.
void lo_message_clear(lo_message m)
Clear elements from a lo_message but do not free allocated memory.
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:1123
lo_timetag now()
Return the current time in lo_timetag format.
Definition lo_cpp.h:1120
std::string version()
Return the library version as an std::string.
Definition lo_cpp.h:1113
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:963
A structure to store OSC TimeTag values.
Union used to read values from incoming messages.