O2  1.1
Inter-process communication system for media applications
o2.h
1 // o2.h -- public header file for o2 system
2 // Roger B. Dannenberg and Zhang Chi
3 // see license.txt for license
4 // June 2016
5 
6 #ifndef O2_H
7 #define O2_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 
124 // get uint32_t, etc.:
125 #include <stdlib.h>
126 #include <stdint.h>
127 
128 #ifndef TRUE
129 #define TRUE 1
130 #define FALSE 0
131 #endif
132 
137 #ifndef O2_NO_DEBUG
160 void o2_debug_flags(const char *flags);
161 #endif
162 
169 // Status return values used in o2 functions
170 #define O2_SUCCESS 0
171 
172 #define O2_FAIL (-1)
178 
179 // TODO: this value is never used/returned
181 #define O2_SERVICE_CONFLICT (-2)
182 
183 // TODO: this value is never used/returned
185 #define O2_NO_SERVICE (-3)
186 
188 #define O2_NO_MEMORY (-4)
189 
191 #define O2_ALREADY_RUNNING (-5)
192 
194 #define O2_BAD_NAME (-6)
195 
197 #define O2_BAD_TYPE (-7)
198 
201 #define O2_BAD_ARGS (-8)
202 
204 #define O2_TCP_HUP (-9)
205 
208 #define O2_HOSTNAME_TO_NETADDR_FAIL (-10)
209 
211 #define O2_TCP_CONNECT_FAIL (-11)
212 
215 #define O2_NO_CLOCK (-12)
216 
218 #define O2_NO_HANDLER (-13)
219 
221 #define O2_INVALID_MSG (-14)
222 
224 #define O2_SEND_FAIL (-15)
225 
227 #define O2_BAD_SERVICE_NAME (-16)
228 
230 #define O2_SERVICE_EXISTS (-17)
231 
233 #define O2_NOT_INITIALIZED (-18)
234 
235 
236 // Status return codes for o2_status function:
237 
243 #define O2_LOCAL_NOTIME 0
244 
251 #define O2_REMOTE_NOTIME 1
252 
265 #define O2_BRIDGE_NOTIME 2
266 
282 #define O2_TO_OSC_NOTIME 3
283 
292 #define O2_LOCAL 4
293 
298 #define O2_REMOTE 5
299 
308 #define O2_BRIDGE 6
309 
324 #define O2_TO_OSC 7
325 
329 // Macros for o2 protocol
330 /* an internal value, ignored in transmission but check against O2_MARKER in the
331  * argument list. Used to do primitive bounds checking */
332 #define O2_MARKER_A (void *) 0xdeadbeefdeadbeefL
333 #define O2_MARKER_B (void *) 0xf00baa23f00baa23L
334 //#endif
335 
336 extern void *((*o2_malloc)(size_t size));
337 extern void ((*o2_free)(void *));
338 void *o2_calloc(size_t n, size_t s);
339 
344 #ifndef O2_NO_DEBUG
345 void *o2_dbg_malloc(size_t size, char *file, int line);
346 void o2_dbg_free(void *obj, char *file, int line);
347 #define O2_MALLOC(x) o2_dbg_malloc(x, __FILE__, __LINE__)
348 #define O2_FREE(x) o2_dbg_free(x, __FILE__, __LINE__)
349 #endif
350 
361 #ifndef O2_MALLOC
362 #ifdef NO_O2_DEBUG
363 #define O2_MALLOC(x) (*o2_malloc)(x)
364 #else
365 #define O2_MALLOC(x) o2_dbg_malloc(x, __FILE__, __LINE__)
366 #endif
367 #endif
368 
370 #ifndef O2_FREE
371 #ifdef NO_O2_DEBUG
372 #define O2_FREE(x) (*o2_free)(x)
373 #else
374 #define O2_FREE(x) (*o2_dbg_free)(x, __FILE__, __LINE__)
375 #endif
376 #endif
377 
379 #ifndef O2_CALLOC
380 #ifdef NO_O2_DEBUG
381 void *o2_calloc(size_t n, size_t s);
382 #define O2_CALLOC(n, s) o2_calloc((n), (s))
383 #else
384 void *o2_dbg_calloc(size_t n, size_t s, char *file, int line);
385 #define O2_CALLOC(n, s) o2_dbg_calloc((n), (s), __FILE__, __LINE__)
386 #endif
387 #endif
388 
392 typedef double o2_time;
393 
394 
414 typedef struct o2_msg_data {
416 
424  char address[4];
426 
427 // get the length from a pointer to an o2_msg_data. This macro dereferences
428 // the o2_msg_data pointer to impose some mild typechecking. Not just any
429 // pointer will work.
430 #define MSG_DATA_LENGTH(m) (((int32_t *) &((m)->timestamp))[-1])
431 
432 
437 #define WORD_ALIGN_PTR(p) ((char *) (((size_t) (p)) & ~3))
438 #define O2_MSG_TYPES(msg) \
439  WORD_ALIGN_PTR((msg)->address + strlen((msg)->address) + 4) + 1;
440 
441 
457 typedef struct o2_message {
458  union {
459  struct o2_message *next;
460  int64_t pad_if_needed;
461  };
462  union {
463  int tcp_flag;
464  int64_t pad_if_needed2;
465  };
466  int32_t allocated;
467  int32_t length;
468  o2_msg_data data;
470 
471 
478 typedef struct o2_blob {
479  uint32_t size;
480  char data[4];
481 } o2_blob, *o2_blob_ptr;
482 
483 
487 typedef enum {
488  // basic O2 types
489  O2_INT32 = 'i',
490  O2_FLOAT = 'f',
491  O2_STRING = 's',
492  O2_BLOB = 'b',
494  O2_ARRAY_END = ']',
495 
496  // extended O2 types
497  O2_INT64 = 'h',
498  O2_TIME = 't',
499  O2_DOUBLE = 'd',
500  O2_SYMBOL = 'S',
501  O2_CHAR = 'c',
502  O2_MIDI = 'm',
503  O2_TRUE = 'T',
504  O2_FALSE = 'F',
505  O2_NIL = 'N',
506  O2_INFINITUM = 'I',
507 
508  // O2 types
509  O2_BOOL = 'B',
510  O2_VECTOR = 'v',
511 } o2_type, *o2_type_ptr;
512 
513 
534 typedef union {
535  int32_t i32;
536  int32_t i;
537  int64_t i64;
538  int64_t h;
539  float f;
540  float f32;
541  double d;
542  double f64;
543  char s[4];
544 
546  char S[4];
547  int c;
548  uint32_t m;
549  o2_time t;
552  int32_t B;
553  struct {
554  int32_t len;
555  int32_t typ;
557  union {
558  int32_t *vi;
559  int64_t *vh;
560  double *vd;
561  float *vf;
562  // note that a blob is basically a vector of bytes;
563  // there is no type conversion from blob to vector though,
564  // and no vector of shorts or bytes because if you converted
565  // to a vector of int64_t, it would take 8x the message
566  // space, forcing us to allocate very big buffers to
567  // unpack messages.
568  };
569  } v;
570 } o2_arg, *o2_arg_ptr;
571 
572 
573 extern o2_arg_ptr o2_got_start_array;
574 extern o2_arg_ptr o2_got_end_array;
575 
589 extern const char *o2_application_name;
590 
597 extern int o2_stop_flag;
598 
599 
630 typedef void (*o2_method_handler)(const o2_msg_data_ptr msg, const char *types,
631  o2_arg_ptr *argv, int argc, void *user_data);
632 
633 
649 int o2_initialize(const char *application_name);
650 
651 
670 int o2_memory(void *((*malloc)(size_t size)), void ((*free)(void *)));
671 
672 
698 
699 
729 int o2_service_new(const char *service_name);
730 
731 
744 int o2_service_free(char *service_name);
745 
746 
768 int o2_method_new(const char *path, const char *typespec,
769  o2_method_handler h, void *user_data, int coerce, int parse);
770 
771 
791 int o2_poll();
792 
799 int o2_run(int rate);
800 
863 int o2_status(const char *service);
864 
869 extern int o2_clock_is_synchronized;
870 
880 int o2_roundtrip(double *mean, double *min);
881 
882 
887 typedef o2_time (*o2_time_callback)(void *rock);
888 
889 
917 int o2_clock_set(o2_time_callback gettime, void *rock);
918 
919  // turn off Doxygen report on o2_send_marker()
942 #define o2_send(path, time, ...) \
943  o2_send_marker(path, time, FALSE, \
944  __VA_ARGS__, O2_MARKER_A, O2_MARKER_B)
945  \
947 int o2_send_marker(const char *path, double time, int tcp_flag,
948  const char *typestring, ...); // turn off Doxygen report on o2_send_marker()
973 #define o2_send_cmd(path, time, ...) \
974  o2_send_marker(path, time, TRUE, \
975  __VA_ARGS__, O2_MARKER_A, O2_MARKER_B)
976 
977 
989 
1004 
1005 
1012 
1020 const char *o2_error_to_string(int i);
1021 
1030 int o2_finish();
1031 
1032 
1033 // Interoperate with OSC
1050 int o2_osc_port_new(const char *service_name, int port_num, int tcp_flag);
1051 
1064 int o2_osc_port_free(int port_num);
1065 
1066 
1091 int o2_osc_delegate(const char *service_name, const char *ip, int port_num,
1092  int tcp_flag);
1093 
1105 uint64_t o2_osc_time_offset(uint64_t offset);
1106 
1107  // end of Basics
1109 
1291 o2_blob_ptr o2_blob_new(uint32_t size);
1292 
1293 
1304 int o2_send_start();
1305 
1306 
1308 int o2_add_float(float f);
1309 
1312 int o2_add_string_or_symbol(o2_type tcode, const char *s);
1313 
1315 #define o2_add_symbol(s) o2_add_string_or_symbol(O2_SYMBOL, s)
1316 
1318 #define o2_add_string(s) o2_add_string_or_symbol(O2_STRING, s)
1319 
1322 int o2_add_blob(o2_blob_ptr b);
1323 
1326 int o2_add_blob_data(uint32_t size, void *data);
1327 
1329 int o2_add_int64(int64_t i);
1330 
1333 int o2_add_double_or_time(o2_type tchar, double d);
1334 
1336 #define o2_add_double(d) o2_add_double_or_time(O2_DOUBLE, d)
1337 
1339 #define o2_add_time(t) o2_add_double_or_time(O2_TIME, t)
1340 
1343 int o2_add_int32_or_char(o2_type tcode, int32_t i);
1344 
1346 #define o2_add_int32(i) o2_add_int32_or_char(O2_INT32, i)
1347 
1349 #define o2_add_char(c) o2_add_int32_or_char(O2_CHAR, c)
1350 
1352 int o2_add_midi(uint32_t m);
1353 
1357 int o2_add_only_typecode(o2_type typecode);
1358 
1360 #define o2_add_true() o2_add_only_typecode(O2_TRUE);
1361 
1363 #define o2_add_false() o2_add_only_typecode(O2_FALSE);
1364 
1366 #define o2_add_bool(x) o2_add_int32_or_char(O2_BOOL, x != 0)
1367 
1369 #define o2_add_nil() o2_add_only_typecode(O2_NIL);
1370 
1372 #define o2_add_infinitum() o2_add_only_typecode(O2_INFINITUM);
1373 
1375 #define o2_add_start_array() o2_add_only_typecode(O2_ARRAY_START);
1376 
1378 #define o2_add_end_array() o2_add_only_typecode(O2_ARRAY_END);
1379 
1388 int o2_add_vector(o2_type element_type,
1389  int length, void *data);
1390 
1407 
1408 
1423 o2_message_ptr o2_message_finish(o2_time time, const char *address,
1424  int tcp_flag);
1425 
1443  const char *service, const char *address, int tcp_flag);
1444 
1452 
1453 
1471 int o2_send_finish(o2_time time, const char *address, int tcp_flag);
1472 
1473 
1500 
1584 o2_arg_ptr o2_get_next(o2_type type_code);
1585 
1589 /* Scheduling */
1594 // Messages are stored in the table modulo their timestamp, so the
1595 // table acts sort of like a hash table (this is also called the
1596 // timing wheel structure). Messages are stored as linked lists sorted
1597 // by increasing timestamps when there are collisions.
1598  \
1600 // Size of scheduler table.
1601 #define O2_SCHED_TABLE_LEN 128
1602 
1603 // Scheduler data structure.
1604 typedef struct o2_sched {
1605  int64_t last_bin;
1606  double last_time;
1607  o2_message_ptr table[O2_SCHED_TABLE_LEN];
1608 } o2_sched, *o2_sched_ptr;
1620 extern o2_sched o2_gtsched;
1621 
1635 extern o2_sched o2_ltsched;
1636 
1645 extern o2_sched_ptr o2_active_sched; // the scheduler that should be used
1646 
1647 
1673 int o2_schedule(o2_sched_ptr scheduler, o2_message_ptr msg);
1674  // end of a basics group
1676 
1677 #ifdef __cplusplus
1678 }
1679 #endif
1680 
1681 #endif /* O2_H */
O2_VECTOR
@ O2_VECTOR
Prefix to indicate a vector.
Definition: o2.h:510
o2_arg::vi
int32_t * vi
vector of 32-bit signed integers
Definition: o2.h:558
o2_message
an O2 message container
Definition: o2.h:457
o2_schedule
int o2_schedule(o2_sched_ptr scheduler, o2_message_ptr msg)
o2_dbg_calloc
void * o2_dbg_calloc(size_t n, size_t s, char *file, int line)
allocate memory
o2_arg::c
int c
Standard C, 8 bit, char, stored as int.
Definition: o2.h:547
o2_arg::vd
double * vd
vector of IEEE-754 doubles
Definition: o2.h:560
O2_BLOB
@ O2_BLOB
Binary Large OBject (BLOB) type.
Definition: o2.h:492
o2_message_free
void o2_message_free(o2_message_ptr msg)
free a message allocated by o2_send_start().
o2_run
int o2_run(int rate)
Run O2.
o2_add_message
int o2_add_message(o2_message_ptr msg)
add a message to a bundle
o2_add_blob
int o2_add_blob(o2_blob_ptr b)
add an o2_blob to the message (see o2_send_start()), where the blob is given as a pointer to an o2_bl...
o2_arg::f32
float f32
an alias for f
Definition: o2.h:540
o2_blob::data
char data[4]
the data, actually of variable length
Definition: o2.h:480
o2_arg::f
float f
32 bit IEEE-754 float.
Definition: o2.h:539
o2_extract_start
int o2_extract_start(o2_msg_data_ptr msg)
initialize internal state to parse, extract, and coerce message arguments.
o2_arg::h
int64_t h
an alias for i64
Definition: o2.h:538
o2_arg::len
int32_t len
IMPORTANT: divide by 4 or 8 to get length in elements.
Definition: o2.h:554
O2_NIL
@ O2_NIL
Symbol representing the value Nil.
Definition: o2.h:505
o2_arg::i
int32_t i
an alias for i32
Definition: o2.h:536
o2_add_int32_or_char
int o2_add_int32_or_char(o2_type tcode, int32_t i)
This function supports o2_add_int32() and o2_add_char() Normally, you should not call this directly.
o2_stop_flag
int o2_stop_flag
set this flag to stop o2_run()
o2_service_message_finish
o2_message_ptr o2_service_message_finish(o2_time time, const char *service, const char *address, int tcp_flag)
finish and return a message, prepending service name
o2_message_send
int o2_message_send(o2_message_ptr msg)
Send an O2 message. (See also macros o2_send and o2_send_cmd).
o2_time
double o2_time
O2 timestamps are doubles representing seconds since the approximate start time of the application.
Definition: o2.h:392
o2_arg::i64
int64_t i64
64 bit signed integer.
Definition: o2.h:537
o2_add_vector
int o2_add_vector(o2_type element_type, int length, void *data)
add a vector
o2_arg
union of all O2 parameter types
Definition: o2.h:534
o2_arg::vf
float * vf
vector of IEEE-754 floats
Definition: o2.h:561
o2_message::pad_if_needed2
int64_t pad_if_needed2
make sure allocated is 8-byte aligned
Definition: o2.h:464
o2_osc_port_free
int o2_osc_port_free(int port_num)
Remove a port receiving OSC messages.
o2_arg::f64
double f64
an alias for d
Definition: o2.h:542
O2_INFINITUM
@ O2_INFINITUM
Symbol representing the value Infinitum.
Definition: o2.h:506
o2_get_next
o2_arg_ptr o2_get_next(o2_type type_code)
get the next message parameter
o2_service_free
int o2_service_free(char *service_name)
Remove a local service.
o2_status
int o2_status(const char *service)
Check the status of the service.
o2_gtsched
o2_sched o2_gtsched
Scheduler that schedules according to global (master) clock time.
o2_method_new
int o2_method_new(const char *path, const char *typespec, o2_method_handler h, void *user_data, int coerce, int parse)
Add a handler for an address.
o2_time_get
o2_time o2_time_get()
Get the estimated synchronized global O2 time.
O2_INT64
@ O2_INT64
64 bit signed integer.
Definition: o2.h:497
o2_clock_is_synchronized
int o2_clock_is_synchronized
A variable indicating that the clock is the master or is synchronized to the master.
o2_memory
int o2_memory(void *((*malloc)(size_t size)), void((*free)(void *)))
Tell O2 how to allocate/free memory.
o2_add_string_or_symbol
int o2_add_string_or_symbol(o2_type tcode, const char *s)
This function suppports o2_add_symbol() and o2_add_string() Normally, you should not call this direct...
O2_FALSE
@ O2_FALSE
Symbol representing the value False.
Definition: o2.h:504
O2_INT32
@ O2_INT32
32 bit signed integer.
Definition: o2.h:489
o2_message_finish
o2_message_ptr o2_message_finish(o2_time time, const char *address, int tcp_flag)
finish and return the message.
o2_local_time
o2_time o2_local_time()
Get the real time using the local O2 clock.
O2_ARRAY_END
@ O2_ARRAY_END
End array or tuple.
Definition: o2.h:494
o2_debug_flags
void o2_debug_flags(const char *flags)
Enable debugging output.
o2_msg_data
data part of an O2 message
Definition: o2.h:414
o2_arg::B
int32_t B
a boolean value, either 0 or 1
Definition: o2.h:552
o2_method_handler
void(* o2_method_handler)(const o2_msg_data_ptr msg, const char *types, o2_arg_ptr *argv, int argc, void *user_data)
callback function to receive an O2 message
Definition: o2.h:630
o2_add_float
int o2_add_float(float f)
add a float to the message (see o2_send_start())
o2_set_discovery_period
o2_time o2_set_discovery_period(o2_time period)
Set discovery period.
o2_osc_port_new
int o2_osc_port_new(const char *service_name, int port_num, int tcp_flag)
Create a port to receive OSC messages.
o2_message::allocated
int32_t allocated
how many bytes allocated in data part
Definition: o2.h:466
o2_message::length
int32_t length
the length of the message in data part
Definition: o2.h:467
o2_arg::b
o2_blob b
a blob (unstructured bytes)
Definition: o2.h:551
O2_TIME
@ O2_TIME
OSC time type.
Definition: o2.h:498
o2_osc_delegate
int o2_osc_delegate(const char *service_name, const char *ip, int port_num, int tcp_flag)
Create a service that forwards O2 messages to an OSC server.
o2_osc_time_offset
uint64_t o2_osc_time_offset(uint64_t offset)
Set the OSC time offset.
o2_blob
The structure for binary large object.
Definition: o2.h:478
o2_ltsched
o2_sched o2_ltsched
Scheduler that schedules according to local clock time.
o2_message::next
struct o2_message * next
links used for free list and scheduler
Definition: o2.h:459
o2_initialize
int o2_initialize(const char *application_name)
Start O2.
O2_CHAR
@ O2_CHAR
8bit char variable (Standard C).
Definition: o2.h:501
O2_ARRAY_START
@ O2_ARRAY_START
Start array or tuple.
Definition: o2.h:493
o2_roundtrip
int o2_roundtrip(double *mean, double *min)
Get network round-trip information.
o2_service_new
int o2_service_new(const char *service_name)
Add a service to the current application.
o2_msg_data::address
char address[4]
the message address string
Definition: o2.h:424
o2_error_to_string
const char * o2_error_to_string(int i)
Return text representation of an O2 error.
O2_TRUE
@ O2_TRUE
Symbol representing the value True.
Definition: o2.h:503
o2_finish
int o2_finish()
release the memory and shut down O2.
o2_message::tcp_flag
int tcp_flag
send message by tcp?
Definition: o2.h:463
o2_clock_set
int o2_clock_set(o2_time_callback gettime, void *rock)
Provide a time reference to O2.
o2_add_only_typecode
int o2_add_only_typecode(o2_type typecode)
This function supports o2_add_true(), o2_add_false(), o2_add_bool(), o2_add_nil(),...
o2_active_sched
o2_sched_ptr o2_active_sched
Current scheduler.
o2_add_int64
int o2_add_int64(int64_t i)
add an int64 to the message (see o2_send_start())
o2_application_name
const char * o2_application_name
name of the application
o2_msg_data::timestamp
o2_time timestamp
the message delivery time (0 for immediate)
Definition: o2.h:415
o2_message::pad_if_needed
int64_t pad_if_needed
make sure allocated is 8-byte aligned
Definition: o2.h:460
o2_message
struct o2_message o2_message
an O2 message container
o2_poll
int o2_poll()
Process current O2 messages.
o2_send_start
int o2_send_start()
Prepare to build a message.
o2_blob_new
o2_blob_ptr o2_blob_new(uint32_t size)
Allocate a blob.
o2_type
o2_type
An enumeration of the O2 message types.
Definition: o2.h:487
o2_blob
struct o2_blob o2_blob
The structure for binary large object.
o2_arg::d
double d
64 bit IEEE-754 double.
Definition: o2.h:541
o2_send_finish
int o2_send_finish(o2_time time, const char *address, int tcp_flag)
send a message allocated by o2_send_start().
o2_arg::vh
int64_t * vh
vector of 64-bit signed integers
Definition: o2.h:559
O2_FLOAT
@ O2_FLOAT
32 bit IEEE-754 float.
Definition: o2.h:490
O2_SYMBOL
@ O2_SYMBOL
Used in systems distinguish strings and symbols.
Definition: o2.h:500
O2_MIDI
@ O2_MIDI
4 byte MIDI packet.
Definition: o2.h:502
O2_STRING
@ O2_STRING
NULL terminated string (Standard C).
Definition: o2.h:491
o2_arg::m
uint32_t m
Definition: o2.h:548
O2_BOOL
@ O2_BOOL
Boolean value returned as either 0 or 1.
Definition: o2.h:509
o2_arg::i32
int32_t i32
32 bit signed integer.
Definition: o2.h:535
o2_msg_data
struct o2_msg_data o2_msg_data
data part of an O2 message
o2_time_callback
o2_time(* o2_time_callback)(void *rock)
signature for callback that defines the master clock
Definition: o2.h:887
o2_add_double_or_time
int o2_add_double_or_time(o2_type tchar, double d)
This function supports o2_add_double() and o2_add_time() Normally, you should not call this directly.
o2_add_blob_data
int o2_add_blob_data(uint32_t size, void *data)
add an o2_blob to the message (see o2_send_start()), where the blob is specified by a size and a data...
O2_DOUBLE
@ O2_DOUBLE
64 bit IEEE-754 double.
Definition: o2.h:499
o2_blob::size
uint32_t size
size of data
Definition: o2.h:479
o2_add_midi
int o2_add_midi(uint32_t m)
add a short midi message to the message (see o2_send_start())