Ibiltari Nora / OSC
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OSCMessage.h Source File

OSCMessage.h

00001 /* mbed OSC Library
00002  This is an Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the
00003  Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige
00004  written by: Alvaro Cassinelli, October 2011
00005  tweaked by: Toby Harris / *spark audio-visual, March 2012
00006 
00007  This library is free software; you can redistribute it and/or
00008  modify it under the terms of the GNU Lesser General Public
00009  License version 2.1 as published by the Free Software Foundation.
00010  Open Sound Control  http://opensoundcontrol.org/
00011 */
00012 
00013 #ifndef mbedOSC_h
00014 #define mbedOSC_h
00015 
00016 #include "mbed.h"
00017 #include "EthernetInterface.h"
00018 #include "UDPSocket.h"
00019 #include "OSCData.h"
00020 
00021 class OSCMessage
00022 {
00023 
00024 private:
00025 
00026     //friends
00027     friend class OSCBundle;
00028 
00029 
00030 /*=============================================================================
00031     PRIVATE VARIABLES
00032 =============================================================================*/
00033 
00034     //the address
00035     char * address;
00036 
00037     //the data
00038     OSCData ** data;
00039 
00040     //the number of OSCData in the data array
00041     int dataCount;
00042 
00043     //error codes for potential runtime problems
00044     OSCErrorCode error;
00045 
00046 /*=============================================================================
00047     DECODING INCOMING BYTES
00048  =============================================================================*/
00049 
00050     //the decoding states for incoming bytes
00051     enum DecodeState {
00052         STANDBY,
00053         ADDRESS,
00054         ADDRESS_PADDING,
00055         TYPES,
00056         TYPES_PADDING,
00057         DATA,
00058         DATA_PADDING,
00059         DONE,
00060     } decodeState;
00061 
00062     //stores incoming bytes until they can be decoded
00063     uint8_t * incomingBuffer;
00064     int incomingBufferSize; // how many bytes are stored
00065     int incomingBufferFree; // how many bytes are allocated but unused
00066 
00067     //adds a byte to the buffer
00068     void addToIncomingBuffer(uint8_t);
00069     //clears the incoming buffer
00070     void clearIncomingBuffer();
00071 
00072     //decoding function
00073     void decode(uint8_t);
00074     void decodeAddress();
00075     void decodeType(uint8_t);
00076     void decodeData(uint8_t);
00077 
00078 /*=============================================================================
00079     HELPER FUNCTIONS
00080 =============================================================================*/
00081 
00082     void setupMessage();
00083 
00084     //compares the OSCData's type char to a test char
00085     bool testType(int position, char type);
00086 
00087     //returns the number of bytes to pad to make it 4-bit aligned
00088     int padSize(int bytes);
00089 
00090 public:
00091 
00092     //returns the OSCData at that position
00093     OSCData * getOSCData(int);
00094 
00095 /*=============================================================================
00096     CONSTRUCTORS / DESTRUCTOR
00097 =============================================================================*/
00098 
00099     //new constructor needs an address
00100     OSCMessage (const char * _address);
00101     //no address
00102     //placeholder since it's invalide OSC
00103     OSCMessage();
00104 
00105     //can optionally accept all of the data after the address
00106     //OSCMessage(const char * _address, char * types, ... );
00107     //created from another OSCMessage
00108     OSCMessage (OSCMessage *);
00109 
00110 
00111     //DESTRUCTOR
00112     ~OSCMessage();
00113 
00114     //empties all of the data
00115     OSCMessage& empty();
00116 
00117     void copy(OSCMessage * msg);
00118 
00119 
00120 /*=============================================================================
00121     SETTING  DATA
00122 =============================================================================*/
00123 
00124     //returns the OSCMessage so that multiple 'add's can be strung together
00125     template <typename T>
00126     OSCMessage& add(T datum){
00127         //make a piece of data
00128         OSCData * d = new OSCData(datum);
00129         //check if it has any errors
00130         if (d->error == ALLOCFAILED){
00131             error = ALLOCFAILED;
00132         } else {
00133             //resize the data array
00134             OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1));
00135             if (dataMem == NULL){
00136                 error = ALLOCFAILED;
00137             } else {
00138                 data = dataMem;
00139                 //add data to the end of the array
00140                 data[dataCount] = d;
00141                 //increment the data size
00142                 dataCount++;
00143             }
00144         }
00145         return *this;
00146     }
00147 
00148     //blob specific add
00149     OSCMessage& add(uint8_t * blob, int length){
00150         //make a piece of data
00151         OSCData * d = new OSCData(blob, length);
00152         //check if it has any errors
00153         if (d->error == ALLOCFAILED){
00154             error = ALLOCFAILED;
00155         } else {
00156             //resize the data array
00157             OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1));
00158             if (dataMem == NULL){
00159                 error = ALLOCFAILED;
00160             } else {
00161                 data = dataMem;
00162                 //add data to the end of the array
00163                 data[dataCount] = d;
00164                 //increment the data size
00165                 dataCount++;
00166             }
00167         }
00168         return *this;
00169     }
00170 
00171     //sets the data at a position
00172     template <typename T>
00173     OSCMessage& set(int position, T datum){
00174         if (position < dataCount){
00175             //replace the OSCData with a new one
00176             OSCData * oldDatum = getOSCData(position);
00177             //destroy the old one
00178             delete oldDatum;
00179             //make a new one
00180             OSCData * newDatum = new OSCData(datum);
00181             //test if there was an error
00182             if (newDatum->error == ALLOCFAILED){
00183                 error = ALLOCFAILED;
00184             } else {
00185                 //otherwise, put it in the data array
00186                 data[position] = newDatum;
00187             }
00188         } else if (position == (dataCount)){
00189             //add the data to the end
00190             add(datum);
00191         } else {
00192             //else out of bounds error
00193             error = INDEX_OUT_OF_BOUNDS;
00194         }
00195         return *this;
00196     }
00197 
00198     //blob specific setter
00199     OSCMessage& set(int position, uint8_t * blob, int length){
00200         if (position < dataCount){
00201             //replace the OSCData with a new one
00202             OSCData * oldDatum = getOSCData(position);
00203             //destroy the old one
00204             delete oldDatum;
00205             //make a new one
00206             OSCData * newDatum = new OSCData(blob, length);
00207             //test if there was an error
00208             if (newDatum->error == ALLOCFAILED){
00209                 error = ALLOCFAILED;
00210             } else {
00211                 //otherwise, put it in the data array
00212                 data[position] = newDatum;
00213             }
00214         } else if (position == (dataCount)){
00215             //add the data to the end
00216             add(blob, length);
00217         } else {
00218             //else out of bounds error
00219             error = INDEX_OUT_OF_BOUNDS;
00220         }
00221         return *this;
00222     }
00223 
00224     OSCMessage& setAddress(const char *);
00225 
00226 /*=============================================================================
00227     GETTING DATA
00228 
00229     getters take a position as an argument
00230 =============================================================================*/
00231 
00232     int32_t getInt(int);
00233     osctime_t getTime(int);
00234 
00235     float getFloat(int);
00236     double getDouble(int);
00237     bool getBoolean(int);
00238 
00239     //return the copied string's length
00240     int getString(int, char *);
00241     //check that it won't overflow the passed buffer's size with a third argument
00242     int getString(int, char *, int);
00243     //offset and size can be defined in order to only query a part of the string
00244     int getString(int, char *, int, int, int);
00245 
00246     //returns the number of unsigned int8's copied into the buffer
00247     int getBlob(int, uint8_t *);
00248     //check that it won't overflow the passed buffer's size with a third argument
00249     int getBlob(int, uint8_t *, int);
00250     //offset and size can be defined in order to only query a part of the blob's content
00251     int getBlob(int, uint8_t *, int, int, int);
00252 
00253 
00254     // returns the length of blob
00255     uint32_t getBlobLength(int position);
00256 
00257     //returns the number of bytes of the data at that position
00258     int getDataLength(int);
00259 
00260     //returns the type at the position
00261     char getType(int);
00262 
00263     //put the address in the buffer
00264     const char * getAddress( int offset = 0);
00265     int getAddress(char * buffer, int offset, int len);
00266 
00267     int getAddressLength(int offset = 0);
00268 
00269 
00270 /*=============================================================================
00271     TESTING DATA
00272 
00273     testers take a position as an argument
00274 =============================================================================*/
00275 
00276     bool isInt(int);
00277     bool isFloat(int);
00278     bool isBlob(int);
00279     bool isChar(int);
00280     bool isString(int);
00281     bool isDouble(int);
00282     bool isBoolean(int);
00283     bool isTime(int);
00284 
00285 /*=============================================================================
00286     PATTERN MATCHING
00287 =============================================================================*/
00288 
00289     //match the pattern against the address
00290     //returns true only for a complete match
00291     bool fullMatch( const char * pattern, int = 0);
00292 
00293     //returns the number of characters matched in the address
00294     int match( const char * pattern, int = 0);
00295 
00296     //calls the function with the message as the arg if it was a full match
00297     bool dispatch(const char * pattern, void (*callback)(OSCMessage &), int = 0);
00298 
00299     //like dispatch, but allows for partial matches
00300     //the address match offset is sent as an argument to the callback
00301     //also room for an option address offset to allow for multiple nested routes
00302     bool route(const char * pattern, void (*callback)(OSCMessage &, int), int = 0);
00303 
00304 
00305 
00306 /*=============================================================================
00307     SIZE
00308 =============================================================================*/
00309 
00310     //the number of data that the message contains
00311     int size();
00312 
00313     //computes the number of bytes the OSCMessage occupies if everything is 32-bit aligned
00314     int bytes();
00315 
00316 /*=============================================================================
00317     TRANSMISSION
00318  =============================================================================*/
00319 
00320     //send the message
00321     OSCMessage& send(UDPSocket &p, const SocketAddress &address);
00322 
00323 
00324     //fill the message from a byte stream
00325     OSCMessage& fill(uint8_t);
00326     OSCMessage& fill(uint8_t *, int);
00327 
00328 /*=============================================================================
00329     ERROR
00330 =============================================================================*/
00331 
00332     bool hasError();
00333 
00334     OSCErrorCode getError();
00335 
00336 };
00337 
00338 
00339 #endif