*** empty log message ***
[chuck-blob.git] / v2 / util_opsc.cpp
blobbf78a4b06fc6894300bf757377e9a4e967f3f673
1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: util_opsc.cpp
27 // desc: ...
29 // author: Philip L. Davidson (philipd@alumni.princeton.edu)
30 // Ge Wang (gewang@cs.princeton.edu)
31 // Perry R. Cook (prc@cs.princeton.edu)
32 // date: Spring 2005
33 //-----------------------------------------------------------------------------
34 #include "util_opsc.h"
36 //chuck networking code
37 #include "util_network.h"
38 #include "util_thread.h"
40 #include "chuck_errmsg.h"
41 #include "chuck_vm.h"
43 #include <algorithm>
44 using namespace std;
47 // FROM PLATFORM.H -UDP TRANSMITTER / RECEIVER
49 #if defined(__PLATFORM_WIN32__)
50 #include <windows.h>
51 #else
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <sys/time.h>
55 #include <unistd.h>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <arpa/inet.h>
59 #include <netdb.h>
60 #endif
62 #if defined(__MACOSX_CORE__)
63 #define SOCKET int
64 #define SOCKADDR_IN struct sockaddr_in
65 #elif !defined(SOCKADDR_IN)
66 #define SOCKET int
67 #define SOCKADDR_IN struct sockaddr_in
68 #endif
71 // squeeze the whole wad of OSC-Kit code in here.
73 // OSC-pattern-match.cpp
76 Copyright © 1998. The Regents of the University of California (Regents).
77 All Rights Reserved.
79 Written by Matt Wright, The Center for New Music and Audio Technologies,
80 University of California, Berkeley.
82 Permission to use, copy, modify, distribute, and distribute modified versions
83 of this software and its documentation without fee and without a signed
84 licensing agreement, is hereby granted, provided that the above copyright
85 notice, this paragraph and the following two paragraphs appear in all copies,
86 modifications, and distributions.
88 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
89 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
90 OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
91 BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
93 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
94 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
96 HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
97 MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
99 The OpenSound Control WWW page is
100 http://www.cnmat.berkeley.edu/OpenSoundControl
106 OSC-pattern-match.c
107 Matt Wright, 3/16/98
108 Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury
111 // #include "OSC-pattern-match.h"
113 static const char *theWholePattern; /* Just for warning messages */
115 static bool MatchBrackets( const char * pattern, const char * test );
116 static bool MatchList( const char * pattern, const char * test );
118 bool PatternMatch( const char * pattern, const char * test )
120 theWholePattern = pattern;
122 if( pattern == 0 || pattern[0] == 0 ) {
123 return test[0] == 0;
126 if( test[0] == 0 ) {
127 if(pattern[0] == '*')
128 return PatternMatch (pattern+1,test);
129 else
130 return FALSE;
133 switch( pattern[0] )
135 case 0 : return test[0] == 0;
136 case '?' : return PatternMatch (pattern + 1, test + 1);
137 case '*' :
138 if( PatternMatch (pattern+1, test) ) {
139 return TRUE;
140 } else {
141 return PatternMatch (pattern, test+1);
143 case ']' :
144 case '}' :
145 fprintf( stderr, "[chuck](via OSC): spurious %c in pattern \".../%s/...\"\n", pattern[0], theWholePattern );
146 return FALSE;
147 case '[' :
148 return MatchBrackets (pattern,test);
149 case '{' :
150 return MatchList (pattern,test);
151 case '\\' :
152 if(pattern[1] == 0) {
153 return test[0] == 0;
154 } else if(pattern[1] == test[0]) {
155 return PatternMatch (pattern+2,test+1);
156 } else {
157 return FALSE;
159 default :
160 if(pattern[0] == test[0]) {
161 return PatternMatch (pattern+1,test+1);
162 } else {
163 return FALSE;
169 /* we know that pattern[0] == '[' and test[0] != 0 */
171 static bool MatchBrackets( const char * pattern, const char * test )
173 bool result;
174 bool negated = FALSE;
175 const char *p = pattern;
177 if(pattern[1] == 0) {
178 fprintf( stderr, "[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern );
179 return FALSE;
182 if(pattern[1] == '!') {
183 negated = TRUE;
184 p++;
187 while (*p != ']') {
188 if(*p == 0) {
189 fprintf( stderr,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern );
190 return FALSE;
193 if(p[1] == '-' && p[2] != 0) {
194 if(test[0] >= p[0] && test[0] <= p[2]) {
195 result = !negated;
196 goto advance;
200 if(p[0] == test[0]) {
201 result = !negated;
202 goto advance;
204 p++;
207 result = negated;
209 advance:
211 if(!result)
212 return FALSE;
214 while (*p != ']') {
215 if(*p == 0) {
216 fprintf( stderr,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern );
217 return FALSE;
219 p++;
222 return PatternMatch (p+1,test+1);
226 static bool MatchList( const char * pattern, const char * test )
228 const char *restOfPattern, *tp = test;
230 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
231 if(*restOfPattern == 0) {
232 fprintf( stderr,"[chuck](via OSC): unterminated { in pattern \".../%s/...\"\n", theWholePattern );
233 return FALSE;
237 restOfPattern++; /* skip close curly brace */
239 pattern++; /* skip open curly brace */
241 while( 1 )
243 if(*pattern == ',') {
244 if(PatternMatch (restOfPattern, tp)) {
245 return TRUE;
246 } else {
247 tp = test;
248 ++pattern;
250 } else if(*pattern == '}') {
251 return PatternMatch (restOfPattern, tp);
252 } else if(*pattern == *tp) {
253 ++pattern;
254 ++tp;
255 } else {
256 tp = test;
257 while (*pattern != ',' && *pattern != '}') {
258 pattern++;
260 if(*pattern == ',') {
261 pattern++;
267 // end OSC-pattern-match.h
270 // OSC-timetag.cpp
273 Copyright (c) 1998. The Regents of the University of California (Regents).
274 All Rights Reserved.
276 Permission to use, copy, modify, and distribute this software and its
277 documentation for educational, research, and not-for-profit purposes, without
278 fee and without a signed licensing agreement, is hereby granted, provided that
279 the above copyright notice, this paragraph and the following two paragraphs
280 appear in all copies, modifications, and distributions. Contact The Office of
281 Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
282 CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
284 Written by Matt Wright, The Center for New Music and Audio Technologies,
285 University of California, Berkeley.
287 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
288 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
289 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
290 REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
293 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
294 FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
295 DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
296 REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
297 ENHANCEMENTS, OR MODIFICATIONS.
299 The OpenSound Control WWW page is
300 http://www.cnmat.berkeley.edu/OpenSoundControl
304 OSC_timeTag.c: library for manipulating OSC time tags
305 Matt Wright, 5/29/97
307 Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
310 //#include "OSC-timetag.h"
313 #ifdef HAS8BYTEINT
314 #define TWO_TO_THE_32_FLOAT 4294967296.0f
316 OSCTimeTag OSCTT_Immediately(void) {
317 return (OSCTimeTag) 1;
320 OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
321 return (OSCTimeTag) 0xffffffffffffffff;
324 OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
325 int64 offset = (int64) (secondsOffset * TWO_TO_THE_32_FLOAT);
327 /* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original,
328 secondsOffset, offset, original + offset); */
330 return original + offset;
333 int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right)
335 #if 0
336 printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right,
337 (left<right) ? -1 : ((left == right) ? 0 : 1));
338 #endif
339 if(left < right) {
340 return -1;
341 } else if(left == right) {
342 return 0;
343 } else {
344 return 1;
348 #ifdef __sgi
349 #include <sys/time.h>
351 #define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */
352 #define TWO_TO_THE_32_OVER_ONE_MILLION 4295
355 OSCTimeTag OSCTT_CurrentTime(void) {
356 uint64 result;
357 uint32 usecOffset;
358 struct timeval tv;
359 struct timezone tz;
361 BSDgettimeofday(&tv, &tz);
363 /* First get the seconds right */
364 result = (unsigned) SECONDS_FROM_1900_to_1970 +
365 (unsigned) tv.tv_sec -
366 (unsigned) 60 * tz.tz_minuteswest +
367 (unsigned) (tz.tz_dsttime ? 3600 : 0);
369 #if 0
370 /* No timezone, no DST version ... */
371 result = (unsigned) SECONDS_FROM_1900_to_1970 +
372 (unsigned) tv.tv_sec;
373 #endif
376 /* make seconds the high-order 32 bits */
377 result = result << 32;
379 /* Now get the fractional part. */
380 usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION;
381 /* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */
383 result += usecOffset;
385 /* printf("* OSCTT_CurrentTime is %llx\n", result); */
386 return result;
389 #else /* __sgi */
391 /* Instead of asking your operating system what time it is, it might be
392 clever to find out the current time at the instant your application
393 starts audio processing, and then keep track of the number of samples
394 output to know how much time has passed. */
396 /* Loser version for systems that have no ability to tell the current time: */
397 OSCTimeTag OSCTT_CurrentTime(void) {
398 return (OSCTimeTag) 1;
401 #endif /* __sgi */
404 #else /* Not HAS8BYTEINT */
406 OSCTimeTag OSCTT_CurrentTime(void) {
407 OSCTimeTag result;
408 result.seconds = 0;
409 result.fraction = 1;
410 return result;
413 OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
414 OSCTimeTag result;
415 result.seconds = 0xffffffff;
416 result.fraction = 0xffffffff;
417 return result;
420 OSCTimeTag OSCTT_Immediately(void) {
421 OSCTimeTag result;
422 result.seconds = 0;
423 result.fraction = 1;
424 return result;
427 OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
428 OSCTimeTag result;
429 result.seconds = 0;
430 result.fraction = 1;
431 return result;
434 int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
435 /* Untested! */
436 int highResult = left.seconds - right.seconds;
438 if(highResult != 0) return highResult;
440 return left.fraction - right.fraction;
444 #endif /* HAS8BYTEINT */
446 // end OSC-timetag.cpp
448 // OSC-client.cpp
451 Copyright (c) 1996. The Regents of the University of California (Regents).
452 All Rights Reserved.
454 Permission to use, copy, modify, and distribute this software and its
455 documentation for educational, research, and not-for-profit purposes, without
456 fee and without a signed licensing agreement, is hereby granted, provided that
457 the above copyright notice, this paragraph and the following two paragraphs
458 appear in all copies, modifications, and distributions. Contact The Office of
459 Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
460 CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
462 Written by Matt Wright, The Center for New Music and Audio Technologies,
463 University of California, Berkeley.
465 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
466 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
467 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
468 REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
470 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
471 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
472 FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
473 DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
474 REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
475 ENHANCEMENTS, OR MODIFICATIONS.
480 Author: Matt Wright
481 Version 2.2: Calls htonl in the right places 20000620
482 Version 2.3: Gets typed messages right.
486 /* Here are the possible values of the state field: */
488 #define EMPTY 0 /* Nothing written to packet yet */
489 #define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
490 #define NEED_COUNT 2 /* Just opened a bundle; must write message name or
491 open another bundle */
492 #define GET_ARGS 3 /* Getting arguments to a message. If we see a message
493 name or a bundle open/close then the current message
494 will end. */
495 #define DONE 4 /* All open bundles have been closed, so can't write
496 anything else */
499 //#include "OSC-client.h"
501 const char * OSC_errorMessage;
504 //static int strlen(char *s);
505 static int OSC_padString(char *dest, const char *str);
506 static int OSC_padStringWithAnExtraStupidComma(char *dest, const char *str);
507 static int OSC_WritePadding(char *dest, int i);
508 static int CheckTypeTag(OSCbuf *buf, char expectedType);
510 void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
511 buf->buffer = byteArray;
512 buf->size = size;
513 OSC_resetBuffer(buf);
516 void OSC_resetBuffer(OSCbuf *buf) {
517 buf->bufptr = buf->buffer;
518 buf->state = EMPTY;
519 buf->bundleDepth = 0;
520 buf->prevCounts[0] = 0;
521 buf->gettingFirstUntypedArg = 0;
522 buf->typeStringPtr = 0;
525 int OSC_isBufferEmpty(OSCbuf *buf) {
526 return buf->bufptr == buf->buffer;
529 int OSC_freeSpaceInBuffer(OSCbuf *buf) {
530 return buf->size - (buf->bufptr - buf->buffer);
533 int OSC_isBufferDone(OSCbuf *buf) {
534 return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
537 char *OSC_getPacket(OSCbuf *buf)
539 #ifdef ERROR_CHECK_GETPACKET
540 if(buf->state == DONE || buf->state == ONE_MSG_ARGS) {
541 return buf->buffer;
542 } else {
543 OSC_errorMessage = "Packet has unterminated bundles";
544 return 0;
546 #else
547 return buf->buffer;
548 #endif
551 int OSC_packetSize(OSCbuf *buf)
553 #ifdef ERROR_CHECK_PACKETSIZE
554 if(buf->state == DONE || buf->state == ONE_MSG_ARGS) {
555 return (buf->bufptr - buf->buffer);
556 } else {
557 OSC_errorMessage = "Packet has unterminated bundles";
558 return 0;
560 #else
561 return (buf->bufptr - buf->buffer);
562 #endif
565 #define CheckOverflow(buf, bytesNeeded) { \
566 if((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
567 OSC_errorMessage = "buffer overflow"; \
568 return 1; \
572 static void PatchMessageSize(OSCbuf *buf)
574 int4byte size;
575 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
576 *(buf->thisMsgSize) = htonl(size);
579 int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt)
581 if(buf->state == ONE_MSG_ARGS) {
582 OSC_errorMessage = "Can't open a bundle in a one-message packet";
583 return 3;
586 if(buf->state == DONE) {
587 OSC_errorMessage = "This packet is finished; can't open a new bundle";
588 return 4;
591 if(++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
592 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
593 return 2;
596 if(CheckTypeTag(buf, '\0')) return 9;
598 if(buf->state == GET_ARGS) {
599 PatchMessageSize(buf);
602 if(buf->state == EMPTY) {
603 /* Need 16 bytes for "#bundle" and time tag */
604 CheckOverflow(buf, 16);
605 } else {
606 /* This bundle is inside another bundle, so we need to leave
607 a blank size count for the size of this current bundle. */
608 CheckOverflow(buf, 20);
609 *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
610 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
612 buf->bufptr += 4;
615 buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
617 *((OSCTimeTag *) buf->bufptr) = tt;
619 if(htonl(1) != 1)
621 /* Byte swap the 8-byte integer time tag */
622 int4byte *intp = (int4byte *)buf->bufptr;
623 intp[0] = htonl(intp[0]);
624 intp[1] = htonl(intp[1]);
626 #ifdef HAS8BYTEINT
627 { /* tt is a 64-bit int so we have to swap the two 32-bit words.
628 (Otherwise tt is a struct of two 32-bit words, and even though
629 each word was wrong-endian, they were in the right order
630 in the struct.) */
631 int4byte temp = intp[0];
632 intp[0] = intp[1];
633 intp[1] = temp;
635 #endif
638 buf->bufptr += sizeof(OSCTimeTag);
640 buf->state = NEED_COUNT;
642 buf->gettingFirstUntypedArg = 0;
643 buf->typeStringPtr = 0;
644 return 0;
647 int OSC_closeBundle(OSCbuf *buf)
649 if(buf->bundleDepth == 0) {
650 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
651 OSC_errorMessage = "Can't close bundle; no bundle is open!";
652 return 5;
655 if(CheckTypeTag(buf, '\0')) return 9;
657 if(buf->state == GET_ARGS) {
658 PatchMessageSize(buf);
661 if(buf->bundleDepth == 1) {
662 /* Closing the last bundle: No bundle size to patch */
663 buf->state = DONE;
664 } else {
665 /* Closing a sub-bundle: patch bundle size */
666 int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
667 *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
668 buf->state = NEED_COUNT;
671 --buf->bundleDepth;
672 buf->gettingFirstUntypedArg = 0;
673 buf->typeStringPtr = 0;
674 return 0;
678 int OSC_closeAllBundles(OSCbuf *buf)
680 if(buf->bundleDepth == 0) {
681 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
682 OSC_errorMessage = "Can't close all bundles; no bundle is open!";
683 return 6;
686 if(CheckTypeTag(buf, '\0')) return 9;
688 while (buf->bundleDepth > 0) {
689 OSC_closeBundle(buf);
692 buf->typeStringPtr = 0;
693 return 0;
696 int OSC_writeAddress(OSCbuf *buf, char *name)
698 int4byte paddedLength;
700 if(buf->state == ONE_MSG_ARGS) {
701 OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
702 return 7;
705 if(buf->state == DONE) {
706 OSC_errorMessage = "This packet is finished; can't write another address";
707 return 8;
710 if(CheckTypeTag(buf, '\0')) return 9;
712 paddedLength = OSC_effectiveStringLength(name);
714 if(buf->state == EMPTY) {
715 /* This will be a one-message packet, so no sizes to worry about */
716 CheckOverflow(buf, paddedLength);
717 buf->state = ONE_MSG_ARGS;
718 } else {
719 /* GET_ARGS or NEED_COUNT */
720 CheckOverflow(buf, 4+paddedLength);
721 if(buf->state == GET_ARGS) {
722 /* Close the old message */
723 PatchMessageSize(buf);
725 buf->thisMsgSize = (int4byte *)buf->bufptr;
726 *(buf->thisMsgSize) = 0xbbbbbbbb;
727 buf->bufptr += 4;
728 buf->state = GET_ARGS;
731 /* Now write the name */
732 buf->bufptr += OSC_padString(buf->bufptr, name);
733 buf->typeStringPtr = 0;
734 buf->gettingFirstUntypedArg = 1;
736 return 0;
739 int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types)
741 int result;
742 int4byte paddedLength;
744 if(CheckTypeTag(buf, '\0')) return 9;
746 result = OSC_writeAddress(buf, name);
748 if(result) return result;
750 paddedLength = OSC_effectiveStringLength(types);
752 CheckOverflow(buf, paddedLength);
754 buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
755 buf->bufptr += OSC_padString(buf->bufptr, types);
757 buf->gettingFirstUntypedArg = 0;
759 return 0;
762 static int CheckTypeTag(OSCbuf *buf, char expectedType)
764 if(buf->typeStringPtr) {
765 if(*(buf->typeStringPtr) != expectedType) {
766 if(expectedType == '\0') {
767 OSC_errorMessage =
768 "According to the type tag I expected more arguments.";
769 } else if(*(buf->typeStringPtr) == '\0') {
770 OSC_errorMessage =
771 "According to the type tag I didn't expect any more arguments.";
772 } else {
773 OSC_errorMessage =
774 "According to the type tag I expected an argument of a different type.";
775 printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
778 return 9;
781 ++(buf->typeStringPtr);
784 return 0;
788 int OSC_writeFloatArg(OSCbuf *buf, float arg)
790 int4byte *intp;
792 CheckOverflow(buf, 4);
794 if(CheckTypeTag(buf, 'f')) return 9;
796 /* Pretend arg is a long int so we can use htonl() */
797 intp = ((int4byte *) &arg);
798 *((int4byte *) buf->bufptr) = htonl(*intp);
800 buf->bufptr += 4;
802 buf->gettingFirstUntypedArg = 0;
804 return 0;
808 int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args)
810 int i;
811 int4byte *intp;
813 CheckOverflow(buf, 4 * numFloats);
815 /* Pretend args are long ints so we can use htonl() */
816 intp = ((int4byte *) args);
818 for(i = 0; i < numFloats; i++) {
819 if(CheckTypeTag(buf, 'f')) return 9;
820 *((int4byte *) buf->bufptr) = htonl(intp[i]);
821 buf->bufptr += 4;
824 buf->gettingFirstUntypedArg = 0;
826 return 0;
830 int OSC_writeIntArg(OSCbuf *buf, int4byte arg)
832 CheckOverflow(buf, 4);
833 if(CheckTypeTag(buf, 'i')) return 9;
835 *((int4byte *) buf->bufptr) = htonl(arg);
836 buf->bufptr += 4;
838 buf->gettingFirstUntypedArg = 0;
839 return 0;
843 int OSC_writeStringArg(OSCbuf *buf, char *arg)
845 int len;
847 if(CheckTypeTag(buf, 's')) return 9;
849 len = OSC_effectiveStringLength(arg);
851 if(buf->gettingFirstUntypedArg && arg[0] == ',') {
852 /* This un-type-tagged message starts with a string
853 that starts with a comma, so we have to escape it
854 (with a double comma) so it won't look like a type
855 tag string. */
857 CheckOverflow(buf, len+4); /* Too conservative */
858 buf->bufptr +=
859 OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
860 } else {
861 CheckOverflow(buf, len);
862 buf->bufptr += OSC_padString(buf->bufptr, arg);
865 buf->gettingFirstUntypedArg = 0;
867 return 0;
871 /* String utilities */
873 static int strlen(char *s) {
874 int i;
875 for(i=0; s[i] != '\0'; i++);
876 return i;
880 #define STRING_ALIGN_PAD 4
881 int OSC_effectiveStringLength(char *string)
883 int len = strlen(string) + 1; /* We need space for the null char. */
885 /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
886 if((len % STRING_ALIGN_PAD) != 0) {
887 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
890 return len;
894 static int OSC_padString(char *dest, const char *str)
896 int i;
898 for(i = 0; str[i] != '\0'; i++) {
899 dest[i] = str[i];
902 return OSC_WritePadding(dest, i);
906 static int OSC_padStringWithAnExtraStupidComma(char *dest, const char *str)
908 int i;
910 dest[0] = ',';
911 for(i = 0; str[i] != '\0'; i++) {
912 dest[i+1] = str[i];
915 return OSC_WritePadding(dest, i+1);
919 static int OSC_WritePadding(char *dest, int i)
921 dest[i] = '\0';
922 i++;
924 for(; (i % STRING_ALIGN_PAD) != 0; i++) {
925 dest[i] = '\0';
928 return i;
932 // end OSC-client.cpp
936 // ACTUAL CODE
939 //chuck networking code
940 #include "util_network.h"
941 #include "util_thread.h"
943 // FROM PLATFORM.H -UDP TRANSMITTER / RECEIVER
945 #if defined(__PLATFORM_WIN32__)
946 #include <winsock.h>
947 #else
948 #include <sys/types.h>
949 #include <sys/socket.h>
950 #include <sys/time.h>
951 #include <unistd.h>
952 #include <netinet/in.h>
953 #include <netinet/tcp.h>
954 #include <arpa/inet.h>
955 #include <netdb.h>
956 #endif
958 #ifdef __MACOSX_CORE__
959 #define SOCKET int
960 #define SOCKADDR_IN struct sockaddr_in
961 #endif
963 #include "stdarg.h"
965 enum udp_stat { UDP_NOINIT, UDP_UNBOUND, UDP_BOUND, UDP_READY, UDP_ERROR, UDP_NUM };
968 /* in the .h so that OSC can subclass it
970 class UDP_Subscriber {
971 virtual void onRecieve( char * mesg, int mesgLen ) = 0;
972 virtual bool subscribe( int port );
973 virtual bool unsubscribe();
974 virtual int& port(); //get/set the value of the subscriber's current port.
979 class DefUDP_Subscriber : public UDP_Subscriber {
980 public:
981 int _port;
982 void onReceive ( char * mesg, int mesgLen ) {} // ignore
983 int& port() { return _port; }
986 class UDP_Port_Listener {
987 private:
988 UDP_Receiver* m_in;
989 bool m_port;
991 XThread* m_thread;
992 XMutex* m_mutex;
994 char m_inbuf[OSCINBUFSIZE];
995 int m_inbufsize;
997 vector < UDP_Subscriber * > m_subscribers;
998 queue < UDP_Subscriber * > m_free;
1000 public:
1001 UDP_Port_Listener( int port );
1002 ~UDP_Port_Listener();
1003 void init();
1004 bool bind_to_port(int port);
1005 void close();
1006 bool listen();
1007 int recv_mesg();
1008 bool add ( UDP_Subscriber * );
1009 bool drop ( UDP_Subscriber * );
1010 int nsubs();
1012 bool listening;
1018 class UDP_Port_Manager {
1020 private:
1022 static UDP_Port_Manager* _inst;
1023 map < int, UDP_Port_Listener* > _listeners;
1025 public:
1027 static UDP_Port_Manager* instance();
1028 UDP_Port_Manager();
1029 void init();
1030 bool subscribe ( UDP_Subscriber * sub, int port );
1031 bool unsubscribe ( UDP_Subscriber * sub );
1037 class UDP_Receiver {
1039 protected:
1040 ck_socket _sock;
1041 udp_stat _status;
1043 SOCKADDR_IN _remote_addr;
1044 int _remote_addr_len;
1045 int _mesgLen;
1047 public:
1049 UDP_Receiver();
1051 ~UDP_Receiver() { }
1052 void init();
1053 bool bind_to_port(int port);
1054 int recv_next(char *buffer, int size);
1055 void close_sock();
1056 udp_stat status();
1062 class UDP_Transmitter {
1064 protected:
1066 ck_socket _sock;
1067 SOCKADDR_IN _host_addr;
1068 udp_stat _status;
1070 public:
1072 UDP_Transmitter() {
1073 _status = UDP_NOINIT;
1075 virtual ~UDP_Transmitter() {}
1076 void init();
1078 void set_host(char * hostaddress, int port);
1079 int send(char *buffer, int size);
1080 udp_stat status(void) { return _status; }
1081 void close_sock();
1085 UDP_Port_Manager * UDP_Port_Manager::_inst = NULL;
1086 UDP_Port_Manager * UDP_Port_Manager::instance() {
1087 if(_inst == NULL ) {
1088 _inst = new UDP_Port_Manager();
1089 assert ( _inst );
1091 return _inst;
1094 UDP_Port_Manager::UDP_Port_Manager() {
1095 init();
1098 void
1099 UDP_Port_Manager::init() {
1100 _listeners.clear();
1103 bool
1104 UDP_Port_Manager::subscribe ( UDP_Subscriber * sub, int port ) {
1105 if( _listeners.count( port ) == 0 ) {
1106 EM_log(CK_LOG_INFO, "PortManager: starting Listener on %d", port );
1107 _listeners[port] = new UDP_Port_Listener( port ); //make a new listener on this port
1109 return _listeners[port]->add( sub );
1112 bool
1113 UDP_Port_Manager::unsubscribe( UDP_Subscriber * sub ) {
1114 if( sub->port() < 0 ) {
1115 EM_log( CK_LOG_INFO, "error, subscriber's port < 0, return false" );
1116 return false;
1118 if( _listeners.count( sub->port() ) == 0 ) {
1119 EM_log( CK_LOG_INFO, "error, cannot unsubscribe: port %d not in use", sub->port() );
1120 return false;
1122 else {
1123 int pp = sub->port();
1124 UDP_Port_Listener* listener = _listeners[pp];
1125 bool ret = listener->drop( sub );
1126 //check empty
1127 if( listener->nsubs() == 0 ) {
1128 EM_log( CK_LOG_INFO, "PortManager: Listener on port %d is empty - removing", sub->port() );
1129 delete listener;
1130 _listeners.erase( pp );
1132 return ret;
1137 UDP_Port_Listener::UDP_Port_Listener( int port ) :
1138 m_inbufsize( OSCINBUFSIZE ),
1139 listening( false )
1141 init();
1142 m_in->bind_to_port( port );
1143 listen();
1146 UDP_Port_Listener::~UDP_Port_Listener() {
1147 //fprintf(stderr , "port listener destructor\n");
1148 close();
1149 // usleep( 10 ); // do we need this ?
1150 delete m_in;
1151 delete m_mutex;
1152 delete m_thread;
1155 void
1156 UDP_Port_Listener::init() {
1157 memset( (void*)m_inbuf, '\0', m_inbufsize * sizeof(char) );
1158 m_thread = new XThread();
1159 m_mutex = new XMutex();
1160 m_in = new UDP_Receiver();
1161 m_in->init();
1165 UDP_Port_Listener::nsubs() { return m_subscribers.size(); }
1167 bool
1168 UDP_Port_Listener::add( UDP_Subscriber * sub ) {
1169 m_mutex->acquire();
1170 if( find( m_subscribers.begin(), m_subscribers.end(), sub ) == m_subscribers.end() ) {
1171 EM_log(CK_LOG_INFO, "UDP_Port_Listener: adding subscriber" );
1172 m_subscribers.push_back( sub );
1173 sub->port() = m_port;
1174 m_mutex->release();
1175 return true;
1177 else {
1178 EM_log(CK_LOG_INFO, "UDP_Port_Listener::add - error subscriber already exists" );
1179 m_mutex->release();
1180 return false;
1185 bool
1186 UDP_Port_Listener::drop( UDP_Subscriber * sub ) {
1188 m_mutex->acquire();
1189 vector < UDP_Subscriber * >::iterator m_iter = find ( m_subscribers.begin(), m_subscribers.end(), sub );
1190 if( m_iter != m_subscribers.end() ) {
1191 EM_log(CK_LOG_INFO, "UDP_Port_Listener: dropping subscriber" );
1192 m_subscribers.erase( m_iter );
1193 sub->port() = -1;
1194 m_mutex->release();
1195 return true;
1197 else {
1198 EM_log(CK_LOG_INFO, "UDP_Port_Listener::add - error subscriber already exists" );
1199 m_mutex->release();
1200 return false;
1205 THREAD_RETURN ( THREAD_TYPE udp_port_listener_thread ) ( void * data )
1207 UDP_Port_Listener * upl = (UDP_Port_Listener *) data;
1209 // priority boost
1210 if( Chuck_VM::our_priority != 0x7fffffff )
1211 Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );
1213 EM_log( CK_LOG_INFO, "UDP_Port_Listener:: starting receive loop\n" );
1214 int mLen;
1215 do {
1216 mLen = upl->recv_mesg();
1217 usleep( 10 );
1218 } while( mLen != 0 );
1220 EM_log( CK_LOG_INFO, "UDP_Port_Listener:: receive loop terminated\n" );
1222 return (THREAD_RETURN)0;
1227 // returns whether an attempt to start the listening thread
1228 // was made.
1229 bool
1230 UDP_Port_Listener::listen() {
1231 if( !listening && m_in->status() != UDP_ERROR ) {
1232 listening = true;
1233 m_thread->start( udp_port_listener_thread, (void*) this );
1234 return true;
1236 return false;
1239 bool
1240 UDP_Port_Listener::bind_to_port(int port) {
1241 return m_in->bind_to_port( port );
1244 void
1245 UDP_Port_Listener::close() {
1246 if( m_in->status() == UDP_BOUND ) {
1247 listening = false;
1248 m_in->close_sock();
1253 UDP_Port_Listener::recv_mesg() {
1254 int mLen = m_in->recv_next( m_inbuf, m_inbufsize );
1256 if( mLen == 0 ) {
1257 EM_log( CK_LOG_INFO, "recvLen 0 on socket, returning 0" );
1258 return 0;
1261 m_mutex->acquire();
1262 vector<UDP_Subscriber *>::size_type i;
1263 for( i = 0 ; i < m_subscribers.size(); i++ ) {
1264 m_subscribers[i]->onReceive( m_inbuf, mLen );
1266 m_mutex->release();
1268 return mLen;
1272 // UDP_Subscriber
1273 bool
1274 UDP_Subscriber::subscribe( int p ) {
1275 if( port() >= 0 ) return false; //already subscribed
1276 else if( UDP_Port_Manager::instance()->subscribe( this, p ) )
1278 port() = p;
1279 return true;
1281 else
1283 port() = -1;
1284 return false;
1288 bool
1289 UDP_Subscriber::unsubscribe() {
1290 if( port() < 0 ) return false; //currently unsubscribed
1291 else if( UDP_Port_Manager::instance()->unsubscribe( this ) ) {
1292 port() = -1;
1293 return true;
1295 else {
1296 return false; //could not unsubscribe?
1302 UDP_Receiver::UDP_Receiver()
1304 _status = UDP_NOINIT;
1308 void
1309 UDP_Receiver::init()
1311 //open port
1312 _sock = ck_udp_create();
1313 _status = ( _sock != NULL ) ? UDP_UNBOUND : UDP_ERROR;
1316 bool
1317 UDP_Receiver::bind_to_port(int port)
1319 // Fill in the interface information
1320 _status = ( ck_bind ( _sock, port ) ) ? UDP_BOUND : UDP_ERROR ;
1321 if( _status == UDP_ERROR ) {
1322 EM_log( CK_LOG_SYSTEM, "(via OSC): cannot bind to port %d!", port);
1323 return false;
1326 return true;
1329 udp_stat
1330 UDP_Receiver::status() { return _status; }
1333 UDP_Receiver::recv_next(char * buffer, int bsize)
1335 if( _status != UDP_BOUND )
1337 EM_log( CK_LOG_SYSTEM, "(via OSC): recv -> socket not bound!"); return 0;
1340 _remote_addr_len = sizeof(_remote_addr);
1341 int ret = ck_recvfrom(_sock, buffer, bsize, (struct sockaddr *) &_remote_addr, &_remote_addr_len );
1343 return ( ret <= 0 ) ? 0 : ret;
1347 void
1348 UDP_Receiver::close_sock() {
1349 ck_close ( _sock );
1350 _status = UDP_NOINIT;
1354 void
1355 UDP_Transmitter::init() {
1356 //open socket
1357 _sock = ck_udp_create();
1358 _status = ( _sock != NULL ) ? UDP_READY : UDP_ERROR;
1362 void
1363 UDP_Transmitter::set_host(char * hostaddress, int port) {
1364 // Fill in the interface information
1366 struct hostent * host;
1367 // printf( "gathering host information..." );
1368 _host_addr.sin_family = AF_INET;
1369 _host_addr.sin_port = htons(port);
1370 _host_addr.sin_addr.s_addr = inet_addr(hostaddress);
1372 if(_host_addr.sin_addr.s_addr == INADDR_NONE) // The address wasn't in numeric
1374 host = NULL;
1375 host = gethostbyname(hostaddress); // Get the IP address of the server
1376 if(host == NULL)
1378 fprintf( stderr, "[chuck](via OSC): UDP_Transmitter: unknown host: %s\n", hostaddress);
1379 _status = UDP_ERROR;
1380 return;
1382 memcpy(&_host_addr.sin_addr, host->h_addr_list[0], host->h_length);
1383 // printf(" ...set\n");
1385 // else printf(" ...set\n");
1386 _status = UDP_READY;
1391 UDP_Transmitter::send(char * buffer, int bsize) {
1392 if( _status != UDP_READY )
1394 EM_log( CK_LOG_SYSTEM, "(via OSC): send -> socket not bound!");
1395 return 0;
1397 int ret = ck_sendto(_sock, buffer, bsize, (struct sockaddr *) &_host_addr, sizeof(_host_addr) );
1398 return ( ret <= 0 ) ? 0 : ret ;
1401 void
1402 UDP_Transmitter::close_sock() {
1403 ck_close( _sock );
1407 // OSC_TRANSMITTER
1409 OSC_Transmitter::OSC_Transmitter() {
1410 _out = new UDP_Transmitter();
1411 _holdMessage = false;
1412 init();
1415 OSC_Transmitter::OSC_Transmitter( UDP_Transmitter * out ) {
1416 _out = out;
1417 _holdMessage = false;
1420 OSC_Transmitter::~OSC_Transmitter() { delete _out; }
1422 void
1423 OSC_Transmitter::init() {
1424 if( _out->status() == UDP_NOINIT ) _out->init();
1425 OSC_initBuffer(&_osc, sizeof(_buffer), _buffer );
1428 void
1429 OSC_Transmitter::setHost( char * hadd, int p ) {
1430 _out->set_host(hadd, p);
1433 void
1434 OSC_Transmitter::presend( char * buf, int sz ) {
1435 _out->send(buf,sz);
1438 void
1439 OSC_Transmitter::openBundle( OSCTimeTag t) {
1440 OSC_openBundle( &_osc, t);
1444 void
1445 OSC_Transmitter::closeBundle() {
1446 OSC_closeBundle( &_osc );
1447 tryMessage();
1451 void
1452 OSC_Transmitter::addMessage( char *address, char * args, ...)
1454 if( args == NULL || args[0] == '\0' ) { // if there's no text
1455 OSC_writeAddress( &_osc, address ); // nothing
1456 return;
1459 va_list tags; // pointer to list of arguments
1460 va_start(tags, args); // parses the string for variables
1462 OSC_writeAddressAndTypes( &_osc, address, args );
1464 int argnum = strlen(args);
1465 int osc_err = 0;
1466 for( int j = 1; !osc_err && j < argnum; j++ ) {
1467 switch ( args[j] ) {
1468 case 'i':
1469 osc_err = OSC_writeIntArg ( &_osc, va_arg(tags, int) );
1470 break;
1471 case 'f':
1472 osc_err = OSC_writeFloatArg ( &_osc, va_arg(tags, double) );
1473 break;
1474 case 's':
1475 osc_err = OSC_writeStringArg ( &_osc, va_arg(tags, char *) );
1476 break;
1480 if( osc_err ) {
1481 EM_log( CK_LOG_SYSTEM, "(via OSC): error writing packet: %d %s...", osc_err, OSC_errorMessage );
1482 // failure action???
1485 va_end(tags); // Results Are Stored In Text
1486 tryMessage();
1489 void
1490 OSC_Transmitter::startMessage( char * spec ) {
1492 int len = strlen( spec );
1494 char * comma = strchr( spec, ',');
1495 char * space = strchr ( spec, ' ');
1496 int coff = ( comma == NULL ) ? len : comma - spec;
1497 int spoff = ( space == NULL ) ? len : space - spec;
1498 int off = min ( coff, spoff );
1500 if( off < len )
1501 spec[off] = '\0';
1503 startMessage( spec, spec + off + 1 );
1506 void
1507 OSC_Transmitter::startMessage( char * address, char * args )
1509 // OSC_writeAddressAndTypes( &_osc, address, args );
1510 char addrfix[512];
1511 int addrlen = strlen( address );
1512 // int mx = strlen(address) + strlen(args) + 1; // either we need to add a comma to args,
1513 // or it's got junk in it.
1514 // char addrfix[] = new char[mx]; // (char*) malloc( mx * sizeof( char ) );
1515 strcpy ( addrfix, address );
1516 addrfix[addrlen] = '\0';
1517 addrfix[addrlen+1] = ',';
1518 char * argptr = addrfix + (addrlen + 2);
1519 char * p_args = args;
1520 while ( *p_args != '\0' ) {
1521 if( *p_args != ',' && *p_args != ' ' ) {
1522 *argptr = *p_args;
1523 argptr++;
1525 p_args++;
1527 *argptr = '\0';
1529 OSC_writeAddressAndTypes( &_osc, addrfix, addrfix + addrlen + 1); //expects the ',' before spec tag.
1530 // delete[] addrfix;
1531 //free ( (void*)addrfix );
1532 tryMessage();
1535 void
1536 OSC_Transmitter::addInt ( int4byte i ) {
1537 int osc_err = OSC_writeIntArg ( &_osc, i );
1538 if( osc_err ) {
1539 fprintf ( stderr, "[chuck](via OSC): error writing packet: %d %s\n", osc_err, OSC_errorMessage );
1540 //failure action???
1542 tryMessage();
1545 void
1546 OSC_Transmitter::addFloat ( float f ) {
1547 int osc_err = OSC_writeFloatArg ( &_osc, f );
1548 if( osc_err ) {
1549 fprintf ( stderr, "[chuck](via OSC): error writing packet: %d %s\n", osc_err, OSC_errorMessage );
1550 //failure action???
1552 tryMessage();
1555 void
1556 OSC_Transmitter::addString ( char * s ) {
1557 int osc_err = OSC_writeStringArg ( &_osc, s );
1558 if( osc_err ) {
1559 fprintf ( stderr, "[chuck](via OSC): error writing packet: %d %s\n", osc_err, OSC_errorMessage );
1560 //failure action???
1562 tryMessage();
1565 bool
1566 OSC_Transmitter::packetReady() {
1567 if( _holdMessage ) return false; //message hold is on
1568 if( _osc.typeStringPtr ) { //if it's been typed, check that type is complete
1569 if( CheckTypeTag(&_osc, '\0' ) ) return false;
1571 return ( OSC_isBufferDone(&_osc) != 0 );
1574 void
1575 OSC_Transmitter::tryMessage() {
1576 if( !packetReady() ) return;
1578 _out->send( OSC_getPacket(&_osc), OSC_packetSize(&_osc) );
1579 OSC_resetBuffer(&_osc);
1582 void
1583 OSC_Transmitter::holdMessage(bool b) {
1584 _holdMessage = b;
1587 void
1588 OSC_Transmitter::kickMessage() {
1589 if( !OSC_isBufferDone(&_osc) ) {
1590 fprintf(stderr, "[chuck](via OSC): error -> sending incomplete packet!\n");
1592 _out->send( OSC_getPacket(&_osc), OSC_packetSize(&_osc) );
1593 OSC_resetBuffer(&_osc);
1597 // OSC_RECEIVER
1599 OSC_Receiver::OSC_Receiver():
1600 // _listening(false),
1601 // _inbufsize(OSCINBUFSIZE),
1602 _inbox(NULL),
1603 _inbox_size(2),
1604 _started(false),
1605 _in_read(0),
1606 _in_write(1),
1607 _address_space (NULL),
1608 _address_size ( 2 ),
1609 _address_num ( 0 )
1612 _inbox = (OSCMesg*) malloc (sizeof(OSCMesg) * _inbox_size);
1613 for( int i = 0; i < _inbox_size; i++ ) _inbox[i].payload = NULL;
1615 _address_space = (OSC_Address_Space **) realloc ( _address_space, _address_size * sizeof ( OSC_Address_Space * ) );
1617 _io_mutex = new XMutex();
1618 // _io_thread = new XThread();
1620 //_in = new UDP_Receiver();
1622 init();
1626 OSC_Receiver::OSC_Receiver(UDP_Receiver* in) {
1627 // _in = in;
1628 _port = -1;
1631 void
1632 OSC_Receiver::init(){
1633 _port = -1;
1634 // _in->init();
1637 OSC_Receiver::~OSC_Receiver()
1639 stopListening();
1640 for( int i=0; i < _inbox_size; i++ ) {
1641 if( _inbox[i].payload ) {
1642 free ( _inbox[i].payload );
1643 _inbox[i].payload = NULL;
1645 free ( _inbox );
1648 //delete _in;
1651 THREAD_RETURN ( THREAD_TYPE osc_recv_thread ) ( void * data )
1653 OSC_Receiver * oscar = (OSC_Receiver * ) data;
1655 // priority boost
1656 if( Chuck_VM::our_priority != 0x7fffffff )
1657 Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );
1659 do {
1660 oscar->recv_mesg();
1661 usleep( 10 );
1662 }while( true );
1664 return (THREAD_RETURN)0;
1668 int&
1669 OSC_Receiver::port() { return _port; }
1671 void
1672 OSC_Receiver::onReceive( char * mesg, int mesgLen ) {
1673 handle_mesg( mesg, mesgLen );
1676 void
1677 OSC_Receiver::bind_to_port(int port ) {
1678 _tmp_port = port;
1679 // _in->bind_to_port(port);
1682 bool
1683 OSC_Receiver::listen( int port ) {
1684 bind_to_port ( port );
1685 return listen();
1688 void
1689 OSC_Receiver::stopListening() {
1690 unsubscribe();
1693 bool
1694 OSC_Receiver::listen() {
1695 unsubscribe(); //in case we're connected.
1696 return subscribe( _tmp_port );
1698 if( !_listening ) {
1699 _listening = true;
1700 _io_thread->start( osc_recv_thread, (void*)this );
1702 return _listening;
1708 void
1709 OSC_Receiver::close_sock() {
1710 unsubscribe();
1711 // _in->close_sock();
1714 void
1715 OSC_Receiver::recv_mesg() {
1716 // this is when OSC_Receiver was
1717 // used as the port-manager. now this code ( and callback ) are in UDP_Port_Listener interface,
1718 // which OSC_Receiver subclasses
1721 _mesglen = _in->recv_next( _inbuf, _inbufsize );
1722 if( _mesglen > 0 ) {
1723 //parse();
1724 handle_mesg(_inbuf, _mesglen);
1730 bool
1731 OSC_Receiver::has_mesg() {
1732 // EM_log( CK_LOG_FINER, "OSC has message?" );
1733 return ( _started && ( _in_read+1 ) % _inbox_size != _in_write );
1736 bool
1737 OSC_Receiver::get_mesg(OSCMesg* bucket) {
1739 _io_mutex->acquire();
1741 if( has_mesg() ) {
1742 // next write _may_ fuck with _in_read
1743 // where when resizing the buffer...
1744 *bucket = *next_read();
1745 // fprintf(stderr, "r"); //read: %d of %d \n", _in_read, _inbox_size);
1746 _io_mutex->release();
1747 return true;
1750 _io_mutex->release();
1752 return false;
1755 void
1756 OSC_Receiver::parse( char * mesg, int mesgLen ) {
1758 // unpack bundles, dump all messages
1759 // any local prep we need here?
1761 long i = 0;
1762 // log
1763 EM_log( CK_LOG_FINER, "OSC_Receiver: print message length %d", mesgLen );
1764 for( i = 0 ; i < mesgLen; i++ ) {
1765 fprintf(stderr, "\t%c(%0x):", mesg[i], mesg[i]);
1768 fprintf( stderr, "\n" );
1771 void
1772 OSC_Receiver::next_write()
1774 // called by the UDP client ( blocks )
1776 if( !_started ) {
1777 _started = true;
1780 int next = (_in_write+1) % _inbox_size;
1782 if( next == _in_read ) {
1784 // fprintf(stderr, "OSC::need to resize...");
1786 _io_mutex->acquire(); //don't let next read return a bogus pointer
1788 if( _inbox_size < OSCINBOXMAX) {
1790 // LOCK MUTEX (on next_read)
1791 // prevents
1793 // mesgs might move around, but their data doesn't..(this is good)..
1794 // if we return an OSCmesg* to an out-of-thread function, it can expire.
1795 // so we pass in pointer to our own mesg from outside (get_mesg) and copy
1796 // from the current 'read' in the buffer...buffer may then be resized...
1797 // since data buffers do not move, we remain okay.
1799 // perhaps a monolithic chunk of memory is a better option...
1800 // but what if we want to handle multiple messages at once?
1802 // orrr..if we follow timetags and need semirandom access to
1803 // mesg contents for scheduling bundles..hmm.
1805 // make a separate case for scheduled messages...
1806 // throw them into a heap...
1808 // fuck...back to the todo...
1810 int new_size = ( _inbox_size * 2 > OSCINBOXMAX ) ? OSCINBOXMAX : _inbox_size * 2 ;
1812 bool err = false;
1814 // okay. read and write may be anywhere.
1815 if( _in_write > _in_read ) {
1816 // easy case
1817 _inbox = (OSCMesg* ) realloc ((void*)_inbox, new_size * sizeof(*_inbox) );
1818 err = (!_inbox);
1819 // indices are still valid
1821 else {
1822 // write is behind read in the buffer
1823 // copy into buffer so that contents remain contiguous
1824 // note:: copy the buffers between write and read...
1825 // they may have valid packet pointers.......
1827 OSCMesg * new_inbox =(OSCMesg*)malloc ( new_size * sizeof(*new_inbox) );
1828 err = (!new_inbox);
1830 if( !err ) {
1831 int _read_tail = _inbox_size - _in_read;
1832 memcpy( (void*)new_inbox, (void*)(_inbox+_in_read), (_read_tail) * sizeof(*_inbox) );
1833 memcpy( (void*)(new_inbox+_read_tail), (void*)_inbox, (_in_read ) * sizeof(*_inbox) );
1835 // update indices
1836 _in_read = 0;
1837 _in_write = (_in_write + _read_tail);
1839 free ( _inbox );
1840 _inbox = new_inbox;
1843 else err = true;
1847 if( !err ) {
1848 // new inbox elements need their payload pointers init to NULL
1849 for( int i = _inbox_size; i < new_size; i++ ) _inbox[i].payload = NULL;
1851 else {
1852 // fprintf(stderr, "fuck! fucking buffer reallocation error!\n");
1853 exit(0);
1856 next = (_in_write+1)%new_size; //where we're headed..
1857 _inbox_size = new_size;
1859 // fprintf(stderr, "(%d)", _inbox_size);
1860 // UNLOCK MUTEX
1862 else {
1863 // fprintf(stderr, "max buffer...dropping old mesg %d\n", next);
1864 _in_read = (next+1)%_inbox_size;
1867 _io_mutex->release();
1870 _in_write = next;
1874 OSCMesg*
1875 OSC_Receiver::next_read() {
1876 int next = ( _in_read + 1 ) % _inbox_size;
1877 if( next == _in_write ) return NULL; // can't intrude on write
1879 _in_read = next; //advance
1880 OSCMesg* ret= _inbox + _in_read; // return this pointer
1881 return ret;
1884 void
1885 OSC_Receiver::set_mesg(OSCMesg* mrp, char * buf, int len ) {
1887 // put pointers in the appropriate places
1888 // this means that mrp has no idea whether
1889 // its pointers refer to its own payload
1890 // or to an external buffer
1892 mrp->len = len; //total size of message
1893 mrp->address = buf;
1894 mrp->types = mrp->address + strlen(mrp->address) + 4 - strlen(mrp->address)%4;
1895 if( mrp->types[0] == ',') {
1896 // typed message
1897 mrp->data= mrp->types + strlen(mrp->types) + 4 - strlen(mrp->types)%4;
1899 else {
1900 // untyped message.
1901 // should there be a warning?
1902 // classes that handle mesgs
1903 // should take care of that.
1904 mrp->data = mrp->types;
1905 mrp->types = NULL;
1910 void
1911 OSC_Receiver::handle_mesg( char * buf, int len )
1913 // this is called sequentially by the receiving thread.
1914 if( buf[0] == '#' ) { handle_bundle( buf, len ); return; }
1916 OSCMesg * mrp = write();
1918 if( mrp->payload == NULL ) {
1919 mrp->payload = (char *)malloc( OSCINBUFSIZE * sizeof(char) );
1920 // fprintf(stderr, "oscrecv:mallocing %d bytes\n", OSCINBUFSIZE);
1923 memcpy( (void*)mrp->payload, (const void*)buf, len ); // copy data from buffer to message payload
1924 set_mesg( mrp, mrp->payload, len ); // set pointers for the message to its own payload
1925 mrp->recvtime = 0.000; // GetTime(); // set message time
1927 distribute_message( mrp ); // copy message to any & all matching address spaces
1929 // the distribute message will copy any necessary data into the addr object's private queue.
1930 // so we don't need to buffer here.. ( totally wasting the kick-ass expanding buffer i have in this class...drat )
1932 // next_write();
1935 void
1936 OSC_Receiver::handle_bundle(char*b, int len) {
1938 //no scheduling for now
1939 //just immediately unpack everything
1941 //fprintf(stderr, "bundle (length %d)\n", len);
1943 int off = 16; //skip "#bundle\0timetags"
1945 while ( off < len )
1947 char * z = b+off;
1948 unsigned long size = ntohl(*((unsigned long*)z));
1950 char * m = z+4;
1952 if( m[0] == '#' ) handle_bundle(m,size);
1953 else handle_mesg(m,size);
1955 off += size+4; //beginning of next message
1959 OSC_Address_Space *
1960 OSC_Receiver::new_event ( char * spec) {
1961 OSC_Address_Space * event = new OSC_Address_Space ( spec );
1962 add_address ( event );
1963 return event;
1966 OSC_Address_Space *
1967 OSC_Receiver::new_event ( char * addr, char * type) {
1968 OSC_Address_Space * event = new OSC_Address_Space ( addr, type );
1969 add_address ( event );
1970 return event;
1974 void
1975 OSC_Receiver::add_address ( OSC_Address_Space * src ) {
1976 if( _address_num == _address_size ) {
1977 _address_size *= 2;
1978 _address_space = (OSC_Address_Space **) realloc ( _address_space, _address_size * sizeof( OSC_Address_Space **));
1980 _address_space[_address_num++] = src;
1981 src->setReceiver(this);
1984 void
1985 OSC_Receiver::remove_address ( OSC_Address_Space *odd ) {
1986 for( int i = 0 ; i < _address_num ; i++ ) {
1987 while ( _address_space[i] == odd ) {
1988 _address_space[i] = _address_space[--_address_num];
1994 This function distributes each message to a matching address inside the
1995 chuck shred. There are some issues with this.
1996 bundle simultaneity might be solved via mutex?
2000 void
2001 OSC_Receiver::distribute_message( OSCMesg * msg ) {
2002 for( int i = 0 ; i < _address_num ; i++ ) {
2003 if( _address_space[i]->try_queue_mesg( msg ) ) {
2004 // fprintf ( stderr, "broadcasting %x from %x\n", (uint)_address_space[i]->SELF, (uint)_address_space[i] );
2005 // if the event has any shreds queued, fire them off..
2006 ( (Chuck_Event *) _address_space[i]->SELF )->queue_broadcast();
2012 // OSC SOURCE ( Parser )
2013 // rename to OSC_address ?
2015 // this is an OSC_Address_Space - we register it to a particular receiver
2016 // the receiver matches an incoming message against registered
2017 // address and sends the message to all that match.
2019 // OSCMesg may still have pointers to a mysterious void.
2020 // we should copy values locally for string and blob.
2022 // public for of inherited chuck_event mfunc.
2024 const char * osc_typename_strings[] = {
2025 "untyped",
2026 "no arguments",
2027 "integer",
2028 "float",
2029 "string",
2030 "blob",
2031 "ERROR: num types exceeded"
2036 OSC_Address_Space::OSC_Address_Space() {
2037 init();
2038 setSpec( "/undefined/default,i" );
2042 OSC_Address_Space::OSC_Address_Space( const char * spec ) {
2043 init();
2044 setSpec( spec );
2047 OSC_Address_Space::OSC_Address_Space( const char * addr, const char * types) {
2048 init();
2049 setSpec( addr, types );
2052 void
2053 OSC_Address_Space::init() {
2054 _receiver = NULL;
2055 SELF = NULL;
2056 _queueSize = 512; // start queue size at 512 // 64.
2057 _dataSize = 0;
2058 _cur_mesg = NULL;
2059 _queue = NULL;
2060 _cur_value = 0;
2061 _current_data = NULL;
2062 _buffer_mutex = new XMutex();
2065 OSC_Address_Space::~OSC_Address_Space() {
2066 if( _queue ) free ( _queue );
2069 void
2070 OSC_Address_Space::setReceiver(OSC_Receiver * recv) {
2071 _receiver = recv;
2074 void
2075 OSC_Address_Space::setSpec( const char *addr, const char * types ) {
2076 strncpy ( _spec, addr, 512 );
2077 strncat ( _spec, "," , 512);
2078 strncat ( _spec, types, 512 );
2079 scanSpec();
2080 _needparse = true;
2081 parseSpec();
2084 void
2085 OSC_Address_Space::setSpec( const char *c ) {
2086 strncpy ( _spec, c, 512);
2087 scanSpec();
2088 _needparse = true;
2089 parseSpec();
2092 void
2093 OSC_Address_Space::scanSpec() { //this allows for sloppy-ish definitions in type string
2094 //assumes that a potential spec is already in _spec;
2095 char * pread;
2096 char * pwrite;
2097 pread = pwrite = (char*)_spec;
2098 bool in_type = false;
2099 while ( *pread != '\0' ) {
2100 if( *pread == ',' || *pread == ' ' ) {
2101 if( !in_type ) {
2102 in_type = true;
2103 *pwrite = ',';
2104 pwrite++;
2105 } // otherwise, we ignore
2106 else if( *pread == ' ' ) {
2107 EM_log(CK_LOG_INFO, "OSC-Address-Space: spaces in OSC type tag string! ignoring");
2110 else {
2111 if( pwrite != pread ) { *pwrite = *pread; }
2112 pwrite++;
2114 pread++;
2116 if( !in_type ) {
2117 //no type args found, add a comma to indicate a zero-arg string.
2118 *(pwrite++) = ',';
2120 *pwrite = '\0'; //if pread terminates, so does pwrite.
2123 void
2124 OSC_Address_Space::parseSpec() {
2126 if( !_needparse ) return;
2128 char * type = strrchr(_spec, ',');
2129 if( !type ) return;
2131 *type = '\0'; //null the address
2132 type++; //point to type string
2134 strcpy ( _address, _spec );
2135 strcpy ( _type , type );
2137 // fprintf(stderr," parsing spec- address %s :: type %s\n", _address, _type);
2139 int n = strlen ( type );
2140 _noArgs = ( n == 0 );
2141 resizeData( ( n < 1 ) ? 1 : n );
2142 _qread = 0;
2143 _qwrite = 1;
2145 _needparse = false;
2148 void
2149 OSC_Address_Space::resizeQueue( int n )
2151 if( n <= _queueSize )
2152 return; // only grows
2154 // lock
2155 _buffer_mutex->acquire();
2157 // it's possible that between the test above and now,
2158 // qread has moved on and we actually DO have space..
2160 EM_log( CK_LOG_INFO, "OSC_Address (%s) -- buffer full ( r:%d , w:%d, of %d(x%d) ), resizing...",
2161 _address, _qread, _qwrite, _queueSize, _dataSize );
2162 // fprintf( stderr, "--- hasMesg ( %d ) nextMesg ( %d )\n", (int) has_mesg(), (int)next_mesg() );
2164 // we're the server... all we know is that the contents of qread are in the current_buffer,
2165 // so we can move the data, but we don't want to move ahead and lose it just yet.
2167 // compute chunk size
2168 size_t chunkSize = _dataSize * sizeof( opsc_data );
2170 // allocate
2171 int _newQSize = n;
2172 opsc_data * _new_queue = (opsc_data *)malloc( _newQSize * chunkSize );
2174 // clear
2175 memset( _new_queue, 0, _newQSize * chunkSize ); // out with the old...
2176 // copy
2177 if( _qread < _qwrite )
2179 // we're doing this because qwrite is out of room.
2180 // so if qwrite is already greater than qread,
2181 // just copy the whole thing to the start of the new buffer ( adding more space to the end )
2182 memcpy( (void*)_new_queue, (const void*)_queue, _queueSize * chunkSize);
2183 // _qwrite and _qread can stay right where they are.
2184 // fprintf(stderr, "resize - case 1\n");
2186 else
2188 // _qread is in front of _qwrite, so we must unwrap, and place _qread at the
2189 // front of the queue, and qwrite at the end, preserving all elements that qread
2190 // is waiting to consume.
2191 int nread = _queueSize - _qread;
2192 memcpy( (void*)_new_queue,
2193 (const void*)(_queue + _qread * _dataSize),
2194 (nread) * chunkSize);
2195 memcpy( (void*)(_new_queue + nread * _dataSize),
2196 (const void*)_queue,
2197 (_qread) * _dataSize * sizeof( opsc_data ));
2198 _qread = 0;
2199 _qwrite += nread;
2200 // EM_log(CK_LOG_INFO, "resize - case 2\n");
2203 _queueSize = _newQSize;
2204 opsc_data * trash = _queue;
2205 _queue = _new_queue;
2206 free ( (void*)trash );
2208 // don't move qread or qwrite until we're done.
2209 _buffer_mutex->release();
2213 void
2214 OSC_Address_Space::resizeData( int n ) {
2215 if( _dataSize == n ) return;
2216 _dataSize = n;
2217 int queueLen = _queueSize * _dataSize * sizeof( opsc_data );
2218 _queue = ( opsc_data * ) realloc ( _queue, queueLen );
2219 memset ( _queue, 0, queueLen );
2220 _current_data = (opsc_data* ) realloc ( _current_data, _dataSize * sizeof( opsc_data) );
2224 bool
2225 OSC_Address_Space::message_matches( OSCMesg * m ) {
2227 //this should test for type as well.
2229 bool addr_match;
2230 if( strcmp ( m->address, _address ) == 0 ) addr_match = true;
2231 else addr_match = PatternMatch( m->address, _address);
2232 if( !addr_match ) return false;
2234 //address AND type must match
2235 //but there should be an option for the blank 'information about this' pattern
2237 char * type = m->types+1;
2238 if( m->types == NULL || strcmp( _type , type ) != 0 ) {
2239 // if( type )
2240 // fprintf(stderr, "error, mismatched type string( %s ) vs ( %s ) \n", _type, type ) ;
2241 // else
2242 // fprintf( stderr, "error, missing type string (expecting %s) \n", _type );
2243 return false;
2245 return true;
2249 bool
2250 OSC_Address_Space::try_queue_mesg( OSCMesg * m )
2252 if( !message_matches( m ) ) return false;
2253 queue_mesg( m );
2254 return true;
2259 bool
2260 OSC_Address_Space::has_mesg() {
2261 // EM_log( CK_LOG_FINER, "OSC has mesg" );
2262 return ( ( _qread + 1 ) % _queueSize != _qwrite );
2266 bool
2267 OSC_Address_Space::next_mesg()
2269 if( has_mesg() )
2271 _buffer_mutex->acquire();
2273 if( !has_mesg() ) return false;
2275 // move qread forward
2276 _qread = ( _qread + 1 ) % _queueSize;
2277 memcpy( _current_data, _queue + _qread * _dataSize, _dataSize * sizeof( opsc_data ) );
2278 _cur_mesg = _current_data;
2279 _cur_value = 0;
2281 _buffer_mutex->release();
2283 return true;
2286 return false;
2289 bool
2290 OSC_Address_Space::vcheck( osc_datatype tt ) {
2292 if( !_cur_mesg ) {
2293 EM_log( CK_LOG_SEVERE, "OscEvent: getVal(): nextMsg() must be called before reading data..." );
2294 return false;
2296 else if( _cur_value < 0 || _cur_value >= _dataSize ) {
2297 EM_log( CK_LOG_SEVERE, "OscEvent: read position %d outside message ...", _cur_value );
2298 return false;
2300 else if( _cur_mesg[_cur_value].t != tt ) {
2301 EM_log( CK_LOG_SEVERE, "OscEvent: error -> message type %s != request type %s", osc_typename_strings[_cur_mesg[_cur_value].t], osc_typename_strings[tt] );
2302 return false;
2305 return true;
2308 int4byte
2309 OSC_Address_Space::next_int() {
2310 return ( vcheck(OSC_INT) ) ? _cur_mesg[_cur_value++].i : 0 ;
2313 float
2314 OSC_Address_Space::next_float() {
2315 return ( vcheck(OSC_FLOAT) ) ? _cur_mesg[_cur_value++].f : 0.0 ;
2318 char *
2319 OSC_Address_Space::next_string() {
2320 return ( vcheck(OSC_STRING) ) ? _cur_mesg[_cur_value++].s : NULL ;
2323 char *
2324 OSC_Address_Space::next_string_dup() {
2325 if( !vcheck(OSC_STRING) ) return NULL;
2326 char * alt_c = _cur_mesg[_cur_value++].s;
2327 char * dup_c = (char * ) malloc ( (strlen ( alt_c )+1 ) * sizeof(char) );
2328 strcpy ( dup_c, alt_c );
2329 return dup_c;
2332 char *
2333 OSC_Address_Space::next_blob() {
2334 return ( vcheck(OSC_BLOB) ) ? _cur_mesg[_cur_value++].s : NULL ;
2337 void
2338 OSC_Address_Space::queue_mesg( OSCMesg * m )
2340 // in the server thread.
2341 int nqw = ( _qwrite + 1 ) % _queueSize;
2342 EM_log( CK_LOG_FINE, "OSC address(%s): read: %d write: %d size: %d", _address, _qread, _qwrite, _queueSize );
2344 if( nqw == _qread ) {
2345 if( _queueSize < OSC_ADDRESS_QUEUE_MAX ) {
2346 resizeQueue( _queueSize * 2 );
2347 nqw = ( _qwrite + 1 ) % _queueSize; // _qwrite, _qread may have changed.
2349 else {
2350 EM_log( CK_LOG_INFO, "OSC_Address_Space(%s): message queue reached max size %d...", _address, _queueSize );
2351 EM_log( CK_LOG_INFO, "...(dropping oldest message %d)", _qread );
2353 // bump!
2354 _buffer_mutex->acquire();
2355 _qread = ( _qread + 1 ) % _queueSize;
2356 _buffer_mutex->release();
2360 _vals = _queue + _qwrite * _dataSize;
2362 if( _noArgs ) { // if address takes no arguments,
2363 _vals[0].t = OSC_NOARGS;
2365 else {
2366 char * type = m->types+1;
2367 char * data = m->data;
2369 unsigned int endy;
2370 int i=0;
2372 float *fp;
2373 int *ip;
2374 int clen;
2375 while ( *type != '\0' ) {
2376 switch ( *type ) {
2377 case 'f':
2378 endy = ntohl(*((unsigned long*)data));
2379 fp = (float*)(&endy);
2380 _vals[i].t = OSC_FLOAT;
2381 _vals[i].f = *fp;
2382 data += 4;
2383 break;
2384 case 'i':
2385 endy = ntohl(*((unsigned long*)data));
2386 ip = (int4byte*)(&endy);
2387 _vals[i].t = OSC_INT;
2388 _vals[i].i = *ip;
2389 data += 4;
2390 break;
2391 case 's':
2392 // string
2393 clen = strlen(data) + 1; // terminating!
2394 _vals[i].t = OSC_STRING;
2395 _vals[i].s = (char *) realloc ( _vals[i].s, clen * sizeof(char) );
2396 memcpy ( _vals[i].s, data, clen ); // make a copy of the data...
2397 // fprintf(stderr, "add string |%s| ( %d ) \n", _vals[i].s, clen );
2398 data += (((clen-1) >> 2) + 1) << 2;
2399 // data += clen + 4 - clen % 4;
2400 break;
2401 case 'b':
2402 // blobs
2403 endy = ntohl(*((unsigned long*)data));
2404 clen = *((int*)(&endy));
2405 _vals[i].t = OSC_BLOB;
2406 _vals[i].s = (char* ) realloc ( _vals[i].s, clen * sizeof(char) );
2407 memcpy ( _vals[i].s, data, clen );
2408 data += clen + 4 - clen % 4;
2409 break;
2411 i++;
2412 type++;
2416 _qwrite = nqw;
2418 //review
2420 for( i=0; i < _nvals; i++ ) {
2421 fprintf(stderr, "%d %f : ", i, _val[i] );
2423 fprintf(stderr, "\n");