# MIOS32_OSC

## Functions
s32 | MIOS32_OSC_Init (u32 mode)
u32 | MIOS32_OSC_GetWord (u8 *buffer)
u8 * | MIOS32_OSC_PutWord (u8 *buffer, u32 word)
mios32_osc_timetag_t | MIOS32_OSC_GetTimetag (u8 *buffer)
u8 * | MIOS32_OSC_PutTimetag (u8 *buffer, mios32_osc_timetag_t timetag)
s32 | MIOS32_OSC_GetInt (u8 *buffer)
u8 * | MIOS32_OSC_PutInt (u8 *buffer, s32 value)
float | MIOS32_OSC_GetFloat (u8 *buffer)
u8 * | MIOS32_OSC_PutFloat (u8 *buffer, float value)
char * | MIOS32_OSC_GetString (u8 *buffer)
u8 * | MIOS32_OSC_PutString (u8 *buffer, char *str)
u32 | MIOS32_OSC_GetBlobLength (u8 *buffer)
u8 * | MIOS32_OSC_GetBlobData (u8 *buffer)
u8 * | MIOS32_OSC_PutBlob (u8 *buffer, u8 *data, u32 len)
long long | MIOS32_OSC_GetLongLong (u8 *buffer)
u8 * | MIOS32_OSC_PutLongLong (u8 *buffer, long long value)
double | MIOS32_OSC_GetDouble (u8 *buffer)
u8 * | MIOS32_OSC_PutDouble (u8 *buffer, double value)
char | MIOS32_OSC_GetChar (u8 *buffer)
u8 * | MIOS32_OSC_PutChar (u8 *buffer, char c)
mios32_midi_package_t | MIOS32_OSC_GetMIDI (u8 *buffer)
u8 * | MIOS32_OSC_PutMIDI (u8 *buffer, mios32_midi_package_t p)
s32 | MIOS32_OSC_ParsePacket (u8 *packet, u32 len, const mios32_osc_search_tree_t *search_tree)
s32 | MIOS32_OSC_SendDebugMessage (mios32_osc_args_t *osc_args, u32 method_arg)

## Detailed Description

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:

- the OSC address part or NULL if there are no more address parts/methods in the "OSC container"
- a link to the next address part or NULL if the leaf has been reached (method reached)
- if leaf: pointer to function which dispatches the addressed OSC method
- optional arguments for method (32bit)

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":

- 'i': signed 32bit integer
- 'f': IEEE 754 floating point number
- 's': OSC-string
- 'b': OSC-blob
- 'h': signed 64bit integer
- 't': OSC-timetag
- 'd': 64bit ("double") IEEE floating point number
- 'S': alternate type represented as an OSC-string (for example, for systems that differentiate "symbols" from "strings")
- 'c': an ascii character, sent as 32 bits
- 'r': 32 bit RGBA color
- 'm': 4 byte MIDI message
- 'T': TRUE
- 'F': FALSE
- 'N': NIL
- 'I': Infinitum
- '[': Indicates the beginning of an array. The tags following are for data in the Array until a close brace tag is reached.
- ']': Indicates the end of an array.

Arguments are stored in mios32_osc_args_t before the OSC method function is called.
This structure contains:

- the timetag (seconds and fraction)
- number of address parts
- an array of address parts without wildcards (!) - this allows the method to reconstruct the complete path, e.g. to send parameters to different targets
- number of arguments
- an array of argument tags
- pointer to arguments (have to be fetched with MIOS32_OSC_Get*() functions)

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));
     }

## Function Documentation

u8* MIOS32_OSC_GetBlobData | ( | u8 * | buffer | ) |

Returns the data part of a Blob

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  pointer to data part of a Blob

u32 MIOS32_OSC_GetBlobLength | ( | u8 * | buffer | ) |

Returns the length of a Blob

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  blob length

Here is the call graph for this function:

char MIOS32_OSC_GetChar | ( | u8 * | buffer | ) |

Returns a character

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  a single character

double MIOS32_OSC_GetDouble | ( | u8 * | buffer | ) |

Gets two words (8 bytes) from buffer and converts them to a float with double precession

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  float with double procession

Here is the call graph for this function:

float MIOS32_OSC_GetFloat | ( | u8 * | buffer | ) |

