|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- /*
- 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
- */
-
- #ifndef OSCMESSAGE_h
- #define OSCMESSAGE_h
-
- #include "OSCData.h"
- #include <Print.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();
-
- /*=============================================================================
- 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 *, int);
- //returns the number of unsigned int8's copied into the buffer
- int getBlob(int, uint8_t *, int);
-
- //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
- int getAddress(char * buffer, int offset = 0);
- int getAddress(char * buffer, int offset, int len);
-
- // TODO: 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(Print &p);
-
- //fill the message from a byte stream
- OSCMessage& fill(uint8_t);
- OSCMessage& fill(uint8_t *, int);
-
- /*=============================================================================
- ERROR
- =============================================================================*/
-
- bool hasError();
-
- OSCErrorCode getError();
-
- };
-
- #endif
|