modded version CNMAT/OSC https://github.com/CNMAT/OSC

Dependents:   CVtoOSCConverter

Fork of osc-cnmat by Asperius van Hansen

Committer:
casiotone401
Date:
Sat Feb 13 11:29:14 2016 +0000
Revision:
4:107c23eb31b6
Parent:
2:61caa2495215
OSCMessage::send & OSCBundle::send supports return OSC buffer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aspeteRakete 1:18009e3041ea 1 /*
aspeteRakete 1:18009e3041ea 2 Written by Yotam Mann, The Center for New Music and Audio Technologies,
aspeteRakete 1:18009e3041ea 3 University of California, Berkeley. Copyright (c) 2012, The Regents of
aspeteRakete 1:18009e3041ea 4 the University of California (Regents).
aspeteRakete 1:18009e3041ea 5
aspeteRakete 1:18009e3041ea 6 Permission to use, copy, modify, distribute, and distribute modified versions
aspeteRakete 1:18009e3041ea 7 of this software and its documentation without fee and without a signed
aspeteRakete 1:18009e3041ea 8 licensing agreement, is hereby granted, provided that the above copyright
aspeteRakete 1:18009e3041ea 9 notice, this paragraph and the following two paragraphs appear in all copies,
aspeteRakete 1:18009e3041ea 10 modifications, and distributions.
aspeteRakete 1:18009e3041ea 11
aspeteRakete 1:18009e3041ea 12 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
aspeteRakete 1:18009e3041ea 13 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
aspeteRakete 1:18009e3041ea 14 OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
aspeteRakete 1:18009e3041ea 15 BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
aspeteRakete 1:18009e3041ea 16
aspeteRakete 1:18009e3041ea 17 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
aspeteRakete 1:18009e3041ea 18 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
aspeteRakete 1:18009e3041ea 19 PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
aspeteRakete 1:18009e3041ea 20 HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
aspeteRakete 1:18009e3041ea 21 MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
aspeteRakete 1:18009e3041ea 22
aspeteRakete 1:18009e3041ea 23 For bug reports and feature requests please email me at yotam@cnmat.berkeley.edu
aspeteRakete 1:18009e3041ea 24 */
aspeteRakete 1:18009e3041ea 25
aspeteRakete 1:18009e3041ea 26 #ifndef OSCMESSAGE_h
aspeteRakete 1:18009e3041ea 27 #define OSCMESSAGE_h
aspeteRakete 1:18009e3041ea 28
aspeteRakete 1:18009e3041ea 29 #include "OSCData.h"
aspeteRakete 2:61caa2495215 30 #include "Stream.h"
aspeteRakete 1:18009e3041ea 31 //#include <Print.h>
aspeteRakete 1:18009e3041ea 32
aspeteRakete 2:61caa2495215 33 using namespace mbed;
aspeteRakete 1:18009e3041ea 34 class OSCMessage
aspeteRakete 1:18009e3041ea 35 {
aspeteRakete 1:18009e3041ea 36
aspeteRakete 1:18009e3041ea 37 private:
aspeteRakete 1:18009e3041ea 38
aspeteRakete 1:18009e3041ea 39 //friends
aspeteRakete 1:18009e3041ea 40 friend class OSCBundle;
aspeteRakete 1:18009e3041ea 41
aspeteRakete 1:18009e3041ea 42
aspeteRakete 1:18009e3041ea 43 /*=============================================================================
aspeteRakete 1:18009e3041ea 44 PRIVATE VARIABLES
aspeteRakete 1:18009e3041ea 45 =============================================================================*/
aspeteRakete 1:18009e3041ea 46
casiotone401 4:107c23eb31b6 47 //buffer array index offset for bundle
casiotone401 4:107c23eb31b6 48 uint16_t bundleOffset;
casiotone401 4:107c23eb31b6 49
aspeteRakete 1:18009e3041ea 50 //the address
aspeteRakete 1:18009e3041ea 51 char * address;
aspeteRakete 1:18009e3041ea 52
aspeteRakete 1:18009e3041ea 53 //the data
aspeteRakete 1:18009e3041ea 54 OSCData ** data;
aspeteRakete 1:18009e3041ea 55
aspeteRakete 1:18009e3041ea 56 //the number of OSCData in the data array
aspeteRakete 1:18009e3041ea 57 int dataCount;
aspeteRakete 1:18009e3041ea 58
aspeteRakete 1:18009e3041ea 59 //error codes for potential runtime problems
aspeteRakete 1:18009e3041ea 60 OSCErrorCode error;
aspeteRakete 1:18009e3041ea 61
aspeteRakete 1:18009e3041ea 62 /*=============================================================================
aspeteRakete 1:18009e3041ea 63 DECODING INCOMING BYTES
aspeteRakete 1:18009e3041ea 64 =============================================================================*/
aspeteRakete 1:18009e3041ea 65
aspeteRakete 1:18009e3041ea 66 //the decoding states for incoming bytes
aspeteRakete 1:18009e3041ea 67 enum DecodeState {
aspeteRakete 1:18009e3041ea 68 STANDBY,
aspeteRakete 1:18009e3041ea 69 ADDRESS,
aspeteRakete 1:18009e3041ea 70 ADDRESS_PADDING,
aspeteRakete 1:18009e3041ea 71 TYPES,
aspeteRakete 1:18009e3041ea 72 TYPES_PADDING,
aspeteRakete 1:18009e3041ea 73 DATA,
aspeteRakete 1:18009e3041ea 74 DATA_PADDING,
aspeteRakete 1:18009e3041ea 75 DONE,
aspeteRakete 1:18009e3041ea 76 } decodeState;
aspeteRakete 1:18009e3041ea 77
aspeteRakete 1:18009e3041ea 78 //stores incoming bytes until they can be decoded
aspeteRakete 1:18009e3041ea 79 uint8_t * incomingBuffer;
aspeteRakete 1:18009e3041ea 80 int incomingBufferSize; // how many bytes are stored
aspeteRakete 1:18009e3041ea 81 int incomingBufferFree; // how many bytes are allocated but unused
aspeteRakete 1:18009e3041ea 82
aspeteRakete 1:18009e3041ea 83 //adds a byte to the buffer
aspeteRakete 1:18009e3041ea 84 void addToIncomingBuffer(uint8_t);
aspeteRakete 1:18009e3041ea 85 //clears the incoming buffer
aspeteRakete 1:18009e3041ea 86 void clearIncomingBuffer();
aspeteRakete 1:18009e3041ea 87
aspeteRakete 1:18009e3041ea 88 //decoding function
aspeteRakete 1:18009e3041ea 89 void decode(uint8_t);
aspeteRakete 1:18009e3041ea 90 void decodeAddress();
aspeteRakete 1:18009e3041ea 91 void decodeType(uint8_t);
aspeteRakete 1:18009e3041ea 92 void decodeData(uint8_t);
aspeteRakete 1:18009e3041ea 93
aspeteRakete 1:18009e3041ea 94 /*=============================================================================
aspeteRakete 1:18009e3041ea 95 HELPER FUNCTIONS
aspeteRakete 1:18009e3041ea 96 =============================================================================*/
aspeteRakete 1:18009e3041ea 97
aspeteRakete 1:18009e3041ea 98 void setupMessage();
aspeteRakete 1:18009e3041ea 99
aspeteRakete 1:18009e3041ea 100 //compares the OSCData's type char to a test char
aspeteRakete 1:18009e3041ea 101 bool testType(int position, char type);
aspeteRakete 1:18009e3041ea 102
aspeteRakete 1:18009e3041ea 103 //returns the number of bytes to pad to make it 4-bit aligned
aspeteRakete 1:18009e3041ea 104 // int padSize(int bytes);
aspeteRakete 1:18009e3041ea 105
aspeteRakete 1:18009e3041ea 106 public:
aspeteRakete 1:18009e3041ea 107
aspeteRakete 1:18009e3041ea 108 //returns the OSCData at that position
aspeteRakete 1:18009e3041ea 109 OSCData * getOSCData(int);
aspeteRakete 1:18009e3041ea 110
aspeteRakete 1:18009e3041ea 111 /*=============================================================================
aspeteRakete 1:18009e3041ea 112 CONSTRUCTORS / DESTRUCTOR
aspeteRakete 1:18009e3041ea 113 =============================================================================*/
aspeteRakete 1:18009e3041ea 114
aspeteRakete 1:18009e3041ea 115 //new constructor needs an address
aspeteRakete 1:18009e3041ea 116 OSCMessage (const char * _address);
aspeteRakete 1:18009e3041ea 117 //no address
aspeteRakete 1:18009e3041ea 118 //placeholder since it's invalide OSC
aspeteRakete 1:18009e3041ea 119 OSCMessage();
aspeteRakete 1:18009e3041ea 120
aspeteRakete 1:18009e3041ea 121 //can optionally accept all of the data after the address
aspeteRakete 1:18009e3041ea 122 //OSCMessage(const char * _address, char * types, ... );
aspeteRakete 1:18009e3041ea 123 //created from another OSCMessage
aspeteRakete 1:18009e3041ea 124 OSCMessage (OSCMessage *);
aspeteRakete 1:18009e3041ea 125
aspeteRakete 1:18009e3041ea 126 //DESTRUCTOR
aspeteRakete 1:18009e3041ea 127 ~OSCMessage();
aspeteRakete 1:18009e3041ea 128
aspeteRakete 1:18009e3041ea 129 //empties all of the data
aspeteRakete 1:18009e3041ea 130 void empty();
aspeteRakete 1:18009e3041ea 131
aspeteRakete 1:18009e3041ea 132 /*=============================================================================
aspeteRakete 1:18009e3041ea 133 SETTING DATA
aspeteRakete 1:18009e3041ea 134 =============================================================================*/
aspeteRakete 1:18009e3041ea 135
aspeteRakete 1:18009e3041ea 136 //returns the OSCMessage so that multiple 'add's can be strung together
aspeteRakete 1:18009e3041ea 137 template <typename T>
aspeteRakete 1:18009e3041ea 138 OSCMessage& add(T datum){
aspeteRakete 1:18009e3041ea 139 //make a piece of data
aspeteRakete 1:18009e3041ea 140 OSCData * d = new OSCData(datum);
aspeteRakete 1:18009e3041ea 141 //check if it has any errors
aspeteRakete 1:18009e3041ea 142 if (d->error == ALLOCFAILED){
aspeteRakete 1:18009e3041ea 143 error = ALLOCFAILED;
aspeteRakete 1:18009e3041ea 144 } else {
aspeteRakete 1:18009e3041ea 145 //resize the data array
aspeteRakete 1:18009e3041ea 146 OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1));
aspeteRakete 1:18009e3041ea 147 if (dataMem == NULL){
aspeteRakete 1:18009e3041ea 148 error = ALLOCFAILED;
aspeteRakete 1:18009e3041ea 149 } else {
aspeteRakete 1:18009e3041ea 150 data = dataMem;
aspeteRakete 1:18009e3041ea 151 //add data to the end of the array
aspeteRakete 1:18009e3041ea 152 data[dataCount] = d;
aspeteRakete 1:18009e3041ea 153 //increment the data size
aspeteRakete 1:18009e3041ea 154 dataCount++;
aspeteRakete 1:18009e3041ea 155 }
aspeteRakete 1:18009e3041ea 156 }
aspeteRakete 1:18009e3041ea 157 return *this;
aspeteRakete 1:18009e3041ea 158 }
aspeteRakete 1:18009e3041ea 159
aspeteRakete 1:18009e3041ea 160 //blob specific add
aspeteRakete 1:18009e3041ea 161 OSCMessage& add(uint8_t * blob, int length){
aspeteRakete 1:18009e3041ea 162 //make a piece of data
aspeteRakete 1:18009e3041ea 163 OSCData * d = new OSCData(blob, length);
aspeteRakete 1:18009e3041ea 164 //check if it has any errors
aspeteRakete 1:18009e3041ea 165 if (d->error == ALLOCFAILED){
aspeteRakete 1:18009e3041ea 166 error = ALLOCFAILED;
aspeteRakete 1:18009e3041ea 167 } else {
aspeteRakete 1:18009e3041ea 168 //resize the data array
aspeteRakete 1:18009e3041ea 169 OSCData ** dataMem = (OSCData **) realloc(data, sizeof(OSCData *) * (dataCount + 1));
aspeteRakete 1:18009e3041ea 170 if (dataMem == NULL){
aspeteRakete 1:18009e3041ea 171 error = ALLOCFAILED;
aspeteRakete 1:18009e3041ea 172 } else {
aspeteRakete 1:18009e3041ea 173 data = dataMem;
aspeteRakete 1:18009e3041ea 174 //add data to the end of the array
aspeteRakete 1:18009e3041ea 175 data[dataCount] = d;
aspeteRakete 1:18009e3041ea 176 //increment the data size
aspeteRakete 1:18009e3041ea 177 dataCount++;
aspeteRakete 1:18009e3041ea 178 }
aspeteRakete 1:18009e3041ea 179 }
aspeteRakete 1:18009e3041ea 180 return *this;
aspeteRakete 1:18009e3041ea 181 }
aspeteRakete 1:18009e3041ea 182
aspeteRakete 1:18009e3041ea 183 //sets the data at a position
aspeteRakete 1:18009e3041ea 184 template <typename T>
aspeteRakete 1:18009e3041ea 185 void set(int position, T datum){
aspeteRakete 1:18009e3041ea 186 if (position < dataCount){
aspeteRakete 1:18009e3041ea 187 //replace the OSCData with a new one
aspeteRakete 1:18009e3041ea 188 OSCData * oldDatum = getOSCData(position);
aspeteRakete 1:18009e3041ea 189 //destroy the old one
aspeteRakete 1:18009e3041ea 190 delete oldDatum;
aspeteRakete 1:18009e3041ea 191 //make a new one
aspeteRakete 1:18009e3041ea 192 OSCData * newDatum = new OSCData(datum);
aspeteRakete 1:18009e3041ea 193 //test if there was an error
aspeteRakete 1:18009e3041ea 194 if (newDatum->error == ALLOCFAILED){
aspeteRakete 1:18009e3041ea 195 error = ALLOCFAILED;
aspeteRakete 1:18009e3041ea 196 } else {
aspeteRakete 1:18009e3041ea 197 //otherwise, put it in the data array
aspeteRakete 1:18009e3041ea 198 data[position] = newDatum;
aspeteRakete 1:18009e3041ea 199 }
aspeteRakete 1:18009e3041ea 200 } else if (position == (dataCount)){
aspeteRakete 1:18009e3041ea 201 //add the data to the end
aspeteRakete 1:18009e3041ea 202 add(datum);
aspeteRakete 1:18009e3041ea 203 } else {
aspeteRakete 1:18009e3041ea 204 //else out of bounds error
aspeteRakete 1:18009e3041ea 205 error = INDEX_OUT_OF_BOUNDS;
aspeteRakete 1:18009e3041ea 206 }
aspeteRakete 1:18009e3041ea 207 }
aspeteRakete 1:18009e3041ea 208
aspeteRakete 1:18009e3041ea 209 //blob specific setter
aspeteRakete 1:18009e3041ea 210 void set(int position, uint8_t * blob, int length){
aspeteRakete 1:18009e3041ea 211 if (position < dataCount){
aspeteRakete 1:18009e3041ea 212 //replace the OSCData with a new one
aspeteRakete 1:18009e3041ea 213 OSCData * oldDatum = getOSCData(position);
aspeteRakete 1:18009e3041ea 214 //destroy the old one
aspeteRakete 1:18009e3041ea 215 delete oldDatum;
aspeteRakete 1:18009e3041ea 216 //make a new one
aspeteRakete 1:18009e3041ea 217 OSCData * newDatum = new OSCData(blob, length);
aspeteRakete 1:18009e3041ea 218 //test if there was an error
aspeteRakete 1:18009e3041ea 219 if (newDatum->error == ALLOCFAILED){
aspeteRakete 1:18009e3041ea 220 error = ALLOCFAILED;
aspeteRakete 1:18009e3041ea 221 } else {
aspeteRakete 1:18009e3041ea 222 //otherwise, put it in the data array
aspeteRakete 1:18009e3041ea 223 data[position] = newDatum;
aspeteRakete 1:18009e3041ea 224 }
aspeteRakete 1:18009e3041ea 225 } else if (position == (dataCount)){
aspeteRakete 1:18009e3041ea 226 //add the data to the end
aspeteRakete 1:18009e3041ea 227 add(blob, length);
aspeteRakete 1:18009e3041ea 228 } else {
aspeteRakete 1:18009e3041ea 229 //else out of bounds error
aspeteRakete 1:18009e3041ea 230 error = INDEX_OUT_OF_BOUNDS;
aspeteRakete 1:18009e3041ea 231 }
aspeteRakete 1:18009e3041ea 232 }
aspeteRakete 1:18009e3041ea 233
aspeteRakete 1:18009e3041ea 234 void setAddress(const char *);
aspeteRakete 1:18009e3041ea 235
aspeteRakete 1:18009e3041ea 236 /*=============================================================================
aspeteRakete 1:18009e3041ea 237 GETTING DATA
aspeteRakete 1:18009e3041ea 238
aspeteRakete 1:18009e3041ea 239 getters take a position as an argument
aspeteRakete 1:18009e3041ea 240 =============================================================================*/
aspeteRakete 1:18009e3041ea 241
aspeteRakete 1:18009e3041ea 242 int32_t getInt(int);
aspeteRakete 1:18009e3041ea 243 uint64_t getTime(int);
aspeteRakete 1:18009e3041ea 244
aspeteRakete 1:18009e3041ea 245 float getFloat(int);
aspeteRakete 1:18009e3041ea 246 double getDouble(int);
aspeteRakete 1:18009e3041ea 247 bool getBoolean(int);
aspeteRakete 1:18009e3041ea 248
aspeteRakete 1:18009e3041ea 249 //return the copied string's length
aspeteRakete 1:18009e3041ea 250 int getString(int, char *, int);
aspeteRakete 1:18009e3041ea 251 //returns the number of unsigned int8's copied into the buffer
aspeteRakete 1:18009e3041ea 252 int getBlob(int, uint8_t *, int);
aspeteRakete 1:18009e3041ea 253
aspeteRakete 1:18009e3041ea 254 //returns the number of bytes of the data at that position
aspeteRakete 1:18009e3041ea 255 int getDataLength(int);
aspeteRakete 1:18009e3041ea 256
aspeteRakete 1:18009e3041ea 257 //returns the type at the position
aspeteRakete 1:18009e3041ea 258 char getType(int);
aspeteRakete 1:18009e3041ea 259
aspeteRakete 1:18009e3041ea 260 //put the address in the buffer
aspeteRakete 1:18009e3041ea 261 int getAddress(char * buffer, int offset = 0);
aspeteRakete 1:18009e3041ea 262 int getAddress(char * buffer, int offset, int len);
aspeteRakete 1:18009e3041ea 263
aspeteRakete 1:18009e3041ea 264 // TODO: int getAddressLength(int offset = 0);
aspeteRakete 1:18009e3041ea 265
aspeteRakete 1:18009e3041ea 266
aspeteRakete 1:18009e3041ea 267 /*=============================================================================
aspeteRakete 1:18009e3041ea 268 TESTING DATA
aspeteRakete 1:18009e3041ea 269
aspeteRakete 1:18009e3041ea 270 testers take a position as an argument
aspeteRakete 1:18009e3041ea 271 =============================================================================*/
aspeteRakete 1:18009e3041ea 272
aspeteRakete 1:18009e3041ea 273 bool isInt(int);
aspeteRakete 1:18009e3041ea 274 bool isFloat(int);
aspeteRakete 1:18009e3041ea 275 bool isBlob(int);
aspeteRakete 1:18009e3041ea 276 bool isChar(int);
aspeteRakete 1:18009e3041ea 277 bool isString(int);
aspeteRakete 1:18009e3041ea 278 bool isDouble(int);
aspeteRakete 1:18009e3041ea 279 bool isBoolean(int);
aspeteRakete 1:18009e3041ea 280 bool isTime(int);
aspeteRakete 1:18009e3041ea 281
aspeteRakete 1:18009e3041ea 282 /*=============================================================================
aspeteRakete 1:18009e3041ea 283 PATTERN MATCHING
aspeteRakete 1:18009e3041ea 284 =============================================================================*/
aspeteRakete 1:18009e3041ea 285
aspeteRakete 1:18009e3041ea 286 //match the pattern against the address
aspeteRakete 1:18009e3041ea 287 //returns true only for a complete match
aspeteRakete 1:18009e3041ea 288 bool fullMatch( const char * pattern, int = 0);
aspeteRakete 1:18009e3041ea 289
aspeteRakete 1:18009e3041ea 290 //returns the number of characters matched in the address
aspeteRakete 1:18009e3041ea 291 int match( const char * pattern, int = 0);
aspeteRakete 1:18009e3041ea 292
aspeteRakete 1:18009e3041ea 293 //calls the function with the message as the arg if it was a full match
aspeteRakete 1:18009e3041ea 294 bool dispatch(const char * pattern, void (*callback)(OSCMessage &), int = 0);
aspeteRakete 1:18009e3041ea 295
aspeteRakete 1:18009e3041ea 296 //like dispatch, but allows for partial matches
aspeteRakete 1:18009e3041ea 297 //the address match offset is sent as an argument to the callback
aspeteRakete 1:18009e3041ea 298 //also room for an option address offset to allow for multiple nested routes
aspeteRakete 1:18009e3041ea 299 bool route(const char * pattern, void (*callback)(OSCMessage &, int), int = 0);
aspeteRakete 1:18009e3041ea 300
aspeteRakete 1:18009e3041ea 301
aspeteRakete 1:18009e3041ea 302
aspeteRakete 1:18009e3041ea 303 /*=============================================================================
aspeteRakete 1:18009e3041ea 304 SIZE
aspeteRakete 1:18009e3041ea 305 =============================================================================*/
aspeteRakete 1:18009e3041ea 306
aspeteRakete 1:18009e3041ea 307 //the number of data that the message contains
aspeteRakete 1:18009e3041ea 308 int size();
aspeteRakete 1:18009e3041ea 309
aspeteRakete 1:18009e3041ea 310 //computes the number of bytes the OSCMessage occupies if everything is 32-bit aligned
aspeteRakete 1:18009e3041ea 311 int bytes();
aspeteRakete 1:18009e3041ea 312
aspeteRakete 1:18009e3041ea 313 /*=============================================================================
aspeteRakete 1:18009e3041ea 314 TRANSMISSION
aspeteRakete 1:18009e3041ea 315 =============================================================================*/
aspeteRakete 1:18009e3041ea 316
aspeteRakete 1:18009e3041ea 317 //send the message
casiotone401 4:107c23eb31b6 318 int send(uint8_t *);
aspeteRakete 1:18009e3041ea 319
aspeteRakete 1:18009e3041ea 320 //fill the message from a byte stream
aspeteRakete 1:18009e3041ea 321 void fill(uint8_t);
casiotone401 4:107c23eb31b6 322 //void fill(uint8_t *, int);
aspeteRakete 1:18009e3041ea 323
aspeteRakete 1:18009e3041ea 324 /*=============================================================================
aspeteRakete 1:18009e3041ea 325 ERROR
aspeteRakete 1:18009e3041ea 326 =============================================================================*/
aspeteRakete 1:18009e3041ea 327
aspeteRakete 1:18009e3041ea 328 bool hasError();
aspeteRakete 1:18009e3041ea 329
aspeteRakete 1:18009e3041ea 330 OSCErrorCode getError();
aspeteRakete 1:18009e3041ea 331
aspeteRakete 1:18009e3041ea 332 };
aspeteRakete 1:18009e3041ea 333
casiotone401 4:107c23eb31b6 334 #endif