O2 2.0
A communication protocol for interactive music and media applications.
|
This documentation is divided into modules. Each module describes a different area of functionality: Basics, Return Codes, Low-Level Message Send, and Low-Level Message Parsing.
O2 uses CMake, which can create a Linux Makefile, Xcode project, or Visual Studio solution. The basic procedure is run CMake (ccmake on Linux) to create the Makefile of project file, then build using make or your IDE. The main options for CMake are BUILD_MIDI_EXAMPLE: builds an example that depends on PortMidi (disable this option unless you need it), BUILD_STATIC_LIB: builds a static O2 library (recommended), BUILD_TESTS: builds a suite of tests (useful for O2 developers), and BUILD_TESTS_WITH_LIBLO: includes some tests that depends on the OSC library liblo (also useful for O2 developers).
To use O2 in your application, normally you should only need to include the O2 static library o2_static.lib
into your project, make sure the path to o2.h is on your headers search path, and maybe put the path to o2_static.lib
on your libraries search path.
O2 depends on some libraries. On Windows, if your application includes O2, you will need to link to winmm.lib
and ws2_32.lib
. On OS X, you will need to link to the CoreAudio
framework. On Linux, you will need to link to asound
(you may have to install a developer package to get this), pthread
, and m
(the math library).
O2 is a communication protocol for interactive music and media applications. O2 is inspired by Open Sound Control (OSC) and uses similar means to form addresses, specify types, and encode messages.
However, in addition to providing message delivery, O2 offers a discovery mechanism where processes automatically discover and connect to other processes. Each process can offer zero or more named "services," which are top-level nodes in a global, tree-structured address space for a distributed O2 application. In O2, services replace the notion of network addresses (e.g. 128.2.100.57) in OSC.
O2 is based on IP (Internet Protocol), but there is a mechanism that allows an O2 process to serve as a bridge to other protocols including WebSockets, shared memory, and MQTT. OSC is also supported: An O2 service can be delegated to an OSC server address, and O2 can offer an OSC server that forwards to an O2 service.
O2 addresses begin with the service name. Thus, a complete O2 address would be written simply as "/synth/filterFtoff," where "synth" is the service name.
Furthermore, O2 implements a clock synchronization protocol. A single process is designated as the "reference," and other processes automatically synchronize their local clocks to the reference. All O2 messages are timestamped. Messages are delivered immediately, but their designated operations are invoked according to the timestamp. A timestamp of zero (0.0) means deliver the message immediately. Messages with non-zero timestamps are only deliverable after both the sender and receiver have synchronized clocks.
A service is created using the functions:
o2_service_new("service_name")
and
o2_method_new("address," "types," handler, user_data, coerce, parse)
, where o2_method_new is called to install a handler for each node, and each "address" includes the service name as the first node.
Some major components and concepts of O2 are the following:
@public:internal:port
strings that denote a remote process.O2 uses O2 messages for some internal functions and also to communicate status information with O2 processes. Since messages are dropped if there is no handler, O2 processes need not set up handlers for all information.
In the following descriptions, if the service name is @public:internal:port
it means the IP address and port number are used to construct a string, e.g. "@4a6dfb76:c0a801a6:fc1d" might be the actual service name.
/_o2/dy "sissiii"
ensemble_name version public_ip internal_ip tcp_port udp_port dy - this message is normally sent to the discovery port, but it can also be sent as a result of calling o2_hub and providing an O2 process address. Processes must exchange discovery messages to be connected. The version number encodes the O2 version number of the sender as ((<major-vers> * 256) + <minor-vers>) * 256 + <patch-vers>, where <major-vers>, <minor-vers> and <patch-vers> follow the O2 semantic versioning scheme, e.g. version 2.3.4 would have version number 0x020304. Thus, each component of the 3-part version number ranges from 0 through 255. Connections are completed only if the major version numbers match. The dy parameter is O2_DY_INFO, O2_DY_HUB, O2_DY_REPLY, O2_DY_CALLBACK, O2_DY_CONNECT, or O2_DY_O2LITE, depending on the expected response.
/_o2/hub ""
- requests the receiver to become the hub for the sender
/_o2/cs/cs ""
- announces when clock sync is obtained.
/_o2/ds ""
- this message invokes the sending of discovery messages. It is used with a timestamp to schedule periodic discovery message sending.
`/_cs/get "is" serial-no reply-to - send the time. The reply-to parameter is the full address for the reply. The reply contains the type string "it" and the parameters are the serial-no and the current time.
/_o2/sv "ssbbsi..."
process-name service-name add-flag service-flag* tapper-or-properties send_mode... - reports service creation or deletion. Each service is described by name, true, and either true followed by a properties string and zero or false followed by the tapper name and tapper send_mode. If a service is deleted, then false is sent rather than true, and if this is not a tap, the properties string is empty. The "..." notation here indicates that there can be any number of services described in this message, each service consisting of another "sbbsi" (string, Boolean, Boolean, string, int32) sequence. Properties strings are sent with escaped values, a leading ';' and a trailing ';'. This is the first message sent when a process-to-process connection is made.
/_o2/cs/rt "s"
reply-to - A process can send this message to request round trip (to the clock reference) information; reply-to is the full address of the reply. The reply message has the type string "sff" and the parameters are the process name (:internal:port), the mean round-trip time, and the minimum round-trip time.
/_o2/cs/ps ""
- this message invokes the sending of the /_cs/get
message to request the time as part of the clock synchronization protocol.
/_o2/si "siss"
service_name status process-name properties - Whenever an active service status changes or service properties change, this message is sent to the local process. Note that when a local service is created, an internal /sv
message is sent to all other processes, and when that process's services table is updated, if the service is or becomes active, the change is reported locally to the application by sending this /_o2/si
message. Normally, you should not add handlers or use the _o2
service, but in this case, an application is expected to add a custom handler to receive status updates. See o2_status for a list of status values. O2_UNKNOWN is reported when the current provider of a service is removed. This may be followed immediately by another message to /_o2/si
if another provider offers the service. The service _o2
is created before you can install a handler for /_o2/si
, so you will not receive an si
message when _o2
is created. If the service name begins with '@', it represents a remote process and the name has the form:internal:port, e.g. @c0a35801:80e8a1a5:d67e
. There is also a @public:internal:port
service representing the local process, but the local process is also represented by _o2
, so the local @public:internal:port
service is never reported in an /_o2/si
message. Instead, the string "_o2"
indicates that process is the local one. You can get the local @public:internal:port
string by calling o2_get_addresses or o2_get_proc_name. The properties string contains the service properties in the form "attr1:value1;attr2:value2;" with no leading ";". If there are no properties, the string is empty. Values are escaped: within a value, the characters ":;\" are preceded by "\" since ":" and ";" are separator characters. Attribute names are alphanumeric.