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 
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 
76 namespace 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);
205  lo_message_free(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);
246  lo_message_free(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 
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);
913  lo_message_free(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 
1123  inline lo_timetag immediate() { return LO_TT_IMMEDIATE; }
1124 };
1125 
1128 #endif // _LO_CPP_H_
Class representing an OSC method, proxy for lo_method.
Definition: lo_cpp.h:150
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_message lo_bundle_get_message(lo_bundle b, int index, const char **path)
Gets a message contained within a bundle.
Class representing an OSC message, proxy for lo_message.
Definition: lo_cpp.h:322
struct lo_address_ * lo_address
A reference to an OSC service.
Definition: lo_types.h:45
void lo_bundle_free_messages(lo_bundle b)
Obsolete, use lo_bundle_free_recursive instead.
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_timetag lo_bundle_get_timestamp(lo_bundle b)
Get the timestamp associated with a bundle.
lo_timetag lo_message_get_timestamp(lo_message m)
Returns the timestamp (lo_timetag *) of a bundled incoming message.
int lo_message_add_nil(lo_message m)
Append a data item and typechar of the specified type to a message. See lo_message_add_int32() for de...
lo_server_thread lo_server_thread_new(const char *port, lo_err_handler err_h)
Create a new server thread to handle incoming OSC messages.
struct lo_server_ * lo_server
An object representing an instance of an OSC server.
Definition: lo_types.h:85
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 lo_message_clone(lo_message m)
Create a new lo_message object by cloning an already existing one.
lo_server lo_server_new(const char *port, lo_err_handler err_h)
Create a new server instance.
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.
Class representing an OSC blob, proxy for lo_blob.
Definition: lo_cpp.h:927
int lo_message_get_argc(lo_message m)
Return the message argument count.
Union used to read values from incoming messages.
Definition: lo_osc_types.h:104
int lo_server_add_bundle_handlers(lo_server s, lo_bundle_start_handler sh, lo_bundle_end_handler eh, void *user_data)
Add bundle notification handlers to the specified server.
lo_element_type
An enumeration of bundle element types liblo can handle.
Definition: lo_osc_types.h:48
lo_element_type lo_bundle_get_type(lo_bundle b, int index)
Gets the element type contained within a bundle.
int lo_bundle_add_message(lo_bundle b, const char *path, lo_message m)
Adds an OSC message to an existing bundle.
void lo_bundle_incref(lo_bundle b)
Add one to a bundle&#39;s reference count.
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...
const char * lo_address_errstr(lo_address a)
Return the error string from the last failed lo_send() or lo_address_new() call.
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_send_bundle(lo_address targ, lo_bundle b)
Send a lo_bundle object to address targ.
A structure to store OSC TimeTag values.
Definition: lo_osc_types.h:35
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_thread_start(lo_server_thread st)
Start the server thread.
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_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...
void lo_server_del_method(lo_server s, const char *path, const char *typespec)
Delete an OSC method from the specified server.
struct lo_bundle_ * lo_bundle
A low-level object used to represent bundles of messages passed over OSC.
Definition: lo_types.h:69
Server(const num_string_type &port, int proto, E &&e=0)
Definition: lo_cpp.h:527
Class representing a server thread, proxy for lo_server_thread.
Definition: lo_cpp.h:757
lo_address lo_message_get_source(lo_message m)
Returns the source (lo_address) of an incoming message.
struct lo_message_ * lo_message
A low-level object used to represent messages passed over OSC.
Definition: lo_types.h:60
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_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.
Method add_method(const string_type &path, const string_type &types, lo_method_handler h, void *data) const
Definition: lo_cpp.h:596
void lo_blob_free(lo_blob b)
Free the memory taken by a blob.
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...
Server(const num_string_type &port, int proto, lo_err_handler err_h=0)
Definition: lo_cpp.h:572
lo_bundle lo_bundle_new(lo_timetag tt)
Create a new bundle object.
struct lo_method_ * lo_method
An object representing an method on a server.
Definition: lo_types.h:77
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...
void lo_server_free(lo_server s)
Free up memory used by the lo_server object.
lo_timetag now()
Return the current time in lo_timetag format.
Definition: lo_cpp.h:1120
Server(const num_string_type &port, lo_err_handler err_h=0)
Definition: lo_cpp.h:568
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
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_arg ** lo_message_get_argv(lo_message m)
Return the message arguments. Do not free the returned data.
lo_timetag immediate()
Return the OSC timetag representing "immediately".
Definition: lo_cpp.h:1123
lo_address lo_address_new_from_url(const char *url)
Create a lo_address object from an OSC URL.
#define LO_TT_IMMEDIATE
A timetag constant representing "now".
Definition: lo_osc_types.h:151
void lo_bundle_pp(lo_bundle b)
Pretty-print a lo_bundle object.
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_message lo_message_new(void)
Create a new lo_message object.
void lo_bundle_clear(lo_bundle b)
Clear elements from a lo_bundle but do not free allocated memory.
Class representing an OSC destination address, proxy for lo_address.
Definition: lo_cpp.h:162
const char * lo_address_get_port(lo_address a)
Return the port/service name of a lo_address object.
LO_ADD_METHOD((const char *, const char *, lo_arg **, int),((char *) 0,(char *) 0,(lo_arg **) 0,(int) 0),(path, types, argv, argc))
int lo_address_get_protocol(lo_address a)
Return the protocol of a lo_address object.
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.
size_t lo_message_length(lo_message m, const char *path)
Return the length of a message in bytes.
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_send_message(lo_address targ, const char *path, lo_message msg)
Send a lo_message object to target targ.
void lo_message_clear(lo_message m)
Clear elements from a lo_message but do not free allocated memory.
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...
Definition: lo_cpp.h:76
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...
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
int lo_message_add_int32(lo_message m, int32_t a)
Append a data item and typechar of the specified type to a message.
struct lo_blob_ * lo_blob
A object to store an opaque binary data object.
Definition: lo_types.h:52
lo_bundle lo_bundle_get_bundle(lo_bundle b, int index)
Gets a nested bundle contained within a bundle.
const char * lo_address_get_iface(lo_address t)
Get the name of the network interface assigned to an OSC address.
int lo_address_set_tcp_nodelay(lo_address t, int enable)
Set the TCP_NODELAY flag on outgoing TCP connections.
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()...
Class representing an OSC path (std::string) and lo::Message pair.
Definition: lo_cpp.h:962
int lo_address_get_ttl(lo_address t)
Get the Time-to-Live value for a given target address.
const char * lo_address_get_hostname(lo_address a)
Return the hostname of a lo_address object.
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...
Server(lo_server s)
Definition: lo_cpp.h:506
int lo_server_recv_noblock(lo_server s, int timeout)
Look for an OSC message waiting to be received.
int lo_bundle_add_bundle(lo_bundle b, lo_bundle n)
Adds an OSC bundle to an existing bundle.
char * lo_server_get_url(lo_server s)
Return an OSC URL that can be used to contact the server.
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_server_get_port(lo_server s)
Return the port number that the server has bound to.
Class representing a local OSC server, proxy for lo_server.
Definition: lo_cpp.h:502
void lo_address_set_ttl(lo_address t, int ttl)
Set the Time-to-Live value for a given target address.
double lo_server_next_event_delay(lo_server s)
Return the time in seconds until the next scheduled event.
lo_server lo_server_thread_get_server(lo_server_thread st)
Return the lo_server for a lo_server_thread.
size_t lo_bundle_length(lo_bundle b)
Return the length of a bundle in bytes.
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...
int lo_message_add_varargs(lo_message m, const char *types, va_list ap)
Append a varargs list 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...
char * lo_address_get_url(lo_address a)
Return a URL representing an OSC address.
Class representing an OSC bundle, proxy for lo_bundle.
Definition: lo_cpp.h:972
int lo_server_get_socket_fd(lo_server s)
Return the file descriptor of the server socket.
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.
virtual ~Server()
Definition: lo_cpp.h:587
struct lo_server_thread_ * lo_server_thread
An object representing a thread containing an OSC server.
Definition: lo_types.h:92
int lo_server_dispatch_data(lo_server s, void *data, size_t size)
Dispatch a raw block of memory containing an OSC message.
void lo_address_free(lo_address t)
Free the memory used by the lo_address object.
int lo_server_del_lo_method(lo_server s, lo_method m)
Delete a specific OSC method from the specified server.
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_events_pending(lo_server s)
Return true if there are scheduled events (eg. from bundles) waiting to be dispatched by the server...
Server(const num_string_type &port, E &&e)
Definition: lo_cpp.h:510
void lo_bundle_free_recursive(lo_bundle b)
Frees the memory taken by a bundle object and its messages and nested bundles recursively.
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_server_get_protocol(lo_server s)
Return the protocol that the server is using.
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
int lo_server_thread_stop(lo_server_thread st)
Stop the server thread.
void lo_bundle_set_timestamp(lo_bundle b, lo_timetag t)
Get the timestamp associated with a bundle.
lo_blob lo_blob_new(int32_t size, const void *data)
Create a new OSC blob type.
uint32_t lo_blob_datasize(lo_blob b)
Return the amount of valid data in a lo_blob object.
int lo_server_recv(lo_server s)
Block, waiting for an OSC message to be received.
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
void lo_message_incref(lo_message m)
Add one to a message&#39;s reference count.
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
void lo_timetag_now(lo_timetag *t)
Return a timetag for the current time.
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.
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...
char * lo_message_get_types(lo_message m)
Return the message type tag string.
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_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.
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...
unsigned int lo_bundle_count(lo_bundle b)
Return the number of top-level elements in 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_server_wait(lo_server s, int timeout)
Wait for an OSC message to be received.
int lo_address_errno(lo_address a)
Return the error number from the last failed lo_send() or lo_address_new() call.
int lo_send(lo_address targ, const char *path, const char *type,...)
Send a OSC formatted message to the address specified.
void * lo_blob_dataptr(lo_blob b)
Return a pointer to the start of the blob data to allow contents to be changed.
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_server_thread_free(lo_server_thread st)
Free memory taken by a server thread.
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_message_pp(lo_message m)
Pretty-print a lo_message object.
std::string version()
Return the library version as an std::string.
Definition: lo_cpp.h:1113