Gets a word (4 bytes) from buffer and converts it to a float with normal precession

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  float with normal procession

Here is the call graph for this function:

s32 MIOS32_OSC_GetInt | ( | u8 * | buffer | ) |

Gets a word (4 bytes) from buffer and converts it to a 32bit signed integer.

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  32bit signed integer

Here is the call graph for this function:

long long MIOS32_OSC_GetLongLong | ( | u8 * | buffer | ) |

Gets two words (8 bytes) from buffer and converts them to a 64bit signed integer.

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  64bit signed integer

Here is the call graph for this function:

mios32_midi_package_t MIOS32_OSC_GetMIDI | ( | u8 * | buffer | ) |

Returns a MIDI package

Note:
  doesn't work with SysEx streams - they have to be handled separately

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  a MIOS32 compliant MIDI package

char* MIOS32_OSC_GetString | ( | u8 * | buffer | ) |

Returns pointer to a string in message buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  zero-terminated string

mios32_osc_timetag_t MIOS32_OSC_GetTimetag | ( | u8 * | buffer | ) |

Gets a timetag (8 bytes) from buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  timetag (seconds and fraction part)

Here is the call graph for this function:

u32 MIOS32_OSC_GetWord | ( | u8 * | buffer | ) |

Gets a word (4 bytes) from buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer

Returns:
  32bit unsigned integer

s32 MIOS32_OSC_Init | ( | u32 | mode | ) |

Initializes OSC layer

Parameters:

  `[in]` | mode | currently only mode 0 supported

Returns:
  < 0 if initialisation failed

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

Parameters:

  `[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

Returns:
  0 if packet has been parsed w/o errors
  -1 if packet format invalid
  -2 if the packet contains an OSC element with invalid format
  -3 if the packet contains an OSC element with an unsupported format returns -4 if MIOS32_OSC_MAX_PATH_PARTS has been exceeded

Here is the call graph for this function:

u8* MIOS32_OSC_PutBlob | ( | u8 * | buffer,
|  | u8 * | data,
|  | u32 | len |
| ) |  |  |

Puts an OSC-Blob into buffer and pads with 0 until word boundary has been reached

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | data | blob data
  `[in]` | len | blob size

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutChar | ( | u8 * | buffer,
|  | char | c |
| ) |  |  |

Puts a character into buffer and pads with 3 zeros (word aligned)

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | c | the character which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutDouble | ( | u8 * | buffer,
|  | double | value |
| ) |  |  |

Puts a float with double precission into buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | value | the double value which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutFloat | ( | u8 * | buffer,
|  | float | value |
| ) |  |  |

Puts a float with normal precission into buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | value | the float value which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutInt | ( | u8 * | buffer,
|  | s32 | value |
| ) |  |  |

Puts a 32bit signed integer into buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | value | the integer value which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutLongLong | ( | u8 * | buffer,
|  | long long | value |
| ) |  |  |

Puts a 64bit signed integer into buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | value | the "long long" value which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutMIDI | ( | u8 * | buffer,
|  | mios32_midi_package_t | p |
| ) |  |  |

Puts a MIDI package into buffer

Note:
  doesn't work with SysEx streams - they have to be handled separately

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | p | the MIDI package which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutString | ( | u8 * | buffer,
|  | char * | str |
| ) |  |  |

Puts a string into buffer and pads with 0 until word boundary has been reached

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | value | the string which should be inserted

Returns:
  buffer pointer behind the inserted entry

u8* MIOS32_OSC_PutTimetag | ( | u8 * | buffer,
|  | mios32_osc_timetag_t | timetag |
| ) |  |  |

Puts a timetag (8 bytes) into buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | timetag | the timetag which should be inserted

Returns:
  buffer pointer behind the inserted entry

Here is the call graph for this function:

u8* MIOS32_OSC_PutWord | ( | u8 * | buffer,
|  | u32 | word |
| ) |  |  |

Puts a word (4 bytes) into buffer

Parameters:

  `[in]` | buffer | pointer to OSC message buffer
  `[in]` | word | 32bit word

Returns:
  buffer pointer behind the inserted entry

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
     }

Parameters:

  `[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()

Returns:
  < 0 on errors

Here is the call graph for this function: