Loading...
Searching...
No Matches
o2.h
Go to the documentation of this file.
// o2.h -- public header file for o2 system
// Roger B. Dannenberg and Zhang Chi
// see license.txt for license
// June 2016
#ifndef O2_H
#define O2_H
#ifdef __cplusplus
extern "C" {
#endif
// get uint32_t, etc.:
#include <stdlib.h>
#include <stdint.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef O2_NO_DEBUG
void o2_debug_flags(const char *flags);
#endif
// Status return values used in o2 functions
#define O2_SUCCESS 0
#define O2_FAIL (-1)
// TODO: this value is never used/returned
#define O2_SERVICE_CONFLICT (-2)
// TODO: this value is never used/returned
#define O2_NO_SERVICE (-3)
#define O2_NO_MEMORY (-4)
#define O2_ALREADY_RUNNING (-5)
#define O2_BAD_NAME (-6)
#define O2_BAD_TYPE (-7)
#define O2_BAD_ARGS (-8)
#define O2_TCP_HUP (-9)
#define O2_HOSTNAME_TO_NETADDR_FAIL (-10)
#define O2_TCP_CONNECT_FAIL (-11)
#define O2_NO_CLOCK (-12)
#define O2_NO_HANDLER (-13)
#define O2_INVALID_MSG (-14)
#define O2_SEND_FAIL (-15)
#define O2_BAD_SERVICE_NAME (-16)
#define O2_SERVICE_EXISTS (-17)
#define O2_NOT_INITIALIZED (-18)
// Status return codes for o2_status function:
#define O2_LOCAL_NOTIME 0
#define O2_REMOTE_NOTIME 1
#define O2_BRIDGE_NOTIME 2
#define O2_TO_OSC_NOTIME 3
#define O2_LOCAL 4
#define O2_REMOTE 5
#define O2_BRIDGE 6
#define O2_TO_OSC 7
// Macros for o2 protocol
/* an internal value, ignored in transmission but check against O2_MARKER in the
* argument list. Used to do primitive bounds checking */
#define O2_MARKER_A (void *) 0xdeadbeefdeadbeefL
#define O2_MARKER_B (void *) 0xf00baa23f00baa23L
//#endif
extern void *((*o2_malloc)(size_t size));
extern void ((*o2_free)(void *));
void *o2_calloc(size_t n, size_t s);
#ifndef O2_NO_DEBUG
void *o2_dbg_malloc(size_t size, const char *file, int line);
void o2_dbg_free(void *obj, const char *file, int line);
#define O2_MALLOC(x) o2_dbg_malloc(x, __FILE__, __LINE__)
#define O2_FREE(x) o2_dbg_free(x, __FILE__, __LINE__)
#endif
#ifndef O2_MALLOC
#ifdef NO_O2_DEBUG
#define O2_MALLOC(x) (*o2_malloc)(x)
#else
#define O2_MALLOC(x) o2_dbg_malloc(x, __FILE__, __LINE__)
#endif
#endif
#ifndef O2_FREE
#ifdef NO_O2_DEBUG
#define O2_FREE(x) (*o2_free)(x)
#else
#define O2_FREE(x) (*o2_dbg_free)(x, __FILE__, __LINE__)
#endif
#endif
#ifndef O2_CALLOC
#ifdef NO_O2_DEBUG
void *o2_calloc(size_t n, size_t s);
#define O2_CALLOC(n, s) o2_calloc((n), (s))
#else
void *o2_dbg_calloc(size_t n, size_t s, const char *file, int line);
#define O2_CALLOC(n, s) o2_dbg_calloc((n), (s), __FILE__, __LINE__)
#endif
#endif
typedef double o2_time;
typedef struct o2_msg_data {
o2_time timestamp;
char address[4];
} o2_msg_data, *o2_msg_data_ptr;
// get the length from a pointer to an o2_msg_data. This macro dereferences
// the o2_msg_data pointer to impose some mild typechecking. Not just any
// pointer will work.
#define MSG_DATA_LENGTH(m) (((int32_t *) &((m)->timestamp))[-1])
#define WORD_ALIGN_PTR(p) ((char *) (((size_t) (p)) & ~3))
#define O2_MSG_TYPES(msg) \
WORD_ALIGN_PTR((msg)->address + strlen((msg)->address) + 4) + 1;
typedef struct o2_message {
union {
struct o2_message *next;
int64_t pad_if_needed;
};
union {
int tcp_flag;
int64_t pad_if_needed2;
};
int32_t allocated;
int32_t length;
o2_msg_data data;
} o2_message, *o2_message_ptr;
typedef struct o2_blob {
uint32_t size;
char data[4];
} o2_blob, *o2_blob_ptr;
typedef enum {
// basic O2 types
O2_INT32 = 'i',
O2_FLOAT = 'f',
O2_STRING = 's',
O2_BLOB = 'b',
O2_ARRAY_START = '[',
O2_ARRAY_END = ']',
// extended O2 types
O2_INT64 = 'h',
O2_TIME = 't',
O2_DOUBLE = 'd',
O2_SYMBOL = 'S',
O2_CHAR = 'c',
O2_MIDI = 'm',
O2_TRUE = 'T',
O2_FALSE = 'F',
O2_NIL = 'N',
O2_INFINITUM = 'I',
// O2 types
O2_BOOL = 'B',
O2_VECTOR = 'v',
} o2_type, *o2_type_ptr;
typedef union {
int32_t i32;
int32_t i;
int64_t i64;
int64_t h;
float f;
float f32;
double d;
double f64;
char s[4];
char S[4];
int c;
uint32_t m;
o2_time t;
o2_blob b;
int32_t B;
struct {
int32_t len;
int32_t typ;
union {
int32_t *vi;
int64_t *vh;
double *vd;
float *vf;
// note that a blob is basically a vector of bytes;
// there is no type conversion from blob to vector though,
// and no vector of shorts or bytes because if you converted
// to a vector of int64_t, it would take 8x the message
// space, forcing us to allocate very big buffers to
// unpack messages.
};
} v;
} o2_arg, *o2_arg_ptr;
extern o2_arg_ptr o2_got_start_array;
extern o2_arg_ptr o2_got_end_array;
extern int o2_stop_flag;
/*
* A collection of cooperating O2 processes forms an
* *application*. Applications must have unique names. This allows
* more than one application to exist within a single network without
* conflict. For example, there could be two applications, "joe" and
* "sue", each with services named "synth." Since the application
* names are different, joe's messages to the synth service go to
* joe's synth and not to sue's synth.
*
* Do not set, modify or free this variable! Consider it to be
* read-only. It is managed by O2 using o2_initialize() and o2_finish().
*/
extern const char *o2_application_name; // also used to detect initialization
typedef void (*o2_method_handler)(const o2_msg_data_ptr msg, const char *types,
o2_arg_ptr *argv, int argc, void *user_data);
int o2_initialize(const char *application_name);
int o2_memory(void *((*malloc)(size_t size)), void ((*free)(void *)));
o2_time o2_set_discovery_period(o2_time period);
int o2_hub(const char *ipaddress, int port);
int o2_get_address(const char **ipaddress, int *port);
int o2_service_new(const char *service_name);
int o2_tap(const char *tappee, const char *tapper);
int o2_service_free(const char *service_name);
int o2_method_new(const char *path, const char *typespec,
o2_method_handler h, void *user_data, int coerce, int parse);
int o2_poll();
int o2_run(int rate);
int o2_status(const char *service);
extern int o2_clock_is_synchronized;
int o2_roundtrip(double *mean, double *min);
typedef o2_time (*o2_time_callback)(void *rock);
int o2_clock_set(o2_time_callback gettime, void *rock);
// turn off Doxygen report on o2_send_marker()
#define o2_send(path, time, ...) \
o2_send_marker(path, time, FALSE, \
__VA_ARGS__, O2_MARKER_A, O2_MARKER_B)
\
int o2_send_marker(const char *path, double time, int tcp_flag,
const char *typestring, ...);
// turn off Doxygen report on o2_send_marker()
#define o2_send_cmd(path, time, ...) \
o2_send_marker(path, time, TRUE, \
__VA_ARGS__, O2_MARKER_A, O2_MARKER_B)
int o2_message_send(o2_message_ptr msg);
o2_time o2_time_get();
o2_time o2_local_time();
const char *o2_error_to_string(int i);
int o2_finish();
// Interoperate with OSC
int o2_osc_port_new(const char *service_name, int port_num, int tcp_flag);
int o2_osc_port_free(int port_num);
int o2_osc_delegate(const char *service_name, const char *ip, int port_num,
int tcp_flag);
uint64_t o2_osc_time_offset(uint64_t offset);
// end of Basics
o2_blob_ptr o2_blob_new(uint32_t size);
int o2_send_start();
int o2_add_float(float f);
int o2_add_string_or_symbol(o2_type tcode, const char *s);
#define o2_add_symbol(s) o2_add_string_or_symbol(O2_SYMBOL, s)
#define o2_add_string(s) o2_add_string_or_symbol(O2_STRING, s)
int o2_add_blob(o2_blob_ptr b);
int o2_add_blob_data(uint32_t size, void *data);
int o2_add_int64(int64_t i);
int o2_add_double_or_time(o2_type tchar, double d);
#define o2_add_double(d) o2_add_double_or_time(O2_DOUBLE, d)
#define o2_add_time(t) o2_add_double_or_time(O2_TIME, t)
int o2_add_int32_or_char(o2_type tcode, int32_t i);
#define o2_add_int32(i) o2_add_int32_or_char(O2_INT32, i)
#define o2_add_char(c) o2_add_int32_or_char(O2_CHAR, c)
int o2_add_midi(uint32_t m);
int o2_add_only_typecode(o2_type typecode);
#define o2_add_true() o2_add_only_typecode(O2_TRUE);
#define o2_add_false() o2_add_only_typecode(O2_FALSE);
#define o2_add_bool(x) o2_add_int32_or_char(O2_BOOL, x != 0)
#define o2_add_nil() o2_add_only_typecode(O2_NIL);
#define o2_add_infinitum() o2_add_only_typecode(O2_INFINITUM);
#define o2_add_start_array() o2_add_only_typecode(O2_ARRAY_START);
#define o2_add_end_array() o2_add_only_typecode(O2_ARRAY_END);
int o2_add_vector(o2_type element_type,
int length, void *data);
int o2_add_message(o2_message_ptr msg);
o2_message_ptr o2_message_finish(o2_time time, const char *address,
int tcp_flag);
o2_message_ptr o2_service_message_finish(o2_time time,
const char *service, const char *address, int tcp_flag);
void o2_message_free(o2_message_ptr msg);
int o2_send_finish(o2_time time, const char *address, int tcp_flag);
int o2_extract_start(o2_msg_data_ptr msg);
o2_arg_ptr o2_get_next(o2_type type_code);
/* Scheduling */
// Messages are stored in the table modulo their timestamp, so the
// table acts sort of like a hash table (this is also called the
// timing wheel structure). Messages are stored as linked lists sorted
// by increasing timestamps when there are collisions.
\
// Size of scheduler table.
#define O2_SCHED_TABLE_LEN 128
// Scheduler data structure.
typedef struct o2_sched {
int64_t last_bin;
double last_time;
o2_message_ptr table[O2_SCHED_TABLE_LEN];
} o2_sched, *o2_sched_ptr;
extern o2_sched o2_gtsched;
extern o2_sched o2_ltsched;
extern o2_sched_ptr o2_active_sched; // the scheduler that should be used
int o2_schedule(o2_sched_ptr scheduler, o2_message_ptr msg);
// end of a basics group
#ifdef __cplusplus
}
#endif
#endif /* O2_H */
o2_stop_flag
int o2_stop_flag
set this flag to stop o2_run()
o2_poll
int o2_poll()
Process current O2 messages.
o2_time_get
o2_time o2_time_get()
Get the estimated synchronized global O2 time.
o2_gtsched
o2_sched o2_gtsched
Scheduler that schedules according to global (master) clock time.
o2_error_to_string
const char * o2_error_to_string(int i)
Return text representation of an O2 error.
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_schedule
int o2_schedule(o2_sched_ptr scheduler, o2_message_ptr msg)
o2_set_discovery_period
o2_time o2_set_discovery_period(o2_time period)
Set discovery period.
o2_osc_time_offset
uint64_t o2_osc_time_offset(uint64_t offset)
Set the OSC time offset.
o2_status
int o2_status(const char *service)
Check the status of the service.
o2_time_callback
o2_time(* o2_time_callback)(void *rock)
signature for callback that defines the master clock
Definition o2.h:990
o2_initialize
int o2_initialize(const char *application_name)
Start O2.
o2_dbg_calloc
void * o2_dbg_calloc(size_t n, size_t s, const char *file, int line)
allocate memory
o2_get_address
int o2_get_address(const char **ipaddress, int *port)
Get IP address and TCP connection port number.
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_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_ltsched
o2_sched o2_ltsched
Scheduler that schedules according to local clock time.
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_service_free
int o2_service_free(const char *service_name)
Remove a local service.
o2_active_sched
o2_sched_ptr o2_active_sched
Current scheduler.
o2_memory
int o2_memory(void *((*malloc)(size_t size)), void((*free)(void *)))
Tell O2 how to allocate/free memory.
o2_run
int o2_run(int rate)
Run O2.
o2_time
double o2_time
O2 timestamps are doubles representing seconds since the approximate start time of the application.
Definition o2.h:392
o2_hub
int o2_hub(const char *ipaddress, int port)
Connect to a hub.
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_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_tap
int o2_tap(const char *tappee, const char *tapper)
copy messages from one service to another
o2_service_new
int o2_service_new(const char *service_name)
Add a service to the current application.
o2_osc_port_free
int o2_osc_port_free(int port_num)
Remove a port receiving OSC messages.
o2_local_time
o2_time o2_local_time()
Get the real time using the local O2 clock.
o2_clock_set
int o2_clock_set(o2_time_callback gettime, void *rock)
Provide a time reference to O2.
o2_type
o2_type
An enumeration of the O2 message types.
Definition o2.h:486
o2_finish
int o2_finish()
release the memory and shut down O2.
o2_roundtrip
int o2_roundtrip(double *mean, double *min)
Get network round-trip information.
O2_ARRAY_END
@ O2_ARRAY_END
End array or tuple.
Definition o2.h:493
O2_BLOB
@ O2_BLOB
Binary Large OBject (BLOB) type.
Definition o2.h:491
O2_FALSE
@ O2_FALSE
Symbol representing the value False.
Definition o2.h:503
O2_TRUE
@ O2_TRUE
Symbol representing the value True.
Definition o2.h:502
O2_INFINITUM
@ O2_INFINITUM
Symbol representing the value Infinitum.
Definition o2.h:505
O2_VECTOR
@ O2_VECTOR
Prefix to indicate a vector.
Definition o2.h:509
O2_FLOAT
@ O2_FLOAT
32 bit IEEE-754 float.
Definition o2.h:489
O2_MIDI
@ O2_MIDI
4 byte MIDI packet.
Definition o2.h:501
O2_DOUBLE
@ O2_DOUBLE
64 bit IEEE-754 double.
Definition o2.h:498
O2_TIME
@ O2_TIME
OSC time type.
Definition o2.h:497
O2_CHAR
@ O2_CHAR
8bit char variable (Standard C).
Definition o2.h:500
O2_INT32
@ O2_INT32
32 bit signed integer.
Definition o2.h:488
O2_ARRAY_START
@ O2_ARRAY_START
Start array or tuple.
Definition o2.h:492
O2_NIL
@ O2_NIL
Symbol representing the value Nil.
Definition o2.h:504
O2_INT64
@ O2_INT64
64 bit signed integer.
Definition o2.h:496
O2_BOOL
@ O2_BOOL
Boolean value returned as either 0 or 1.
Definition o2.h:508
O2_SYMBOL
@ O2_SYMBOL
Used in systems distinguish strings and symbols.
Definition o2.h:499
O2_STRING
@ O2_STRING
NULL terminated string (Standard C).
Definition o2.h:490
o2_debug_flags
void o2_debug_flags(const char *flags)
Enable debugging output.
o2_extract_start
int o2_extract_start(o2_msg_data_ptr msg)
initialize internal state to parse, extract, and coerce message arguments.
o2_get_next
o2_arg_ptr o2_get_next(o2_type type_code)
get the next message parameter
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_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_add_vector
int o2_add_vector(o2_type element_type, int length, void *data)
add a vector
o2_add_message
int o2_add_message(o2_message_ptr msg)
add a message to a bundle
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_message_finish
o2_message_ptr o2_message_finish(o2_time time, const char *address, int tcp_flag)
finish and return the message.
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_blob_new
o2_blob_ptr o2_blob_new(uint32_t size)
Allocate a blob.
o2_message_free
void o2_message_free(o2_message_ptr msg)
free a message allocated by o2_send_start().
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_add_float
int o2_add_float(float f)
add a float to the message (see o2_send_start())
o2_add_midi
int o2_add_midi(uint32_t m)
add a short midi message to the message (see o2_send_start())
o2_add_int64
int o2_add_int64(int64_t i)
add an int64 to the message (see o2_send_start())
o2_send_start
int o2_send_start()
Prepare to build a message.
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_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_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_blob
The structure for binary large object.
Definition o2.h:477
o2_blob::data
char data[4]
the data, actually of variable length
Definition o2.h:479
o2_blob::size
uint32_t size
size of data
Definition o2.h:478
o2_message
an O2 message container
Definition o2.h:456
o2_message::tcp_flag
int tcp_flag
send message by tcp?
Definition o2.h:462
o2_message::pad_if_needed
int64_t pad_if_needed
make sure allocated is 8-byte aligned
Definition o2.h:459
o2_message::allocated
int32_t allocated
how many bytes allocated in data part
Definition o2.h:465
o2_message::length
int32_t length
the length of the message in data part
Definition o2.h:466
o2_message::next
struct o2_message * next
links used for free list and scheduler
Definition o2.h:458
o2_message::pad_if_needed2
int64_t pad_if_needed2
make sure allocated is 8-byte aligned
Definition o2.h:463
o2_msg_data
data part of an O2 message
Definition o2.h:413
o2_msg_data::timestamp
o2_time timestamp
the message delivery time (0 for immediate)
Definition o2.h:414
o2_msg_data::address
char address[4]
the message address string
Definition o2.h:423
o2_arg
union of all O2 parameter types
Definition o2.h:533
o2_arg::t
o2_time t
TimeTag value.
Definition o2.h:549
o2_arg::vd
double * vd
vector of IEEE-754 doubles
Definition o2.h:559
o2_arg::vh
int64_t * vh
vector of 64-bit signed integers
Definition o2.h:558
o2_arg::i64
int64_t i64
64 bit signed integer.
Definition o2.h:536
o2_arg::B
int32_t B
a boolean value, either 0 or 1
Definition o2.h:551
o2_arg::f64
double f64
an alias for d
Definition o2.h:541
o2_arg::c
int c
Standard C, 8 bit, char, stored as int.
Definition o2.h:546
o2_arg::vf
float * vf
vector of IEEE-754 floats
Definition o2.h:560
o2_arg::len
int32_t len
IMPORTANT: divide by 4 or 8 to get length in elements.
Definition o2.h:553
o2_arg::b
o2_blob b
a blob (unstructured bytes)
Definition o2.h:550
o2_arg::h
int64_t h
an alias for i64
Definition o2.h:537
o2_arg::f32
float f32
an alias for f
Definition o2.h:539
o2_arg::m
uint32_t m
Definition o2.h:547
o2_arg::d
double d
64 bit IEEE-754 double.
Definition o2.h:540
o2_arg::i32
int32_t i32
32 bit signed integer.
Definition o2.h:534
o2_arg::typ
int32_t typ
type of vector elements
Definition o2.h:555
o2_arg::i
int32_t i
an alias for i32
Definition o2.h:535
o2_arg::vi
int32_t * vi
vector of 32-bit signed integers
Definition o2.h:557
o2_arg::f
float f
32 bit IEEE-754 float.
Definition o2.h:538