Fork of, triyin to rewrite for mbed 5. WIP not yet finished but working. ----------------------- An Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige written by: Alvaro Cassinelli, October 2011 tweaked by: Toby Harris / *spark audio-visual, March 2012
OSCMessage.h
- Committer:
- Ibiltari
- Date:
- 2021-11-04
- Revision:
- 19:35408d190f4e
- Parent:
- 17:9479c15a9d54
File content as of revision 19:35408d190f4e:
/* mbed OSC Library This is an Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige written by: Alvaro Cassinelli, October 2011 tweaked by: Toby Harris / *spark audio-visual, March 2012 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. Open Sound Control http://opensoundcontrol.org/ */ #ifndef mbedOSC_h #define mbedOSC_h #include "mbed.h" #include "EthernetInterface.h" #include "UDPSocket.h" #include "OSCData.h" class OSCMessage { private: //friends friend class OSCBundle; /*============================================================================= PRIVATE VARIABLES =============================================================================*/ //the address char * address; //the data OSCData ** data; //the number of OSCData in the data array int dataCount; //error codes for potential runtime problems OSCErrorCode error; /*============================================================================= DECODING INCOMING BYTES =============================================================================*/ //the decoding states for incoming bytes enum DecodeState { STANDBY, ADDRESS, ADDRESS_PADDING, TYPES, TYPES_PADDING, DATA, DATA_PADDING, DONE, } decodeState; //stores incoming bytes until they can be decoded uint8_t * incomingBuffer; int incomingBufferSize; // how many bytes are stored int incomingBufferFree; // how many bytes are allocated but unused //adds a byte to the buffer void addToIncomingBuffer(uint8_t); //clears the incoming buffer void clearIncomingBuffer(); //decoding function void decode(uint8_t); void decodeAddress(); void decodeType(uint8_t); void decodeData(uint8_t); /*============================================================================= HELPER FUNCTIONS =============================================================================*/ void setupMessage(); //compares the OSCData's type char to a test char bool testType(int position, char type); //returns the number of bytes to pad to make it 4-bit aligned int padSize(int bytes); public: //returns the OSCData at that position OSCData * getOSCData(int); /*============================================================================= CONSTRUCTORS / DESTRUCTOR =============================================================================*/ //new constructor needs an address OSCMessage (const char * _address); //no address //placeholder since it's invalide OSC OSCMessage(); //can optionally accept all of the data after the address //OSCMessage(const char * _address, char * types, ... ); //created from another OSCMessage OSCMessage (OSCMessage *); //DESTRUCTOR ~OSCMessage(); //empties all of the data OSCMessage& empty(); void copy(OSCMessage * msg); /*============================================================================= SETTING DATA =============================================================================*/ //returns the OSCMessage so that multiple 'add's can be strung together template <typename T> OSCMessage& add(T datum){ //make a piece of data OSCData * d = new OSCData(datum); //check if it has any errors if (d->error == ALLOCFAILED){ error = ALLOCFAILED; } else { //resize the data array OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1)); if (dataMem == NULL){ error = ALLOCFAILED; } else { data = dataMem; //add data to the end of the array data[dataCount] = d; //increment the data size dataCount++; } } return *this; } //blob specific add OSCMessage& add(uint8_t * blob, int length){ //make a piece of data OSCData * d = new OSCData(blob, length); //check if it has any errors if (d->error == ALLOCFAILED){ error = ALLOCFAILED; } else { //resize the data array OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1)); if (dataMem == NULL){ error = ALLOCFAILED; } else { data = dataMem; //add data to the end of the array data[dataCount] = d; //increment the data size dataCount++; } } return *this; } //sets the data at a position template <typename T> OSCMessage& set(int position, T datum){ if (position < dataCount){ //replace the OSCData with a new one OSCData * oldDatum = getOSCData(position); //destroy the old one delete oldDatum; //make a new one OSCData * newDatum = new OSCData(datum); //test if there was an error if (newDatum->error == ALLOCFAILED){ error = ALLOCFAILED; } else { //otherwise, put it in the data array data[position] = newDatum; } } else if (position == (dataCount)){ //add the data to the end add(datum); } else { //else out of bounds error error = INDEX_OUT_OF_BOUNDS; } return *this; } //blob specific setter OSCMessage& set(int position, uint8_t * blob, int length){ if (position < dataCount){ //replace the OSCData with a new one OSCData * oldDatum = getOSCData(position); //destroy the old one delete oldDatum; //make a new one OSCData * newDatum = new OSCData(blob, length); //test if there was an error if (newDatum->error == ALLOCFAILED){ error = ALLOCFAILED; } else { //otherwise, put it in the data array data[position] = newDatum; } } else if (position == (dataCount)){ //add the data to the end add(blob, length); } else { //else out of bounds error error = INDEX_OUT_OF_BOUNDS; } return *this; } OSCMessage& setAddress(const char *); /*============================================================================= GETTING DATA getters take a position as an argument =============================================================================*/ int32_t getInt(int); osctime_t getTime(int); float getFloat(int); double getDouble(int); bool getBoolean(int); //return the copied string's length int getString(int, char *); //check that it won't overflow the passed buffer's size with a third argument int getString(int, char *, int); //offset and size can be defined in order to only query a part of the string int getString(int, char *, int, int, int); //returns the number of unsigned int8's copied into the buffer int getBlob(int, uint8_t *); //check that it won't overflow the passed buffer's size with a third argument int getBlob(int, uint8_t *, int); //offset and size can be defined in order to only query a part of the blob's content int getBlob(int, uint8_t *, int, int, int); // returns the length of blob uint32_t getBlobLength(int position); //returns the number of bytes of the data at that position int getDataLength(int); //returns the type at the position char getType(int); //put the address in the buffer const char * getAddress( int offset = 0); int getAddress(char * buffer, int offset, int len); int getAddressLength(int offset = 0); /*============================================================================= TESTING DATA testers take a position as an argument =============================================================================*/ bool isInt(int); bool isFloat(int); bool isBlob(int); bool isChar(int); bool isString(int); bool isDouble(int); bool isBoolean(int); bool isTime(int); /*============================================================================= PATTERN MATCHING =============================================================================*/ //match the pattern against the address //returns true only for a complete match bool fullMatch( const char * pattern, int = 0); //returns the number of characters matched in the address int match( const char * pattern, int = 0); //calls the function with the message as the arg if it was a full match bool dispatch(const char * pattern, void (*callback)(OSCMessage &), int = 0); //like dispatch, but allows for partial matches //the address match offset is sent as an argument to the callback //also room for an option address offset to allow for multiple nested routes bool route(const char * pattern, void (*callback)(OSCMessage &, int), int = 0); /*============================================================================= SIZE =============================================================================*/ //the number of data that the message contains int size(); //computes the number of bytes the OSCMessage occupies if everything is 32-bit aligned int bytes(); /*============================================================================= TRANSMISSION =============================================================================*/ //send the message OSCMessage& send(UDPSocket &p, const SocketAddress &address); //fill the message from a byte stream OSCMessage& fill(uint8_t); OSCMessage& fill(uint8_t *, int); /*============================================================================= ERROR =============================================================================*/ bool hasError(); OSCErrorCode getError(); }; #endif