00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #define EMPTY 0
00040 #define ONE_MSG_ARGS 1
00041 #define NEED_COUNT 2
00042
00043 #define GET_ARGS 3
00044
00045
00046 #define DONE 4
00047
00048
00049
00050 #include "OSC-client.h"
00051
00052
00053
00054 #include "progmem.h"
00055 #include "debug.h"
00056 #define printf debug
00057
00058
00059 char *OSC_errorMessage;
00060
00061 static int OSC_padString(char *dest, char PROGMEM *str);
00062 static int OSC_WritePadding(char *dest, int i);
00063 static int CheckTypeTag(OSCbuf *buf, char expectedType);
00064
00065 void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
00066 buf->buffer = byteArray;
00067 buf->size = size;
00068 OSC_resetBuffer(buf);
00069 }
00070
00071 void OSC_resetBuffer(OSCbuf *buf) {
00072 buf->bufptr = buf->buffer;
00073 buf->state = EMPTY;
00074 buf->bundleDepth = 0;
00075 buf->prevCounts[0] = 0;
00076 buf->gettingFirstUntypedArg = 0;
00077 buf->typeStringPtr = 0;
00078 }
00079
00080 int OSC_isBufferEmpty(OSCbuf *buf) {
00081 return buf->bufptr == buf->buffer;
00082 }
00083
00084 int OSC_freeSpaceInBuffer(OSCbuf *buf) {
00085 return buf->size - (buf->bufptr - buf->buffer);
00086 }
00087
00088 int OSC_isBufferDone(OSCbuf *buf) {
00089 return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
00090 }
00091
00092 char *OSC_getPacket(OSCbuf *buf) {
00093 #ifdef ERROR_CHECK_GETPACKET
00094 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
00095 return buf->buffer;
00096 } else {
00097 OSC_errorMessage = "Packet has unterminated bundles";
00098 return 0;
00099 }
00100 #else
00101 return buf->buffer;
00102 #endif
00103 }
00104
00105 int OSC_packetSize(OSCbuf *buf) {
00106 #ifdef ERROR_CHECK_PACKETSIZE
00107 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
00108 return (buf->bufptr - buf->buffer);
00109 } else {
00110 OSC_errorMessage = "Packet has unterminated bundles";
00111 return 0;
00112 }
00113 #else
00114 return (buf->bufptr - buf->buffer);
00115 #endif
00116 }
00117
00118 #define CheckOverflow(buf, bytesNeeded) { \
00119 if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
00120 OSC_errorMessage = "buffer overflow"; \
00121 return 1; \
00122 } \
00123 }
00124
00125 static void PatchMessageSize(OSCbuf *buf) {
00126 int4byte size;
00127 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
00128 *(buf->thisMsgSize) = htonl(size);
00129 }
00130
00131 int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
00132 if (buf->state == ONE_MSG_ARGS) {
00133 OSC_errorMessage = "Can't open a bundle in a one-message packet";
00134 return 3;
00135 }
00136
00137 if (buf->state == DONE) {
00138 OSC_errorMessage = "This packet is finished; can't open a new bundle";
00139 return 4;
00140 }
00141
00142 if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
00143 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
00144 return 2;
00145 }
00146
00147 if (CheckTypeTag(buf, '\0')) return 9;
00148
00149 if (buf->state == GET_ARGS) {
00150 PatchMessageSize(buf);
00151 }
00152
00153 if (buf->state == EMPTY) {
00154
00155 CheckOverflow(buf, 16);
00156 } else {
00157
00158
00159 CheckOverflow(buf, 20);
00160 *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
00161 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
00162
00163 buf->bufptr += 4;
00164 }
00165
00166 buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
00167
00168
00169 *((OSCTimeTag *) buf->bufptr) = tt;
00170
00171 if (htonl(1L) != 1L) {
00172
00173 int4byte *intp = (int4byte *)buf->bufptr;
00174 intp[0] = htonl(intp[0]);
00175 intp[1] = htonl(intp[1]);
00176
00177 #ifdef HAS8BYTEINT
00178 {
00179
00180
00181
00182 int4byte temp = intp[0];
00183 intp[0] = intp[1];
00184 intp[1] = temp;
00185 }
00186 #endif
00187 }
00188
00189 buf->bufptr += sizeof(OSCTimeTag);
00190
00191 buf->state = NEED_COUNT;
00192
00193 buf->gettingFirstUntypedArg = 0;
00194 buf->typeStringPtr = 0;
00195 return 0;
00196 }
00197
00198
00199 int OSC_closeBundle(OSCbuf *buf) {
00200 if (buf->bundleDepth == 0) {
00201
00202 OSC_errorMessage = "Can't close bundle; no bundle is open!";
00203 return 5;
00204 }
00205
00206 if (CheckTypeTag(buf, '\0')) return 9;
00207
00208 if (buf->state == GET_ARGS) {
00209 PatchMessageSize(buf);
00210 }
00211
00212 if (buf->bundleDepth == 1) {
00213
00214 buf->state = DONE;
00215 } else {
00216
00217 int4byte size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
00218 *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
00219 buf->state = NEED_COUNT;
00220 }
00221
00222 --buf->bundleDepth;
00223 buf->gettingFirstUntypedArg = 0;
00224 buf->typeStringPtr = 0;
00225 return 0;
00226 }
00227
00228
00229 int OSC_closeAllBundles(OSCbuf *buf) {
00230 if (buf->bundleDepth == 0) {
00231
00232 OSC_errorMessage = "Can't close all bundles; no bundle is open!";
00233 return 6;
00234 }
00235
00236 if (CheckTypeTag(buf, '\0')) return 9;
00237
00238 while (buf->bundleDepth > 0) {
00239 OSC_closeBundle(buf);
00240 }
00241 buf->typeStringPtr = 0;
00242 return 0;
00243 }
00244
00245 int OSC_writeAddress(OSCbuf *buf, char PROGMEM *name) {
00246 int4byte paddedLength;
00247
00248 if (buf->state == ONE_MSG_ARGS) {
00249 debug(PSTR("This packet is not a bundle, so you can't write another address"));
00250 return 7;
00251 }
00252
00253 if (buf->state == DONE) {
00254 debug(PSTR("This packet is finished; can't write another address"));
00255 return 8;
00256 }
00257
00258 if (CheckTypeTag(buf, '\0')) return 9;
00259
00260 paddedLength = OSC_effectiveStringLength(name);
00261
00262 if (buf->state == EMPTY) {
00263
00264 CheckOverflow(buf, paddedLength);
00265 buf->state = ONE_MSG_ARGS;
00266 } else {
00267
00268 CheckOverflow(buf, 4+paddedLength);
00269 if (buf->state == GET_ARGS) {
00270
00271 PatchMessageSize(buf);
00272 }
00273 buf->thisMsgSize = (int4byte *)buf->bufptr;
00274 *(buf->thisMsgSize) = 0xbbbbbbbb;
00275 buf->bufptr += 4;
00276 buf->state = GET_ARGS;
00277 }
00278
00279
00280 buf->bufptr += OSC_padString(buf->bufptr, name);
00281 buf->typeStringPtr = 0;
00282 buf->gettingFirstUntypedArg = 1;
00283
00284 return 0;
00285 }
00286
00287 int OSC_writeAddressAndTypes(OSCbuf *buf, char PROGMEM *name, char PROGMEM *types) {
00288 int result;
00289 int4byte paddedLength;
00290
00291 if (CheckTypeTag(buf, '\0')) return 9;
00292
00293 result = OSC_writeAddress(buf, name);
00294
00295 if (result) return result;
00296
00297 paddedLength = OSC_effectiveStringLength(types);
00298
00299 CheckOverflow(buf, paddedLength);
00300
00301 buf->typeStringPtr = buf->bufptr + 1;
00302 buf->bufptr += OSC_padString(buf->bufptr, types);
00303
00304 buf->gettingFirstUntypedArg = 0;
00305 return 0;
00306 }
00307
00308 static int CheckTypeTag(OSCbuf *buf, char expectedType) {
00309 if (buf->typeStringPtr) {
00310 if (*(buf->typeStringPtr) != expectedType) {
00311 if (expectedType == '\0') {
00312 OSC_errorMessage =
00313 "According to the type tag I expected more arguments.";
00314 } else if (*(buf->typeStringPtr) == '\0') {
00315 OSC_errorMessage =
00316 "According to the type tag I didn't expect any more arguments.";
00317 } else {
00318 OSC_errorMessage =
00319 "According to the type tag I expected an argument of a different type.";
00320
00321 }
00322 return 9;
00323 }
00324 ++(buf->typeStringPtr);
00325 }
00326 return 0;
00327 }
00328
00329
00330 int OSC_writeFloatArg(OSCbuf *buf, float arg) {
00331 int4byte *intp;
00332
00333 CheckOverflow(buf, 4);
00334
00335 if (CheckTypeTag(buf, 'f')) return 9;
00336
00337
00338 intp = ((int4byte *) &arg);
00339 *((int4byte *) buf->bufptr) = htonl(*intp);
00340
00341 buf->bufptr += 4;
00342
00343 buf->gettingFirstUntypedArg = 0;
00344 return 0;
00345 }
00346
00347
00348
00349 int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
00350 int i;
00351 int4byte *intp;
00352
00353 CheckOverflow(buf, 4 * numFloats);
00354
00355
00356 intp = ((int4byte *) args);
00357
00358 for (i = 0; i < numFloats; i++) {
00359 if (CheckTypeTag(buf, 'f')) return 9;
00360 *((int4byte *) buf->bufptr) = htonl(intp[i]);
00361 buf->bufptr += 4;
00362 }
00363
00364 buf->gettingFirstUntypedArg = 0;
00365 return 0;
00366 }
00367
00368 int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
00369 CheckOverflow(buf, 4);
00370 if (CheckTypeTag(buf, 'i')) return 9;
00371
00372 *((int4byte *) buf->bufptr) = htonl(arg);
00373 buf->bufptr += 4;
00374
00375 buf->gettingFirstUntypedArg = 0;
00376 return 0;
00377 }
00378
00379 int OSC_writeStringArg(OSCbuf *buf, char PROGMEM *arg) {
00380 int len;
00381
00382 if (CheckTypeTag(buf, 's')) return 9;
00383
00384 len = OSC_effectiveStringLength(arg);
00385
00386 CheckOverflow(buf, len);
00387 buf->bufptr += OSC_padString(buf->bufptr, arg);
00388
00389 buf->gettingFirstUntypedArg = 0;
00390 return 0;
00391
00392 }
00393
00394 #define STRING_ALIGN_PAD 4
00395 int OSC_effectiveStringLength(char PROGMEM *string) {
00396 int len = strlen_P(string) + 1;
00397
00398
00399 if ((len % STRING_ALIGN_PAD) != 0) {
00400 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
00401 }
00402 return len;
00403 }
00404
00405 static int OSC_padString(char *dest, char PROGMEM *str) {
00406 int i;
00407 char c;
00408
00409 for (i = 0; (c = PRG_RDB(str+i)) != '\0'; i++) {
00410 dest[i] = c;
00411 }
00412
00413 return OSC_WritePadding(dest, i);
00414 }
00415
00416 static int OSC_WritePadding(char *dest, int i) {
00417 dest[i] = '\0';
00418 i++;
00419
00420 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
00421 dest[i] = '\0';
00422 }
00423
00424 return i;
00425 }