You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
791 lines
22 KiB
791 lines
22 KiB
/* |
|
Written by Yotam Mann, The Center for New Music and Audio Technologies, |
|
University of California, Berkeley. Copyright (c) 2012, The Regents of |
|
the University of California (Regents). |
|
|
|
Permission to use, copy, modify, distribute, and distribute modified versions |
|
of this software and its documentation without fee and without a signed |
|
licensing agreement, is hereby granted, provided that the above copyright |
|
notice, this paragraph and the following two paragraphs appear in all copies, |
|
modifications, and distributions. |
|
|
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, |
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING |
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS |
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED |
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE |
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
|
|
|
For bug reports and feature requests please email me at yotam@cnmat.berkeley.edu |
|
*/ |
|
|
|
#include "OSCMessage.h" |
|
#include "OSCMatch.h" |
|
#include "OSCTiming.h" |
|
|
|
extern osctime_t zerotime; |
|
/*============================================================================= |
|
CONSTRUCTORS / DESTRUCTOR |
|
=============================================================================*/ |
|
|
|
//constructor with address |
|
OSCMessage::OSCMessage(const char * _address){ |
|
setupMessage(); |
|
setAddress(_address); |
|
} |
|
|
|
//constructor with nothing |
|
//just a placeholder since the message is invalid |
|
OSCMessage::OSCMessage(){ |
|
setupMessage(); |
|
error = INVALID_OSC; |
|
} |
|
|
|
//variable length constructor |
|
//for example OSCMessage msg("/address", "isf", 1, "two", 3.0); |
|
/* |
|
OSCMessage::OSCMessage(const char * _address, char * types, ... ){ |
|
setupMessage(_address); |
|
} |
|
*/ |
|
|
|
//sets up a new message |
|
void OSCMessage::setupMessage(){ |
|
address = NULL; |
|
//setup the attributes |
|
dataCount = 0; |
|
error = OSC_OK; |
|
//setup the space for data |
|
data = NULL; |
|
//setup for filling the message |
|
incomingBuffer = NULL; |
|
incomingBufferSize = 0; |
|
incomingBufferFree = 0; |
|
clearIncomingBuffer(); |
|
//set the decode state |
|
decodeState = STANDBY; |
|
} |
|
|
|
//DESTRUCTOR |
|
OSCMessage::~OSCMessage(){ |
|
//free everything that needs to be freed |
|
//free the address |
|
free(address); |
|
//free the data |
|
empty(); |
|
//free the filling buffer |
|
free(incomingBuffer); |
|
} |
|
|
|
OSCMessage& OSCMessage::empty(){ |
|
error = OSC_OK; |
|
//free each of the data in the array |
|
for (int i = 0; i < dataCount; i++){ |
|
const auto datum = getOSCData(i); |
|
//explicitly destruct the data |
|
//datum->~OSCData(); |
|
delete datum; |
|
} |
|
//and free the array |
|
free(data); |
|
data = NULL; |
|
dataCount = 0; |
|
decodeState = STANDBY; |
|
clearIncomingBuffer(); |
|
return *this; |
|
} |
|
|
|
//COPY |
|
OSCMessage::OSCMessage(OSCMessage * msg){ |
|
//start with a message with the same address |
|
setupMessage(); |
|
setAddress(msg->address); |
|
//add each of the data to the other message |
|
for (int i = 0; i < msg->dataCount; i++){ |
|
add(msg->data[i]); |
|
} |
|
} |
|
|
|
/*============================================================================= |
|
GETTING DATA |
|
=============================================================================*/ |
|
|
|
OSCData * OSCMessage::getOSCData(int position){ |
|
if (position < dataCount){ |
|
const auto datum = data[position]; |
|
return datum; |
|
} else { |
|
error = INDEX_OUT_OF_BOUNDS; |
|
return nullptr; |
|
} |
|
} |
|
|
|
int32_t OSCMessage::getInt(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getInt(); |
|
} else { |
|
return 0; |
|
} |
|
} |
|
osctime_t OSCMessage::getTime(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getTime(); |
|
} else { |
|
return zerotime; |
|
} |
|
} |
|
float OSCMessage::getFloat(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getFloat(); |
|
} else { |
|
return 0.0f; |
|
} |
|
} |
|
|
|
double OSCMessage::getDouble(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getDouble(); |
|
} else { |
|
|
|
return 0.0; |
|
} |
|
} |
|
|
|
bool OSCMessage::getBoolean(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getBoolean(); |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
|
|
int OSCMessage::getString(int position, char * buffer){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getString(buffer, datum->bytes); |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
int OSCMessage::getString(int position, char * buffer, int bufferSize){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
//the number of bytes to copy is the smaller between the buffer size and the datum's byte length |
|
int copyBytes = bufferSize < datum->bytes? bufferSize : datum->bytes; |
|
return datum->getString(buffer, copyBytes); |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
int OSCMessage::getString(int position, char * buffer, int bufferSize, int offset, int size){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
//the number of bytes to copy is the smaller between the buffer size and the datum's byte length |
|
int copyBytes = bufferSize < datum->bytes? bufferSize : datum->bytes; |
|
return datum->getString(buffer, copyBytes, offset, size); |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
|
|
int OSCMessage::getBlob(int position, uint8_t * buffer){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getBlob(buffer); |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
int OSCMessage::getBlob(int position, uint8_t * buffer, int bufferSize){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getBlob(buffer, bufferSize); |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
int OSCMessage::getBlob(int position, uint8_t * buffer, int bufferSize, int offset, int size){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getBlob(buffer, bufferSize, offset, size); |
|
} else { |
|
return -1; |
|
} |
|
} |
|
|
|
const uint8_t* OSCMessage::getBlob(int position) { |
|
const auto datum = getOSCData(position); |
|
if(!hasError()) { |
|
return datum->getBlob(); |
|
} else { |
|
return nullptr; |
|
} |
|
} |
|
|
|
uint32_t OSCMessage::getBlobLength(int position) |
|
{ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->getBlobLength(); |
|
} else { |
|
return 0; |
|
} |
|
|
|
} |
|
|
|
char OSCMessage::getType(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->type; |
|
} else { |
|
return '\0'; |
|
} |
|
} |
|
|
|
int OSCMessage::getDataLength(int position){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->bytes; |
|
} else { |
|
return 0; |
|
} |
|
} |
|
|
|
/*============================================================================= |
|
TESTING DATA |
|
=============================================================================*/ |
|
|
|
bool OSCMessage::testType(int position, char type){ |
|
const auto datum = getOSCData(position); |
|
if (!hasError()){ |
|
return datum->type == type; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
bool OSCMessage::isInt(int position){ |
|
return testType(position, 'i'); |
|
} |
|
|
|
bool OSCMessage::isTime(int position){ |
|
return testType(position, 't'); |
|
} |
|
|
|
|
|
bool OSCMessage::isFloat(int position){ |
|
return testType(position, 'f'); |
|
} |
|
|
|
bool OSCMessage::isBlob(int position){ |
|
return testType(position, 'b'); |
|
} |
|
|
|
bool OSCMessage::isChar(int position){ |
|
return testType(position, 'c'); |
|
} |
|
|
|
bool OSCMessage::isString(int position){ |
|
return testType(position, 's'); |
|
} |
|
|
|
bool OSCMessage::isDouble(int position){ |
|
return testType(position, 'd'); |
|
} |
|
bool OSCMessage::isBoolean(int position){ |
|
return testType(position, 'T') || testType(position, 'F'); |
|
} |
|
|
|
|
|
/*============================================================================= |
|
PATTERN MATCHING |
|
=============================================================================*/ |
|
|
|
int OSCMessage::match(const char * pattern, int addr_offset){ |
|
int pattern_offset; |
|
int address_offset; |
|
int ret = osc_match(address + addr_offset, pattern, &pattern_offset, &address_offset); |
|
char * next = (char *) (address + addr_offset + pattern_offset); |
|
if (ret==3){ |
|
return pattern_offset; |
|
} else if (pattern_offset > 0 && *next == '/'){ |
|
return pattern_offset; |
|
} else { |
|
return 0; |
|
} |
|
} |
|
|
|
bool OSCMessage::fullMatch( const char * pattern, int addr_offset){ |
|
int pattern_offset; |
|
int address_offset; |
|
int ret = osc_match(address + addr_offset, pattern, &pattern_offset, &address_offset ); |
|
return (ret==3); |
|
} |
|
|
|
bool OSCMessage::dispatch(const char * pattern, void (*callback)(OSCMessage &), int addr_offset){ |
|
if (fullMatch(pattern, addr_offset)){ |
|
callback(*this); |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
bool OSCMessage::route(const char * pattern, void (*callback)(OSCMessage &, int), int initial_offset){ |
|
int match_offset = match(pattern, initial_offset); |
|
if (match_offset>0){ |
|
callback(*this, match_offset + initial_offset); |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
/*============================================================================= |
|
ADDRESS |
|
=============================================================================*/ |
|
|
|
int OSCMessage::getAddress(char * buffer, int offset){ |
|
int result = strlen(address); |
|
if (result > offset) |
|
strcpy(buffer, address+offset); |
|
else |
|
*buffer = 0; |
|
return result - offset; // could be negative! |
|
} |
|
|
|
int OSCMessage::getAddress(char * buffer, int offset, int len){ |
|
int result = strlen(address); |
|
|
|
if (result > offset) |
|
{ |
|
strncpy(buffer, address+offset, len); // N.B. NOT guaranteed to null-terminate! So... |
|
buffer[len-1] = 0; // ...prevent strlen() blowing up |
|
} |
|
else |
|
*buffer = 0; |
|
return strlen(buffer); |
|
} |
|
|
|
const char* OSCMessage::getAddress(){ |
|
return address; |
|
} |
|
|
|
int OSCMessage::getAddressLength(int offset) |
|
{ |
|
int result = (int) strlen(address) - offset; |
|
if (result < 0) // offset past end! |
|
result = 0; // do the best we can |
|
return result; |
|
} |
|
|
|
OSCMessage& OSCMessage::setAddress(const char * _address){ |
|
//free the previous address |
|
free(address); // are we sure address was allocated? |
|
//copy the address |
|
char * addressMemory = (char *) malloc( (strlen(_address) + 1) * sizeof(char) ); |
|
if (addressMemory == NULL){ |
|
error = ALLOCFAILED; |
|
address = NULL; |
|
} else { |
|
strcpy(addressMemory, _address); |
|
address = addressMemory; |
|
} |
|
return *this; |
|
} |
|
|
|
/*============================================================================= |
|
SIZE |
|
=============================================================================*/ |
|
|
|
#ifdef SLOWpadcalculation |
|
int OSCMessage::padSize(int _bytes){ |
|
int space = (_bytes + 3) / 4; |
|
space *= 4; |
|
return space - _bytes; |
|
} |
|
#else |
|
static inline int padSize(int bytes) { return (4- (bytes&03))&3; } |
|
#endif |
|
//returns the number of OSCData in the OSCMessage |
|
int OSCMessage::size(){ |
|
return dataCount; |
|
} |
|
|
|
int OSCMessage::bytes(){ |
|
int messageSize = 0; |
|
//send the address |
|
int addrLen = strlen(address) + 1; |
|
messageSize += addrLen; |
|
//padding amount |
|
int addrPad = padSize(addrLen); |
|
messageSize += addrPad; |
|
//add the comma separator |
|
messageSize += 1; |
|
//add the types |
|
messageSize += dataCount; |
|
//pad the types |
|
int typePad = padSize(dataCount + 1); //for the comma |
|
if (typePad == 0){ |
|
typePad = 4; // to make sure the type string is null terminated |
|
} |
|
messageSize+=typePad; |
|
//then the data |
|
for (int i = 0; i < dataCount; i++){ |
|
const auto datum = getOSCData(i); |
|
messageSize+=datum->bytes; |
|
messageSize += padSize(datum->bytes); |
|
} |
|
return messageSize; |
|
} |
|
|
|
/*============================================================================= |
|
ERROR HANDLING |
|
=============================================================================*/ |
|
|
|
bool OSCMessage::hasError(){ |
|
if(error != OSC_OK) return true; |
|
//test each of the data |
|
for (int i = 0; i < dataCount; i++){ |
|
if(getOSCData(i)->error) return true; |
|
} |
|
return false; |
|
} |
|
|
|
OSCErrorCode OSCMessage::getError(){ |
|
return error; |
|
} |
|
|
|
/*============================================================================= |
|
SENDING |
|
=============================================================================*/ |
|
|
|
OSCMessage& OSCMessage::send(Print &p){ |
|
//don't send a message with errors |
|
if (hasError()){ |
|
return *this; |
|
} |
|
uint8_t nullChar = '\0'; |
|
//send the address |
|
int addrLen = strlen(address) + 1; |
|
//padding amount |
|
int addrPad = padSize(addrLen); |
|
//write it to the stream |
|
p.write((uint8_t *) address, addrLen); |
|
//add the padding |
|
while(addrPad--){ |
|
p.write(nullChar); |
|
} |
|
//add the comma separator |
|
p.write((uint8_t) ','); |
|
//add the types |
|
#ifdef PAULSSUGGESTION |
|
// Paul suggested buffering on the stack |
|
// to improve performance. The problem is this could exhaust the stack |
|
// for long complex messages |
|
{ |
|
uint8_t typstr[dataCount]; |
|
|
|
for (int i = 0; i < dataCount; i++){ |
|
typstr[i] = getType(i); |
|
} |
|
p.write(typstr,dataCount); |
|
} |
|
#else |
|
for (int i = 0; i < dataCount; i++){ |
|
p.write((uint8_t) getType(i)); |
|
} |
|
#endif |
|
//pad the types |
|
int typePad = padSize(dataCount + 1); // 1 is for the comma |
|
if (typePad == 0){ |
|
typePad = 4; // This is because the type string has to be null terminated |
|
} |
|
while(typePad--){ |
|
p.write(nullChar); |
|
} |
|
//write the data |
|
for (int i = 0; i < dataCount; i++){ |
|
const auto datum = getOSCData(i); |
|
if ((datum->type == 's') || (datum->type == 'b')){ |
|
p.write(datum->data.b, datum->bytes); |
|
int dataPad = padSize(datum->bytes); |
|
while(dataPad--){ |
|
p.write(nullChar); |
|
} |
|
} else if (datum->type == 'd'){ |
|
double d = BigEndian(datum->data.d); |
|
uint8_t * ptr = (uint8_t *) &d; |
|
p.write(ptr, 8); |
|
} else if (datum->type == 't'){ |
|
osctime_t time = datum->data.time; |
|
uint32_t d = BigEndian(time.seconds); |
|
uint8_t * ptr = (uint8_t *) &d; |
|
p.write(ptr, 4); |
|
d = BigEndian(time.fractionofseconds); |
|
ptr = (uint8_t *) &d; |
|
p.write(ptr, 4); |
|
|
|
} else if (datum->type == 'T' || datum->type == 'F') |
|
{ } |
|
else { // float or int |
|
uint32_t i = BigEndian(datum->data.i); |
|
uint8_t * ptr = (uint8_t *) &i; |
|
p.write(ptr, datum->bytes); |
|
} |
|
} |
|
return *this; |
|
} |
|
|
|
/*============================================================================= |
|
FILLING |
|
=============================================================================*/ |
|
|
|
OSCMessage& OSCMessage::fill(uint8_t incomingByte){ |
|
decode(incomingByte); |
|
return *this; |
|
} |
|
|
|
OSCMessage& OSCMessage::fill(uint8_t * incomingBytes, int length){ |
|
while (length--){ |
|
decode(*incomingBytes++); |
|
} |
|
return *this; |
|
} |
|
|
|
/*============================================================================= |
|
DECODING |
|
=============================================================================*/ |
|
|
|
void OSCMessage::decodeAddress(){ |
|
setAddress((char *) incomingBuffer); |
|
//change the error from invalid message |
|
error = OSC_OK; |
|
clearIncomingBuffer(); |
|
} |
|
|
|
void OSCMessage::decodeType(uint8_t incomingByte){ |
|
char type = incomingByte; |
|
add(type); |
|
} |
|
|
|
void OSCMessage::decodeData(uint8_t incomingByte){ |
|
//get the first OSCData to re-set |
|
for (int i = 0; i < dataCount; i++){ |
|
const auto datum = getOSCData(i); |
|
if (datum->error == INVALID_OSC){ |
|
//set the contents of datum with the data received |
|
switch (datum->type){ |
|
case 'i': |
|
if (incomingBufferSize == 4){ |
|
//parse the buffer as an int |
|
union { |
|
int32_t i; |
|
uint8_t b[4]; |
|
} u; |
|
memcpy(u.b, incomingBuffer, 4); |
|
int32_t dataVal = BigEndian(u.i); |
|
set(i, dataVal); |
|
clearIncomingBuffer(); |
|
} |
|
break; |
|
case 'f': |
|
if (incomingBufferSize == 4){ |
|
//parse the buffer as a float |
|
union { |
|
float f; |
|
uint8_t b[4]; |
|
} u; |
|
memcpy(u.b, incomingBuffer, 4); |
|
float dataVal = BigEndian(u.f); |
|
set(i, dataVal); |
|
clearIncomingBuffer(); |
|
} |
|
break; |
|
case 'd': |
|
if (incomingBufferSize == 8){ |
|
//parse the buffer as a double |
|
union { |
|
double d; |
|
uint8_t b[8]; |
|
} u; |
|
memcpy(u.b, incomingBuffer, 8); |
|
double dataVal = BigEndian(u.d); |
|
set(i, dataVal); |
|
clearIncomingBuffer(); |
|
} |
|
break; |
|
case 't': |
|
if (incomingBufferSize == 8){ |
|
//parse the buffer as a timetag |
|
union { |
|
osctime_t t; |
|
uint8_t b[8]; |
|
} u; |
|
memcpy(u.b, incomingBuffer, 8); |
|
|
|
u.t.seconds = BigEndian(u.t.seconds); |
|
u.t.fractionofseconds = BigEndian(u.t.fractionofseconds); |
|
set(i, u.t); |
|
clearIncomingBuffer(); |
|
} |
|
break; |
|
|
|
case 's': |
|
if (incomingByte == 0){ |
|
char * str = (char *) incomingBuffer; |
|
set(i, str); |
|
clearIncomingBuffer(); |
|
decodeState = DATA_PADDING; |
|
} |
|
break; |
|
case 'b': |
|
if (incomingBufferSize > 4){ |
|
//compute the expected blob size |
|
union { |
|
uint32_t i; |
|
uint8_t b[4]; |
|
} u; |
|
memcpy(u.b, incomingBuffer, 4); |
|
uint32_t blobLength = BigEndian(u.i); |
|
if (incomingBufferSize == (int)(blobLength + 4)){ |
|
set(i, incomingBuffer + 4, blobLength); |
|
clearIncomingBuffer(); |
|
decodeState = DATA_PADDING; |
|
} |
|
|
|
} |
|
break; |
|
} |
|
//break out of the for loop once we've selected the first invalid message |
|
break; |
|
} |
|
} |
|
} |
|
|
|
//does not validate the incoming OSC for correctness |
|
void OSCMessage::decode(uint8_t incomingByte){ |
|
addToIncomingBuffer(incomingByte); |
|
switch (decodeState){ |
|
case STANDBY: |
|
if (incomingByte == '/'){ |
|
decodeState = ADDRESS; |
|
} |
|
break; |
|
case ADDRESS: |
|
if (incomingByte == 0){ |
|
//end of the address |
|
//decode the address |
|
decodeAddress(); |
|
//next state |
|
decodeState = ADDRESS_PADDING; |
|
} |
|
break; |
|
case ADDRESS_PADDING: |
|
//it does not count the padding |
|
if (incomingByte==','){ |
|
//next state |
|
decodeState = TYPES; |
|
clearIncomingBuffer(); |
|
} |
|
break; |
|
case TYPES: |
|
if (incomingByte != 0){ |
|
//next state |
|
decodeType(incomingByte); |
|
} else { |
|
decodeState = TYPES_PADDING; |
|
} |
|
//FALL THROUGH to test if it should go to the data state |
|
case TYPES_PADDING: { |
|
//compute the padding size for the types |
|
//to determine the start of the data section |
|
int typePad = padSize(dataCount + 1); // 1 is the comma |
|
if (typePad == 0){ |
|
typePad = 4; // to make sure it will be null terminated |
|
} |
|
if (incomingBufferSize == (typePad + dataCount)){ |
|
clearIncomingBuffer(); |
|
decodeState = DATA; |
|
} |
|
} |
|
break; |
|
case DATA: |
|
decodeData(incomingByte); |
|
break; |
|
case DATA_PADDING:{ |
|
//get the last valid data |
|
for (int i = dataCount - 1; i >= 0; i--){ |
|
const auto datum = getOSCData(i); |
|
if (datum->error == OSC_OK){ |
|
//compute the padding size for the data |
|
int dataPad = padSize(datum->bytes); |
|
// if there is no padding required, switch back to DATA, and don't clear the incomingBuffer because it holds next data |
|
if (dataPad == 0){ |
|
decodeState = DATA; |
|
} |
|
else if (incomingBufferSize == dataPad){ |
|
clearIncomingBuffer(); |
|
decodeState = DATA; |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
break; |
|
case DONE: |
|
break; // TODO: is this correct? - was missing from original code, it did this by default |
|
} |
|
} |
|
|
|
|
|
/*============================================================================= |
|
INCOMING BUFFER MANAGEMENT |
|
=============================================================================*/ |
|
#define OSCPREALLOCATEIZE 16 |
|
void OSCMessage::addToIncomingBuffer(uint8_t incomingByte){ |
|
//realloc some space for the new byte and stick it on the end |
|
if(incomingBufferFree>0) |
|
{ |
|
incomingBuffer[incomingBufferSize++] = incomingByte; |
|
incomingBufferFree--; |
|
} |
|
else |
|
{ |
|
|
|
incomingBuffer = (uint8_t *) realloc ( incomingBuffer, incomingBufferSize + 1 + OSCPREALLOCATEIZE); |
|
if (incomingBuffer != NULL){ |
|
incomingBuffer[incomingBufferSize++] = incomingByte; |
|
incomingBufferFree = OSCPREALLOCATEIZE; |
|
} else { |
|
error = ALLOCFAILED; |
|
} |
|
} |
|
} |
|
|
|
void OSCMessage::clearIncomingBuffer(){ |
|
incomingBuffer = (uint8_t *) realloc ( incomingBuffer, OSCPREALLOCATEIZE); |
|
if (incomingBuffer != NULL){ |
|
incomingBufferFree = OSCPREALLOCATEIZE; |
|
} else { |
|
error = ALLOCFAILED; |
|
incomingBuffer = NULL; |
|
|
|
} |
|
incomingBufferSize = 0; |
|
}
|
|
|