OSC is an extremely popular protocol for sending control commands and parameters between devices and applications. It is a protocol in which there is no confirmation of the data exchange success, that is, the sender doesn't know if the receiver received the data, and the receiver does not know if somebody sent something to it. As a result, data can be lost without any notification to the sender and the receiver. Though, in a local network such a situation is very rare and occurs only if you are using extremely fast frame rates for sending data.
For using OSC capabilities in openFrameworks projects, you need to use the ofxOsc addon. This is a core addon included in openFrameworks distribution.
We suggest that the first time you try OSC, play with openFrameworks examples oscSenderExample
and oscReceiveExample
, located in openFrameworks's folder examples/addons
. Run both of them on one PC, and then move the mouse over the oscSenderExample
window. You will see that oscReceiveExample
receives mouse coordinates and writes them on its screen.
To use the addon in your project, you have three options:
oscSenderExample
or oscReceiveExample
into your projects folder. This way is the simplest and the best for the first trial of OSC.addons/ofxOsc
folder to your project and specify their paths. This is the method for adding OSC support to the existing project.Now you have the project with the linked ofxOsc addon, and can send and receive data using OSC protocol.
For sending data with OSC in your project, perform the following steps:
#include "ofxOsc.h"
line in the testApp.h
file right after the #include "ofMain.h"
line.ofxOscSender sender;
line in the testApp
class definition.testApp::setup()
function by using the following line:sender.setup("localhost", 12345 );
The first argument of the sender.setup()
function is a string containing the receiver's address. localhost
is the address of the computer itself, so, sender
will send data to some other application running on the same computer. For sending data to another device, you must know its address and specify it, for example, 192.168.0.3
. The second integer argument is the port of the receiver. We use 12345
because it is not normally used by the operating systems for any special purposes.
ofxOscMessage
, specify its address, fill it with a parameter or parameters, and finally send the message using sender.sendMessage()
:ofxOscMessage m; m.setAddress( "/volume" ); m.addFloatArg( 0.4f ); sender.sendMessage( m );
The address of the message is not the receiver's network address. It is just the name of a parameter that can be understood by the receiver. The address begins with /
and can contain several /
symbols if needed, for example, /object1/velocity
.
The message can contain one of the several arguments of the following types: float
, int
, and string
. The arguments are attached to the message sequentially by calling the corresponding functions: m.addFloatArg()
, m.addIntArg()
, and m.addStringArg()
. For example:
m.addFloatArg( 0.4f ); m.addIntArg( 1 ); m.addStringArg( "start" );
The most used types of arguments are the float values in the range [0, 1]. They are naturally linked to VJ controllers and other equipments via software platforms such as VDMX and Max/MSP. Also, integer values are used for representing a button state (0 - disabled, 1 - enabled).
You can have several senders sending data to many destinations.
We suggest storing destination address and port numbers in an external .xml
file placed in the data
folder of your project. We call this file settings.xml
. Add the operations for reading the values of the destination address and the port number to the testApp::setup()
function and use these values as parameters of sender.setup()
. This method gives you the flexibility to run the project in different network configurations without recompiling it.
Use the ofxXmlSettings addon which works with .xml
files. Learn how to use it in the openFrameworks example: examples/addons/xmlSettingsExample
.
Please note the following rules:
ofxOscBundle
object. Just create an object of this type, add to it your ofxOscMessage
messages, and send it:ofxOscBundle bundle; bundle.addMessage( m ); //First ofxOscMessage message bundle.addMessage( m2 ); //Second message //... sender.sendBundle( bundle ); //Send bundle
For receiving data with OSC in your project, perform the following steps:
#include "ofxOsc.h"
line in the testApp.h
file right after the #include "ofMain.h"
line.ofxOscReceiver receiver;
line in the testApp
class definition.testApp::setup()
function by using the following line:receiver.setup( 12345 );
The argument of the receiver.setup()
function is the integer value of port number.
receiver
and parse them. The best practice is to do it in the testApp::update()
function in a while
loop:while ( receiver.hasWaitingMessages() ){ //Get the next message ofxOscMessage m; receiver.getNextMessage( &m ); //Parse message, for example: if ( m.getAddress() == "/volume" ){ //Get first argument float volume = m.getArgAsFloat( 0 ); //... //Use volume value, for example: sound.setVolume( volume ) } };
You can get the values of arguments in the message m
using the functions m.getArgAsFloat( index )
, m.getArgAsInt32( index )
, and m.getArgAsString( index )
, where index
is the argument's index, 0
– first, 1
- second, and so on. For getting the number of attributes, use the m.getNumArgs()
function, which returns the value of attributes in m
.
Let's look at some typical schemes for using your projects with other applications by connecting them using OSC.
Typical usage of OSC is the following:
For more complex schemes, you need to use an OSC-manager application, which routes OSC signals, such as OSCulator.
While OSC is well-supported by all the creative coding and VJ software, it cannot easily transmit big data such as images. So let's consider how to do it with another protocol, for example, the TCP.