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