Functions to send and parse OSC packets
Based on OSC Spec v1.0 http://opensoundcontrol.org/spec-1_0
(please read for background info and nomenclature)
Optimized for embedded systems which provide more code memory (flash) than RAM.
Server Part (parsing incoming OSC packets):
MIOS32_OSC_ParsePacket() has to be called with the OSC package content, packet length and a pointer to the "search tree".
The search tree allows the parser to match parts of the OSC address path which are separated with the '/' delimiter. At the end of a search tree we will find the OSC method which is called with the arguments that are part of the OSC packet.
Usually the search tree is located in flash memory, since it won't change during runtime. Each node of the tree consists of a mios32_osc_search_tree_t structure which defines:
So, a node either defines the link to the next node which is part of the address path, or it defines the method which should be called.
The optional 32bit argument could be useful for re-using the same function for multiple purposes to save memory. Each node contains such an argument value.
It is ORed for each individual path while scanning the search tree, so that it is possible to allocate certain bitfields for each node (e.g. /sid* will add the SID number to bit [31:30] of the argument value, and /sid?/*/<method> will add the parameter address)
OSC allows to use wildcards in the address path like *, ?, [] and {}.
The MIOS32 implementation currently only supports '*' and '?'
Examples: '/sid?/osc/finetune' or '/sid?/osc/fine*' or '/cs/led/*'
While searching through the tree, the appr. functions of all matching methods will be called with the OSC arguments which are part of the packet (+ the method argument):
s32 osc_method(mios32_osc_args_t *osc_args, u32 method_arg)
All specified OSC arguments are supported, such as following "tags":
Arguments are stored in mios32_osc_args_t before the OSC method function is called.
This structure contains:
An example for a search tree construction and OSC method handling can be found under $MIOS32_PATH/apps/examples/ethernet/osc
Client Part (sending OSC packets):
Outgoing OSC packets can be "constructed" on-the-fly with MIOS32_OSC_Put* functions.
No high-level functions (with large argument lists) are provided to save stack space, and to give the application the highest flexibility. Even unspecified OSC packages can be created if desired.
Following example demonstrates the usage. Note that each MIOS32_OSC_Put* function returns the pointer to the next entry, so that items can be appended without the need for additional pointer calculations.
// Send a Button Value // Path: /cs/button/state <button-number> <0 or 1> s32 OSC_CLIENT_SendButtonState(mios32_osc_timetag_t timetag, u32 button, u8 pressed) { // create the OSC packet u8 packet[128]; u8 *end_ptr = packet; u8 *insert_len_ptr; end_ptr = MIOS32_OSC_PutString(end_ptr, "#bundle"); end_ptr = MIOS32_OSC_PutTimetag(end_ptr, timetag); insert_len_ptr = end_ptr; // remember this address - we will insert the length later end_ptr += 4; end_ptr = MIOS32_OSC_PutString(end_ptr, "/cs/button/state"); end_ptr = MIOS32_OSC_PutString(end_ptr, ",ii"); end_ptr = MIOS32_OSC_PutInt(end_ptr, button); end_ptr = MIOS32_OSC_PutInt(end_ptr, pressed); // now insert the message length MIOS32_OSC_PutWord(insert_len_ptr, (u32)(end_ptr-insert_len_ptr-4)); // send packet and exit return OSC_SERVER_SendPacket(packet, (u32)(end_ptr-packet)); }
Returns the data part of a Blob
[in] | buffer | pointer to OSC message buffer |
Returns the length of a Blob
[in] | buffer | pointer to OSC message buffer |
char MIOS32_OSC_GetChar | ( | u8 * | buffer | ) |
Returns a character
[in] | buffer | pointer to OSC message buffer |
double MIOS32_OSC_GetDouble | ( | u8 * | buffer | ) |
Gets two words (8 bytes) from buffer and converts them to a float with double precession
[in] | buffer | pointer to OSC message buffer |
float MIOS32_OSC_GetFloat | ( | u8 * | buffer | ) |
Gets a word (4 bytes) from buffer and converts it to a float with normal precession
[in] | buffer | pointer to OSC message buffer |
Gets a word (4 bytes) from buffer and converts it to a 32bit signed integer.
[in] | buffer | pointer to OSC message buffer |
long long MIOS32_OSC_GetLongLong | ( | u8 * | buffer | ) |
Gets two words (8 bytes) from buffer and converts them to a 64bit signed integer.
[in] | buffer | pointer to OSC message buffer |
mios32_midi_package_t MIOS32_OSC_GetMIDI | ( | u8 * | buffer | ) |
Returns a MIDI package
[in] | buffer | pointer to OSC message buffer |
char* MIOS32_OSC_GetString | ( | u8 * | buffer | ) |
Returns pointer to a string in message buffer
[in] | buffer | pointer to OSC message buffer |
mios32_osc_timetag_t MIOS32_OSC_GetTimetag | ( | u8 * | buffer | ) |
Gets a timetag (8 bytes) from buffer
[in] | buffer | pointer to OSC message buffer |
Gets a word (4 bytes) from buffer
[in] | buffer | pointer to OSC message buffer |
Initializes OSC layer
[in] | mode | currently only mode 0 supported |
s32 MIOS32_OSC_ParsePacket | ( | u8 * | packet, | |
u32 | len, | |||
const mios32_osc_search_tree_t * | search_tree | |||
) |
Parses an incoming OSC packet and calls OSC methods defined in search_tree on matching addresses
[in] | packet | pointer to OSC packet |
[in] | len | length of packet |
[in] | search_tree | a tree which defines address parts and methods to be called |
Puts an OSC-Blob into buffer and pads with 0 until word boundary has been reached
[in] | buffer | pointer to OSC message buffer |
[in] | data | blob data |
[in] | len | blob size |
Puts a character into buffer and pads with 3 zeros (word aligned)
[in] | buffer | pointer to OSC message buffer |
[in] | c | the character which should be inserted |
Puts a float with double precission into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | value | the double value which should be inserted |
Puts a float with normal precission into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | value | the float value which should be inserted |
Puts a 32bit signed integer into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | value | the integer value which should be inserted |
Puts a 64bit signed integer into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | value | the "long long" value which should be inserted |
u8* MIOS32_OSC_PutMIDI | ( | u8 * | buffer, | |
mios32_midi_package_t | p | |||
) |
Puts a MIDI package into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | p | the MIDI package which should be inserted |
Puts a string into buffer and pads with 0 until word boundary has been reached
[in] | buffer | pointer to OSC message buffer |
[in] | value | the string which should be inserted |
u8* MIOS32_OSC_PutTimetag | ( | u8 * | buffer, | |
mios32_osc_timetag_t | timetag | |||
) |
Puts a timetag (8 bytes) into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | timetag | the timetag which should be inserted |
Puts a word (4 bytes) into buffer
[in] | buffer | pointer to OSC message buffer |
[in] | word | 32bit word |
s32 MIOS32_OSC_SendDebugMessage | ( | mios32_osc_args_t * | osc_args, | |
u32 | method_arg | |||
) |
Sends the argument list of a method to the debug terminal.
By default, the message is sent via MIDI to the MIOS Studio terminal.
Optionally another output function can be used (e.g. printf in emulation) by overruling MIOS32_OSC_DEBUG_MSG in mios32_config.h
Usage Example:
static s32 OSC_SERVER_MyOSCMethod(mios32_osc_args_t *osc_args, u32 method_arg) { MIOS32_OSC_SendDebugMessage(osc_args, method_arg); return 0; // no error }
[in] | osc_args | pointer to OSC argument list as forwarded by MIOS32_OSC_ParsePacket() |
[in] | method_args | 32bit value as forwarded by MIOS32_OSC_ParsePacket() |