*** empty log message ***
[chuck-blob.git] / v2 / util_opsc.cpp
blob2e2ad0ab12cf550546f01a50af222e0d49a21514
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 using namespace std;
46 // FROM PLATFORM.H -UDP TRANSMITTER / RECEIVER
48 #if defined(__PLATFORM_WIN32__)
49 #include <windows.h>
50 #else
51 #include <sys/types.h>
52 #include <sys/socket.h>
53 #include <sys/time.h>
54 #include <unistd.h>
55 #include <netinet/in.h>
56 #include <netinet/tcp.h>
57 #include <arpa/inet.h>
58 #include <netdb.h>
59 #endif
61 #if defined(__MACOSX_CORE__)
62 #define SOCKET int
63 #define SOCKADDR_IN struct sockaddr_in
64 #elif !defined(SOCKADDR_IN)
65 #define SOCKET int
66 #define SOCKADDR_IN struct sockaddr_in
67 #endif
70 // squeeze the whole wad of OSC-Kit code in here.
72 // OSC-pattern-match.cpp
75 Copyright © 1998. The Regents of the University of California (Regents).
76 All Rights Reserved.
78 Written by Matt Wright, The Center for New Music and Audio Technologies,
79 University of California, Berkeley.
81 Permission to use, copy, modify, distribute, and distribute modified versions
82 of this software and its documentation without fee and without a signed
83 licensing agreement, is hereby granted, provided that the above copyright
84 notice, this paragraph and the following two paragraphs appear in all copies,
85 modifications, and distributions.
87 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
88 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
89 OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
90 BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
92 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
93 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
95 HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
96 MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
98 The OpenSound Control WWW page is
99 http://www.cnmat.berkeley.edu/OpenSoundControl
105 OSC-pattern-match.c
106 Matt Wright, 3/16/98
107 Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury
110 // #include "OSC-pattern-match.h"
112 static const char *theWholePattern; /* Just for warning messages */
114 static bool MatchBrackets( const char * pattern, const char * test );
115 static bool MatchList( const char * pattern, const char * test );
117 bool PatternMatch( const char * pattern, const char * test )
119 theWholePattern = pattern;
121 if( pattern == 0 || pattern[0] == 0 ) {
122 return test[0] == 0;
125 if( test[0] == 0 ) {
126 if(pattern[0] == '*')
127 return PatternMatch (pattern+1,test);
128 else
129 return FALSE;
132 switch( pattern[0] )
134 case 0 : return test[0] == 0;
135 case '?' : return PatternMatch (pattern + 1, test + 1);
136 case '*' :
137 if( PatternMatch (pattern+1, test) ) {
138 return TRUE;
139 } else {
140 return PatternMatch (pattern, test+1);
142 case ']' :
143 case '}' :
144 fprintf( stderr, "[chuck](via OSC): spurious %c in pattern \".../%s/...\"\n", pattern[0], theWholePattern );
145 return FALSE;
146 case '[' :
147 return MatchBrackets (pattern,test);
148 case '{' :
149 return MatchList (pattern,test);
150 case '\\' :
151 if(pattern[1] == 0) {
152 return test[0] == 0;
153 } else if(pattern[1] == test[0]) {
154 return PatternMatch (pattern+2,test+1);
155 } else {
156 return FALSE;
158 default :
159 if(pattern[0] == test[0]) {
160 return PatternMatch (pattern+1,test+1);
161 } else {
162 return FALSE;
168 /* we know that pattern[0] == '[' and test[0] != 0 */
170 static bool MatchBrackets( const char * pattern, const char * test )
172 bool result;
173 bool negated = FALSE;
174 const char *p = pattern;
176 if(pattern[1] == 0) {
177 fprintf( stderr, "[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern );
178 return FALSE;
181 if(pattern[1] == '!') {
182 negated = TRUE;
183 p++;
186 while (*p != ']') {
187 if(*p == 0) {
188 fprintf( stderr,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern );
189 return FALSE;
192 if(p[1] == '-' && p[2] != 0) {
193 if(test[0] >= p[0] && test[0] <= p[2]) {
194 result = !negated;
195 goto advance;
199 if(p[0] == test[0]) {
200 result = !negated;
201 goto advance;
203 p++;
206 result = negated;
208 advance:
210 if(!result)
211 return FALSE;
213 while (*p != ']') {
214 if(*p == 0) {
215 fprintf( stderr,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern );
216 return FALSE;
218 p++;
221 return PatternMatch (p+1,test+1);
225 static bool MatchList( const char * pattern, const char * test )
227 const char *restOfPattern, *tp = test;
229 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
230 if(*restOfPattern == 0) {
231 fprintf( stderr,"[chuck](via OSC): unterminated { in pattern \".../%s/...\"\n", theWholePattern );
232 return FALSE;
236 restOfPattern++; /* skip close curly brace */
238 pattern++; /* skip open curly brace */
240 while( 1 )
242 if(*pattern == ',') {
243 if(PatternMatch (restOfPattern, tp)) {
244 return TRUE;
245 } else {
246 tp = test;
247 ++pattern;
249 } else if(*pattern == '}') {
250 return PatternMatch (restOfPattern, tp);
251 } else if(*pattern == *tp) {
252 ++pattern;
253 ++tp;
254 } else {
255 tp = test;
256 while (*pattern != ',' && *pattern != '}') {
257 pattern++;
259 if(*pattern == ',') {
260 pattern++;
266 // end OSC-pattern-match.h
269 // OSC-timetag.cpp
272 Copyright (c) 1998. The Regents of the University of California (Regents).
273 All Rights Reserved.
275 Permission to use, copy, modify, and distribute this software and its
276 documentation for educational, research, and not-for-profit purposes, without
277 fee and without a signed licensing agreement, is hereby granted, provided that
278 the above copyright notice, this paragraph and the following two paragraphs
279 appear in all copies, modifications, and distributions. Contact The Office of
280 Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
281 CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
283 Written by Matt Wright, The Center for New Music and Audio Technologies,
284 University of California, Berkeley.
286 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
287 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
288 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
289 REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
291 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
292 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
293 FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
294 DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
295 REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
296 ENHANCEMENTS, OR MODIFICATIONS.
298 The OpenSound Control WWW page is
299 http://www.cnmat.berkeley.edu/OpenSoundControl
303 OSC_timeTag.c: library for manipulating OSC time tags
304 Matt Wright, 5/29/97
306 Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
309 //#include "OSC-timetag.h"
312 #ifdef HAS8BYTEINT
313 #define TWO_TO_THE_32_FLOAT 4294967296.0f
315 OSCTimeTag OSCTT_Immediately(void) {
316 return (OSCTimeTag) 1;
319 OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
320 return (OSCTimeTag) 0xffffffffffffffff;
323 OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
324 int64 offset = (int64) (secondsOffset * TWO_TO_THE_32_FLOAT);
326 /* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original,
327 secondsOffset, offset, original + offset); */
329 return original + offset;
332 int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right)
334 #if 0
335 printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right,
336 (left<right) ? -1 : ((left == right) ? 0 : 1));
337 #endif
338 if(left < right) {
339 return -1;
340 } else if(left == right) {
341 return 0;
342 } else {
343 return 1;
347 #ifdef __sgi
348 #include <sys/time.h>
350 #define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */
351 #define TWO_TO_THE_32_OVER_ONE_MILLION 4295
354 OSCTimeTag OSCTT_CurrentTime(void) {
355 uint64 result;
356 uint32 usecOffset;
357 struct timeval tv;
358 struct timezone tz;
360 BSDgettimeofday(&tv, &tz);
362 /* First get the seconds right */
363 result = (unsigned) SECONDS_FROM_1900_to_1970 +
364 (unsigned) tv.tv_sec -
365 (unsigned) 60 * tz.tz_minuteswest +
366 (unsigned) (tz.tz_dsttime ? 3600 : 0);
368 #if 0
369 /* No timezone, no DST version ... */
370 result = (unsigned) SECONDS_FROM_1900_to_1970 +
371 (unsigned) tv.tv_sec;
372 #endif
375 /* make seconds the high-order 32 bits */
376 result = result << 32;
378 /* Now get the fractional part. */
379 usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION;
380 /* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */
382 result += usecOffset;
384 /* printf("* OSCTT_CurrentTime is %llx\n", result); */
385 return result;
388 #else /* __sgi */
390 /* Instead of asking your operating system what time it is, it might be
391 clever to find out the current time at the instant your application
392 starts audio processing, and then keep track of the number of samples
393 output to know how much time has passed. */
395 /* Loser version for systems that have no ability to tell the current time: */
396 OSCTimeTag OSCTT_CurrentTime(void) {
397 return (OSCTimeTag) 1;
400 #endif /* __sgi */
403 #else /* Not HAS8BYTEINT */
405 OSCTimeTag OSCTT_CurrentTime(void) {
406 OSCTimeTag result;
407 result.seconds = 0;
408 result.fraction = 1;
409 return result;
412 OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
413 OSCTimeTag result;
414 result.seconds = 0xffffffff;
415 result.fraction = 0xffffffff;
416 return result;
419 OSCTimeTag OSCTT_Immediately(void) {
420 OSCTimeTag result;
421 result.seconds = 0;
422 result.fraction = 1;
423 return result;
426 OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
427 OSCTimeTag result;
428 result.seconds = 0;
429 result.fraction = 1;
430 return result;
433 int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
434 /* Untested! */
435 int highResult = left.seconds - right.seconds;
437 if(highResult != 0) return highResult;
439 return left.fraction - right.fraction;
443 #endif /* HAS8BYTEINT */
445 // end OSC-timetag.cpp
447 // OSC-client.cpp
450 Copyright (c) 1996. The Regents of the University of California (Regents).
451 All Rights Reserved.
453 Permission to use, copy, modify, and distribute this software and its
454 documentation for educational, research, and not-for-profit purposes, without
455 fee and without a signed licensing agreement, is hereby granted, provided that
456 the above copyright notice, this paragraph and the following two paragraphs
457 appear in all copies, modifications, and distributions. Contact The Office of
458 Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
459 CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
461 Written by Matt Wright, The Center for New Music and Audio Technologies,
462 University of California, Berkeley.
464 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
465 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
466 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
467 REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
469 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
470 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
471 FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
472 DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
473 REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
474 ENHANCEMENTS, OR MODIFICATIONS.
479 Author: Matt Wright
480 Version 2.2: Calls htonl in the right places 20000620
481 Version 2.3: Gets typed messages right.
485 /* Here are the possible values of the state field: */
487 #define EMPTY 0 /* Nothing written to packet yet */
488 #define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
489 #define NEED_COUNT 2 /* Just opened a bundle; must write message name or
490 open another bundle */
491 #define GET_ARGS 3 /* Getting arguments to a message. If we see a message
492 name or a bundle open/close then the current message
493 will end. */
494 #define DONE 4 /* All open bundles have been closed, so can't write
495 anything else */
498 //#include "OSC-client.h"
500 char *OSC_errorMessage;
503 //static int strlen(char *s);
504 static int OSC_padString(char *dest, char *str);
505 static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
506 static int OSC_WritePadding(char *dest, int i);
507 static int CheckTypeTag(OSCbuf *buf, char expectedType);
509 void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
510 buf->buffer = byteArray;
511 buf->size = size;
512 OSC_resetBuffer(buf);
515 void OSC_resetBuffer(OSCbuf *buf) {
516 buf->bufptr = buf->buffer;
517 buf->state = EMPTY;
518 buf->bundleDepth = 0;
519 buf->prevCounts[0] = 0;
520 buf->gettingFirstUntypedArg = 0;
521 buf->typeStringPtr = 0;
524 int OSC_isBufferEmpty(OSCbuf *buf) {
525 return buf->bufptr == buf->buffer;
528 int OSC_freeSpaceInBuffer(OSCbuf *buf) {
529 return buf->size - (buf->bufptr - buf->buffer);
532 int OSC_isBufferDone(OSCbuf *buf) {
533 return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
536 char *OSC_getPacket(OSCbuf *buf)
538 #ifdef ERROR_CHECK_GETPACKET
539 if(buf->state == DONE || buf->state == ONE_MSG_ARGS) {
540 return buf->buffer;
541 } else {
542 OSC_errorMessage = "Packet has unterminated bundles";
543 return 0;
545 #else
546 return buf->buffer;
547 #endif
550 int OSC_packetSize(OSCbuf *buf)
552 #ifdef ERROR_CHECK_PACKETSIZE
553 if(buf->state == DONE || buf->state == ONE_MSG_ARGS) {
554 return (buf->bufptr - buf->buffer);
555 } else {
556 OSC_errorMessage = "Packet has unterminated bundles";
557 return 0;
559 #else
560 return (buf->bufptr - buf->buffer);
561 #endif
564 #define CheckOverflow(buf, bytesNeeded) { \
565 if((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
566 OSC_errorMessage = "buffer overflow"; \
567 return 1; \
571 static void PatchMessageSize(OSCbuf *buf)
573 int4byte size;
574 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
575 *(buf->thisMsgSize) = htonl(size);
578 int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt)
580 if(buf->state == ONE_MSG_ARGS) {
581 OSC_errorMessage = "Can't open a bundle in a one-message packet";
582 return 3;
585 if(buf->state == DONE) {
586 OSC_errorMessage = "This packet is finished; can't open a new bundle";
587 return 4;
590 if(++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
591 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
592 return 2;
595 if(CheckTypeTag(buf, '\0')) return 9;
597 if(buf->state == GET_ARGS) {
598 PatchMessageSize(buf);
601 if(buf->state == EMPTY) {
602 /* Need 16 bytes for "#bundle" and time tag */
603 CheckOverflow(buf, 16);
604 } else {
605 /* This bundle is inside another bundle, so we need to leave
606 a blank size count for the size of this current bundle. */
607 CheckOverflow(buf, 20);
608 *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
609 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
611 buf->bufptr += 4;
614 buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
616 *((OSCTimeTag *) buf->bufptr) = tt;
618 if(htonl(1) != 1)
620 /* Byte swap the 8-byte integer time tag */
621 int4byte *intp = (int4byte *)buf->bufptr;
622 intp[0] = htonl(intp[0]);
623 intp[1] = htonl(intp[1]);
625 #ifdef HAS8BYTEINT
626 { /* tt is a 64-bit int so we have to swap the two 32-bit words.
627 (Otherwise tt is a struct of two 32-bit words, and even though
628 each word was wrong-endian, they were in the right order
629 in the struct.) */
630 int4byte temp = intp[0];
631 intp[0] = intp[1];
632 intp[1] = temp;
634 #endif
637 buf->bufptr += sizeof(OSCTimeTag);
639 buf->state = NEED_COUNT;
641 buf->gettingFirstUntypedArg = 0;
642 buf->typeStringPtr = 0;
643 return 0;
646 int OSC_closeBundle(OSCbuf *buf)
648 if(buf->bundleDepth == 0) {
649 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
650 OSC_errorMessage = "Can't close bundle; no bundle is open!";
651 return 5;
654 if(CheckTypeTag(buf, '\0')) return 9;
656 if(buf->state == GET_ARGS) {
657 PatchMessageSize(buf);
660 if(buf->bundleDepth == 1) {
661 /* Closing the last bundle: No bundle size to patch */
662 buf->state = DONE;
663 } else {
664 /* Closing a sub-bundle: patch bundle size */
665 int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
666 *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
667 buf->state = NEED_COUNT;
670 --buf->bundleDepth;
671 buf->gettingFirstUntypedArg = 0;
672 buf->typeStringPtr = 0;
673 return 0;
677 int OSC_closeAllBundles(OSCbuf *buf)
679 if(buf->bundleDepth == 0) {
680 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
681 OSC_errorMessage = "Can't close all bundles; no bundle is open!";
682 return 6;
685 if(CheckTypeTag(buf, '\0')) return 9;
687 while (buf->bundleDepth > 0) {
688 OSC_closeBundle(buf);
691 buf->typeStringPtr = 0;
692 return 0;
695 int OSC_writeAddress(OSCbuf *buf, char *name)
697 int4byte paddedLength;
699 if(buf->state == ONE_MSG_ARGS) {
700 OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
701 return 7;
704 if(buf->state == DONE) {
705 OSC_errorMessage = "This packet is finished; can't write another address";
706 return 8;
709 if(CheckTypeTag(buf, '\0')) return 9;
711 paddedLength = OSC_effectiveStringLength(name);
713 if(buf->state == EMPTY) {
714 /* This will be a one-message packet, so no sizes to worry about */
715 CheckOverflow(buf, paddedLength);
716 buf->state = ONE_MSG_ARGS;
717 } else {
718 /* GET_ARGS or NEED_COUNT */
719 CheckOverflow(buf, 4+paddedLength);
720 if(buf->state == GET_ARGS) {
721 /* Close the old message */
722 PatchMessageSize(buf);
724 buf->thisMsgSize = (int4byte *)buf->bufptr;
725 *(buf->thisMsgSize) = 0xbbbbbbbb;
726 buf->bufptr += 4;
727 buf->state = GET_ARGS;
730 /* Now write the name */
731 buf->bufptr += OSC_padString(buf->bufptr, name);
732 buf->typeStringPtr = 0;
733 buf->gettingFirstUntypedArg = 1;
735 return 0;
738 int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types)
740 int result;
741 int4byte paddedLength;
743 if(CheckTypeTag(buf, '\0')) return 9;
745 result = OSC_writeAddress(buf, name);
747 if(result) return result;
749 paddedLength = OSC_effectiveStringLength(types);
751 CheckOverflow(buf, paddedLength);
753 buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
754 buf->bufptr += OSC_padString(buf->bufptr, types);
756 buf->gettingFirstUntypedArg = 0;
758 return 0;
761 static int CheckTypeTag(OSCbuf *buf, char expectedType)
763 if(buf->typeStringPtr) {
764 if(*(buf->typeStringPtr) != expectedType) {
765 if(expectedType == '\0') {
766 OSC_errorMessage =
767 "According to the type tag I expected more arguments.";
768 } else if(*(buf->typeStringPtr) == '\0') {
769 OSC_errorMessage =
770 "According to the type tag I didn't expect any more arguments.";
771 } else {
772 OSC_errorMessage =
773 "According to the type tag I expected an argument of a different type.";
774 printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
777 return 9;
780 ++(buf->typeStringPtr);
783 return 0;
787 int OSC_writeFloatArg(OSCbuf *buf, float arg)
789 int4byte *intp;
791 CheckOverflow(buf, 4);
793 if(CheckTypeTag(buf, 'f')) return 9;
795 /* Pretend arg is a long int so we can use htonl() */
796 intp = ((int4byte *) &arg);
797 *((int4byte *) buf->bufptr) = htonl(*intp);
799 buf->bufptr += 4;
801 buf->gettingFirstUntypedArg = 0;
803 return 0;
807 int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args)
809 int i;
810 int4byte *intp;
812 CheckOverflow(buf, 4 * numFloats);
814 /* Pretend args are long ints so we can use htonl() */
815 intp = ((int4byte *) args);
817 for(i = 0; i < numFloats; i++) {
818 if(CheckTypeTag(buf, 'f')) return 9;
819 *((int4byte *) buf->bufptr) = htonl(intp[i]);
820 buf->bufptr += 4;
823 buf->gettingFirstUntypedArg = 0;
825 return 0;
829 int OSC_writeIntArg(OSCbuf *buf, int4byte arg)
831 CheckOverflow(buf, 4);
832 if(CheckTypeTag(buf, 'i')) return 9;
834 *((int4byte *) buf->bufptr) = htonl(arg);
835 buf->bufptr += 4;
837 buf->gettingFirstUntypedArg = 0;
838 return 0;
842 int OSC_writeStringArg(OSCbuf *buf, char *arg)
844 int len;
846 if(CheckTypeTag(buf, 's')) return 9;
848 len = OSC_effectiveStringLength(arg);
850 if(buf->gettingFirstUntypedArg && arg[0] == ',') {
851 /* This un-type-tagged message starts with a string
852 that starts with a comma, so we have to escape it
853 (with a double comma) so it won't look like a type
854 tag string. */
856 CheckOverflow(buf, len+4); /* Too conservative */
857 buf->bufptr +=
858 OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
859 } else {
860 CheckOverflow(buf, len);
861 buf->bufptr += OSC_padString(buf->bufptr, arg);
864 buf->gettingFirstUntypedArg = 0;
866 return 0;
870 /* String utilities */
872 static int strlen(char *s) {
873 int i;
874 for(i=0; s[i] != '\0'; i++);
875 return i;
879 #define STRING_ALIGN_PAD 4
880 int OSC_effectiveStringLength(char *string)
882 int len = strlen(string) + 1; /* We need space for the null char. */
884 /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
885 if((len % STRING_ALIGN_PAD) != 0) {
886 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
889 return len;
893 static int OSC_padString(char *dest, char *str)
895 int i;
897 for(i = 0; str[i] != '\0'; i++) {
898 dest[i] = str[i];
901 return OSC_WritePadding(dest, i);
905 static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str)
907 int i;
909 dest[0] = ',';
910 for(i = 0; str[i] != '\0'; i++) {
911 dest[i+1] = str[i];
914 return OSC_WritePadding(dest, i+1);
918 static int OSC_WritePadding(char *dest, int i)
920 dest[i] = '\0';
921 i++;
923 for(; (i % STRING_ALIGN_PAD) != 0; i++) {
924 dest[i] = '\0';
927 return i;
931 // end OSC-client.cpp
935 // ACTUAL CODE
938 //chuck networking code
939 #include "util_network.h"
940 #include "util_thread.h"
942 // FROM PLATFORM.H -UDP TRANSMITTER / RECEIVER
944 #if defined(__PLATFORM_WIN32__)
945 #include <winsock.h>
946 #else
947 #include <sys/types.h>
948 #include <sys/socket.h>
949 #include <sys/time.h>
950 #include <unistd.h>
951 #include <netinet/in.h>
952 #include <netinet/tcp.h>
953 #include <arpa/inet.h>
954 #include <netdb.h>
955 #endif
957 #ifdef __MACOSX_CORE__
958 #define SOCKET int
959 #define SOCKADDR_IN struct sockaddr_in
960 #endif
962 #include "stdarg.h"
964 enum udp_stat { UDP_NOINIT, UDP_UNBOUND, UDP_BOUND, UDP_READY, UDP_ERROR, UDP_NUM };
967 /* in the .h so that OSC can subclass it
969 class UDP_Subscriber {
970 virtual void onRecieve( char * mesg, int mesgLen ) = 0;
971 virtual bool subscribe( int port );
972 virtual bool unsubscribe();
973 virtual int& port(); //get/set the value of the subscriber's current port.
978 class DefUDP_Subscriber : public UDP_Subscriber {
979 public:
980 int _port;
981 void onReceive ( char * mesg, int mesgLen ) {} // ignore
982 int& port() { return _port; }
985 class UDP_Port_Listener {
986 private:
987 UDP_Receiver* m_in;
988 bool m_port;
990 XThread* m_thread;
991 XMutex* m_mutex;
993 char m_inbuf[OSCINBUFSIZE];
994 int m_inbufsize;
996 vector < UDP_Subscriber * > m_subscribers;
997 queue < UDP_Subscriber * > m_free;
999 public:
1000 UDP_Port_Listener( int port );
1001 ~UDP_Port_Listener();
1002 void init();
1003 bool bind_to_port(int port);
1004 void close();
1005 bool listen();
1006 int recv_mesg();
1007 bool add ( UDP_Subscriber * );
1008 bool drop ( UDP_Subscriber * );
1009 int nsubs();
1011 bool listening;
1017 class UDP_Port_Manager {
1019 private:
1021 static UDP_Port_Manager* _inst;
1022 map < int, UDP_Port_Listener* > _listeners;
1024 public:
1026 static UDP_Port_Manager* instance();
1027 UDP_Port_Manager();
1028 void init();
1029 bool subscribe ( UDP_Subscriber * sub, int port );
1030 bool unsubscribe ( UDP_Subscriber * sub );
1036 class UDP_Receiver {
1038 protected:
1039 ck_socket _sock;
1040 udp_stat _status;
1042 SOCKADDR_IN _remote_addr;
1043 int _remote_addr_len;
1044 int _mesgLen;
1046 public:
1048 UDP_Receiver();
1050 ~UDP_Receiver() { }
1051 void init();
1052 bool bind_to_port(int port);
1053 int recv_next(char *buffer, int size);
1054 void close_sock();
1055 udp_stat status();
1061 class UDP_Transmitter {
1063 protected:
1065 ck_socket _sock;
1066 SOCKADDR_IN _host_addr;
1067 udp_stat _status;
1069 public:
1071 UDP_Transmitter() {
1072 _status = UDP_NOINIT;
1074 virtual ~UDP_Transmitter() {}
1075 void init();
1077 void set_host(char * hostaddress, int port);
1078 int send(char *buffer, int size);
1079 udp_stat status(void) { return _status; }
1080 void close_sock();
1084 UDP_Port_Manager * UDP_Port_Manager::_inst = NULL;
1085 UDP_Port_Manager * UDP_Port_Manager::instance() {
1086 if(_inst == NULL ) {
1087 _inst = new UDP_Port_Manager();
1088 assert ( _inst );
1090 return _inst;
1093 UDP_Port_Manager::UDP_Port_Manager() {
1094 init();
1097 void
1098 UDP_Port_Manager::init() {
1099 _listeners.clear();
1102 bool
1103 UDP_Port_Manager::subscribe ( UDP_Subscriber * sub, int port ) {
1104 if( _listeners.count( port ) == 0 ) {
1105 EM_log(CK_LOG_INFO, "PortManager: starting Listener on %d", port );
1106 _listeners[port] = new UDP_Port_Listener( port ); //make a new listener on this port
1108 return _listeners[port]->add( sub );
1111 bool
1112 UDP_Port_Manager::unsubscribe( UDP_Subscriber * sub ) {
1113 if( sub->port() < 0 ) {
1114 EM_log( CK_LOG_INFO, "error, subscriber's port < 0, return false" );
1115 return false;
1117 if( _listeners.count( sub->port() ) == 0 ) {
1118 EM_log( CK_LOG_INFO, "error, cannot unsubscribe: port %d not in use", sub->port() );
1119 return false;
1121 else {
1122 int pp = sub->port();
1123 UDP_Port_Listener* listener = _listeners[pp];
1124 bool ret = listener->drop( sub );
1125 //check empty
1126 if( listener->nsubs() == 0 ) {
1127 EM_log( CK_LOG_INFO, "PortManager: Listener on port %d is empty - removing", sub->port() );
1128 delete listener;
1129 _listeners.erase( pp );
1131 return ret;
1136 UDP_Port_Listener::UDP_Port_Listener( int port ) :
1137 m_inbufsize( OSCINBUFSIZE ),
1138 listening( false )
1140 init();
1141 m_in->bind_to_port( port );
1142 listen();
1145 UDP_Port_Listener::~UDP_Port_Listener() {
1146 //fprintf(stderr , "port listener destructor\n");
1147 close();
1148 // usleep( 10 ); // do we need this ?
1149 delete m_in;
1150 delete m_mutex;
1151 delete m_thread;
1154 void
1155 UDP_Port_Listener::init() {
1156 memset( (void*)m_inbuf, '\0', m_inbufsize * sizeof(char) );
1157 m_thread = new XThread();
1158 m_mutex = new XMutex();
1159 m_in = new UDP_Receiver();
1160 m_in->init();
1164 UDP_Port_Listener::nsubs() { return m_subscribers.size(); }
1166 bool
1167 UDP_Port_Listener::add( UDP_Subscriber * sub ) {
1168 m_mutex->acquire();
1169 if( find( m_subscribers.begin(), m_subscribers.end(), sub ) == m_subscribers.end() ) {
1170 EM_log(CK_LOG_INFO, "UDP_Port_Listener: adding subscriber" );
1171 m_subscribers.push_back( sub );
1172 sub->port() = m_port;
1173 m_mutex->release();
1174 return true;
1176 else {
1177 EM_log(CK_LOG_INFO, "UDP_Port_Listener::add - error subscriber already exists" );
1178 m_mutex->release();
1179 return false;
1184 bool
1185 UDP_Port_Listener::drop( UDP_Subscriber * sub ) {
1187 m_mutex->acquire();
1188 vector < UDP_Subscriber * >::iterator m_iter = find ( m_subscribers.begin(), m_subscribers.end(), sub );
1189 if( m_iter != m_subscribers.end() ) {
1190 EM_log(CK_LOG_INFO, "UDP_Port_Listener: dropping subscriber" );
1191 m_subscribers.erase( m_iter );
1192 sub->port() = -1;
1193 m_mutex->release();
1194 return true;
1196 else {
1197 EM_log(CK_LOG_INFO, "UDP_Port_Listener::add - error subscriber already exists" );
1198 m_mutex->release();
1199 return false;
1204 THREAD_RETURN ( THREAD_TYPE udp_port_listener_thread ) ( void * data )
1206 UDP_Port_Listener * upl = (UDP_Port_Listener *) data;
1208 // priority boost
1209 if( Chuck_VM::our_priority != 0x7fffffff )
1210 Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );
1212 EM_log( CK_LOG_INFO, "UDP_Port_Listener:: starting receive loop\n" );
1213 int mLen;
1214 do {
1215 mLen = upl->recv_mesg();
1216 usleep( 10 );
1217 } while( mLen != 0 );
1219 EM_log( CK_LOG_INFO, "UDP_Port_Listener:: receive loop terminated\n" );
1221 return (THREAD_RETURN)0;
1226 // returns whether an attempt to start the listening thread
1227 // was made.
1228 bool
1229 UDP_Port_Listener::listen() {
1230 if( !listening && m_in->status() != UDP_ERROR ) {
1231 listening = true;
1232 m_thread->start( udp_port_listener_thread, (void*) this );
1233 return true;
1235 return false;
1238 bool
1239 UDP_Port_Listener::bind_to_port(int port) {
1240 return m_in->bind_to_port( port );
1243 void
1244 UDP_Port_Listener::close() {
1245 if( m_in->status() == UDP_BOUND ) {
1246 listening = false;
1247 m_in->close_sock();
1252 UDP_Port_Listener::recv_mesg() {
1253 int mLen = m_in->recv_next( m_inbuf, m_inbufsize );
1255 if( mLen == 0 ) {
1256 EM_log( CK_LOG_INFO, "recvLen 0 on socket, returning 0" );
1257 return 0;
1260 m_mutex->acquire();
1261 vector<UDP_Subscriber *>::size_type i;
1262 for( i = 0 ; i < m_subscribers.size(); i++ ) {
1263 m_subscribers[i]->onReceive( m_inbuf, mLen );
1265 m_mutex->release();
1267 return mLen;
1271 // UDP_Subscriber
1272 bool
1273 UDP_Subscriber::subscribe( int p ) {
1274 if( port() >= 0 ) return false; //already subscribed
1275 else if( UDP_Port_Manager::instance()->subscribe( this, p ) )
1277 port() = p;
1278 return true;
1280 else
1282 port() = -1;
1283 return false;
1287 bool
1288 UDP_Subscriber::unsubscribe() {
1289 if( port() < 0 ) return false; //currently unsubscribed
1290 else if( UDP_Port_Manager::instance()->unsubscribe( this ) ) {
1291 port() = -1;
1292 return true;
1294 else {
1295 return false; //could not unsubscribe?
1301 UDP_Receiver::UDP_Receiver()
1303 _status = UDP_NOINIT;
1307 void
1308 UDP_Receiver::init()
1310 //open port
1311 _sock = ck_udp_create();
1312 _status = ( _sock != NULL ) ? UDP_UNBOUND : UDP_ERROR;
1315 bool
1316 UDP_Receiver::bind_to_port(int port)
1318 // Fill in the interface information
1319 _status = ( ck_bind ( _sock, port ) ) ? UDP_BOUND : UDP_ERROR ;
1320 if( _status == UDP_ERROR ) {
1321 EM_log( CK_LOG_SYSTEM, "(via OSC): cannot bind to port %d!", port);
1322 return false;
1325 return true;
1328 udp_stat
1329 UDP_Receiver::status() { return _status; }
1332 UDP_Receiver::recv_next(char * buffer, int bsize)
1334 if( _status != UDP_BOUND )
1336 EM_log( CK_LOG_SYSTEM, "(via OSC): recv -> socket not bound!"); return 0;
1339 _remote_addr_len = sizeof(_remote_addr);
1340 int ret = ck_recvfrom(_sock, buffer, bsize, (struct sockaddr *) &_remote_addr, &_remote_addr_len );
1342 return ( ret <= 0 ) ? 0 : ret;
1346 void
1347 UDP_Receiver::close_sock() {
1348 ck_close ( _sock );
1349 _status = UDP_NOINIT;
1353 void
1354 UDP_Transmitter::init() {
1355 //open socket
1356 _sock = ck_udp_create();
1357 _status = ( _sock != NULL ) ? UDP_READY : UDP_ERROR;
1361 void
1362 UDP_Transmitter::set_host(char * hostaddress, int port) {
1363 // Fill in the interface information
1365 struct hostent * host;
1366 // printf( "gathering host information..." );
1367 _host_addr.sin_family = AF_INET;
1368 _host_addr.sin_port = htons(port);
1369 _host_addr.sin_addr.s_addr = inet_addr(hostaddress);
1371 if(_host_addr.sin_addr.s_addr == INADDR_NONE) // The address wasn't in numeric
1373 host = NULL;
1374 host = gethostbyname(hostaddress); // Get the IP address of the server
1375 if(host == NULL)
1377 fprintf( stderr, "[chuck](via OSC): UDP_Transmitter: unknown host: %s\n", hostaddress);
1378 _status = UDP_ERROR;
1379 return;
1381 memcpy(&_host_addr.sin_addr, host->h_addr_list[0], host->h_length);
1382 // printf(" ...set\n");
1384 // else printf(" ...set\n");
1385 _status = UDP_READY;
1390 UDP_Transmitter::send(char * buffer, int bsize) {
1391 if( _status != UDP_READY )
1393 EM_log( CK_LOG_SYSTEM, "(via OSC): send -> socket not bound!");
1394 return 0;
1396 int ret = ck_sendto(_sock, buffer, bsize, (struct sockaddr *) &_host_addr, sizeof(_host_addr) );
1397 return ( ret <= 0 ) ? 0 : ret ;
1400 void
1401 UDP_Transmitter::close_sock() {
1402 ck_close( _sock );
1406 // OSC_TRANSMITTER
1408 OSC_Transmitter::OSC_Transmitter() {
1409 _out = new UDP_Transmitter();
1410 _holdMessage = false;
1411 init();
1414 OSC_Transmitter::OSC_Transmitter( UDP_Transmitter * out ) {
1415 _out = out;
1416 _holdMessage = false;
1419 OSC_Transmitter::~OSC_Transmitter() { delete _out; }
1421 void
1422 OSC_Transmitter::init() {
1423 if( _out->status() == UDP_NOINIT ) _out->init();
1424 OSC_initBuffer(&_osc, sizeof(_buffer), _buffer );
1427 void
1428 OSC_Transmitter::setHost( char * hadd, int p ) {
1429 _out->set_host(hadd, p);
1432 void
1433 OSC_Transmitter::presend( char * buf, int sz ) {
1434 _out->send(buf,sz);
1437 void
1438 OSC_Transmitter::openBundle( OSCTimeTag t) {
1439 OSC_openBundle( &_osc, t);
1443 void
1444 OSC_Transmitter::closeBundle() {
1445 OSC_closeBundle( &_osc );
1446 tryMessage();
1450 void
1451 OSC_Transmitter::addMessage( char *address, char * args, ...)
1453 if( args == NULL || args[0] == '\0' ) { // if there's no text
1454 OSC_writeAddress( &_osc, address ); // nothing
1455 return;
1458 va_list tags; // pointer to list of arguments
1459 va_start(tags, args); // parses the string for variables
1461 OSC_writeAddressAndTypes( &_osc, address, args );
1463 int argnum = strlen(args);
1464 int osc_err = 0;
1465 for( int j = 1; !osc_err && j < argnum; j++ ) {
1466 switch ( args[j] ) {
1467 case 'i':
1468 osc_err = OSC_writeIntArg ( &_osc, va_arg(tags, int) );
1469 break;
1470 case 'f':
1471 osc_err = OSC_writeFloatArg ( &_osc, va_arg(tags, double) );
1472 break;
1473 case 's':
1474 osc_err = OSC_writeStringArg ( &_osc, va_arg(tags, char *) );
1475 break;
1479 if( osc_err ) {
1480 EM_log( CK_LOG_SYSTEM, "(via OSC): error writing packet: %d %s...", osc_err, OSC_errorMessage );
1481 // failure action???
1484 va_end(tags); // Results Are Stored In Text
1485 tryMessage();
1488 void
1489 OSC_Transmitter::startMessage( char * spec ) {
1491 int len = strlen( spec );
1493 char * comma = strchr( spec, ',');
1494 char * space = strchr ( spec, ' ');
1495 int coff = ( comma == NULL ) ? len : comma - spec;
1496 int spoff = ( space == NULL ) ? len : space - spec;
1497 int off = min ( coff, spoff );
1499 if( off < len )
1500 spec[off] = '\0';
1502 startMessage( spec, spec + off + 1 );
1505 void
1506 OSC_Transmitter::startMessage( char * address, char * args )
1508 // OSC_writeAddressAndTypes( &_osc, address, args );
1509 char addrfix[512];
1510 int addrlen = strlen( address );
1511 // int mx = strlen(address) + strlen(args) + 1; // either we need to add a comma to args,
1512 // or it's got junk in it.
1513 // char addrfix[] = new char[mx]; // (char*) malloc( mx * sizeof( char ) );
1514 strcpy ( addrfix, address );
1515 addrfix[addrlen] = '\0';
1516 addrfix[addrlen+1] = ',';
1517 char * argptr = addrfix + (addrlen + 2);
1518 char * p_args = args;
1519 while ( *p_args != '\0' ) {
1520 if( *p_args != ',' && *p_args != ' ' ) {
1521 *argptr = *p_args;
1522 argptr++;
1524 p_args++;
1526 *argptr = '\0';
1528 OSC_writeAddressAndTypes( &_osc, addrfix, addrfix + addrlen + 1); //expects the ',' before spec tag.
1529 // delete[] addrfix;
1530 //free ( (void*)addrfix );
1531 tryMessage();
1534 void
1535 OSC_Transmitter::addInt ( int4byte i ) {
1536 int osc_err = OSC_writeIntArg ( &_osc, i );
1537 if( osc_err ) {
1538 fprintf ( stderr, "[chuck](via OSC): error writing packet: %d %s\n", osc_err, OSC_errorMessage );
1539 //failure action???
1541 tryMessage();
1544 void
1545 OSC_Transmitter::addFloat ( float f ) {
1546 int osc_err = OSC_writeFloatArg ( &_osc, f );
1547 if( osc_err ) {
1548 fprintf ( stderr, "[chuck](via OSC): error writing packet: %d %s\n", osc_err, OSC_errorMessage );
1549 //failure action???
1551 tryMessage();
1554 void
1555 OSC_Transmitter::addString ( char * s ) {
1556 int osc_err = OSC_writeStringArg ( &_osc, s );
1557 if( osc_err ) {
1558 fprintf ( stderr, "[chuck](via OSC): error writing packet: %d %s\n", osc_err, OSC_errorMessage );
1559 //failure action???
1561 tryMessage();
1564 bool
1565 OSC_Transmitter::packetReady() {
1566 if( _holdMessage ) return false; //message hold is on
1567 if( _osc.typeStringPtr ) { //if it's been typed, check that type is complete
1568 if( CheckTypeTag(&_osc, '\0' ) ) return false;
1570 return ( OSC_isBufferDone(&_osc) != 0 );
1573 void
1574 OSC_Transmitter::tryMessage() {
1575 if( !packetReady() ) return;
1577 _out->send( OSC_getPacket(&_osc), OSC_packetSize(&_osc) );
1578 OSC_resetBuffer(&_osc);
1581 void
1582 OSC_Transmitter::holdMessage(bool b) {
1583 _holdMessage = b;
1586 void
1587 OSC_Transmitter::kickMessage() {
1588 if( !OSC_isBufferDone(&_osc) ) {
1589 fprintf(stderr, "[chuck](via OSC): error -> sending incomplete packet!\n");
1591 _out->send( OSC_getPacket(&_osc), OSC_packetSize(&_osc) );
1592 OSC_resetBuffer(&_osc);
1596 // OSC_RECEIVER
1598 OSC_Receiver::OSC_Receiver():
1599 // _listening(false),
1600 // _inbufsize(OSCINBUFSIZE),
1601 _inbox(NULL),
1602 _inbox_size(2),
1603 _started(false),
1604 _in_read(0),
1605 _in_write(1),
1606 _address_space (NULL),
1607 _address_size ( 2 ),
1608 _address_num ( 0 )
1611 _inbox = (OSCMesg*) malloc (sizeof(OSCMesg) * _inbox_size);
1612 for( int i = 0; i < _inbox_size; i++ ) _inbox[i].payload = NULL;
1614 _address_space = (OSC_Address_Space **) realloc ( _address_space, _address_size * sizeof ( OSC_Address_Space * ) );
1616 _io_mutex = new XMutex();
1617 // _io_thread = new XThread();
1619 //_in = new UDP_Receiver();
1621 init();
1625 OSC_Receiver::OSC_Receiver(UDP_Receiver* in) {
1626 // _in = in;
1627 _port = -1;
1630 void
1631 OSC_Receiver::init(){
1632 _port = -1;
1633 // _in->init();
1636 OSC_Receiver::~OSC_Receiver()
1638 stopListening();
1639 for( int i=0; i < _inbox_size; i++ ) {
1640 if( _inbox[i].payload ) {
1641 free ( _inbox[i].payload );
1642 _inbox[i].payload = NULL;
1644 free ( _inbox );
1647 //delete _in;
1650 THREAD_RETURN ( THREAD_TYPE osc_recv_thread ) ( void * data )
1652 OSC_Receiver * oscar = (OSC_Receiver * ) data;
1654 // priority boost
1655 if( Chuck_VM::our_priority != 0x7fffffff )
1656 Chuck_VM::set_priority( Chuck_VM::our_priority, NULL );
1658 do {
1659 oscar->recv_mesg();
1660 usleep( 10 );
1661 }while( true );
1663 return (THREAD_RETURN)0;
1667 int&
1668 OSC_Receiver::port() { return _port; }
1670 void
1671 OSC_Receiver::onReceive( char * mesg, int mesgLen ) {
1672 handle_mesg( mesg, mesgLen );
1675 void
1676 OSC_Receiver::bind_to_port(int port ) {
1677 _tmp_port = port;
1678 // _in->bind_to_port(port);
1681 bool
1682 OSC_Receiver::listen( int port ) {
1683 bind_to_port ( port );
1684 return listen();
1687 void
1688 OSC_Receiver::stopListening() {
1689 unsubscribe();
1692 bool
1693 OSC_Receiver::listen() {
1694 unsubscribe(); //in case we're connected.
1695 return subscribe( _tmp_port );
1697 if( !_listening ) {
1698 _listening = true;
1699 _io_thread->start( osc_recv_thread, (void*)this );
1701 return _listening;
1707 void
1708 OSC_Receiver::close_sock() {
1709 unsubscribe();
1710 // _in->close_sock();
1713 void
1714 OSC_Receiver::recv_mesg() {
1715 // this is when OSC_Receiver was
1716 // used as the port-manager. now this code ( and callback ) are in UDP_Port_Listener interface,
1717 // which OSC_Receiver subclasses
1720 _mesglen = _in->recv_next( _inbuf, _inbufsize );
1721 if( _mesglen > 0 ) {
1722 //parse();
1723 handle_mesg(_inbuf, _mesglen);
1729 bool
1730 OSC_Receiver::has_mesg() {
1731 // EM_log( CK_LOG_FINER, "OSC has message?" );
1732 return ( _started && ( _in_read+1 ) % _inbox_size != _in_write );
1735 bool
1736 OSC_Receiver::get_mesg(OSCMesg* bucket) {
1738 _io_mutex->acquire();
1740 if( has_mesg() ) {
1741 // next write _may_ fuck with _in_read
1742 // where when resizing the buffer...
1743 *bucket = *next_read();
1744 // fprintf(stderr, "r"); //read: %d of %d \n", _in_read, _inbox_size);
1745 _io_mutex->release();
1746 return true;
1749 _io_mutex->release();
1751 return false;
1754 void
1755 OSC_Receiver::parse( char * mesg, int mesgLen ) {
1757 // unpack bundles, dump all messages
1758 // any local prep we need here?
1760 long i = 0;
1761 // log
1762 EM_log( CK_LOG_FINER, "OSC_Receiver: print message length %d", mesgLen );
1763 for( i = 0 ; i < mesgLen; i++ ) {
1764 fprintf(stderr, "\t%c(%0x):", mesg[i], mesg[i]);
1767 fprintf( stderr, "\n" );
1770 void
1771 OSC_Receiver::next_write()
1773 // called by the UDP client ( blocks )
1775 if( !_started ) {
1776 _started = true;
1779 int next = (_in_write+1) % _inbox_size;
1781 if( next == _in_read ) {
1783 // fprintf(stderr, "OSC::need to resize...");
1785 _io_mutex->acquire(); //don't let next read return a bogus pointer
1787 if( _inbox_size < OSCINBOXMAX) {
1789 // LOCK MUTEX (on next_read)
1790 // prevents
1792 // mesgs might move around, but their data doesn't..(this is good)..
1793 // if we return an OSCmesg* to an out-of-thread function, it can expire.
1794 // so we pass in pointer to our own mesg from outside (get_mesg) and copy
1795 // from the current 'read' in the buffer...buffer may then be resized...
1796 // since data buffers do not move, we remain okay.
1798 // perhaps a monolithic chunk of memory is a better option...
1799 // but what if we want to handle multiple messages at once?
1801 // orrr..if we follow timetags and need semirandom access to
1802 // mesg contents for scheduling bundles..hmm.
1804 // make a separate case for scheduled messages...
1805 // throw them into a heap...
1807 // fuck...back to the todo...
1809 int new_size = ( _inbox_size * 2 > OSCINBOXMAX ) ? OSCINBOXMAX : _inbox_size * 2 ;
1811 bool err = false;
1813 // okay. read and write may be anywhere.
1814 if( _in_write > _in_read ) {
1815 // easy case
1816 _inbox = (OSCMesg* ) realloc ((void*)_inbox, new_size * sizeof(*_inbox) );
1817 err = (!_inbox);
1818 // indices are still valid
1820 else {
1821 // write is behind read in the buffer
1822 // copy into buffer so that contents remain contiguous
1823 // note:: copy the buffers between write and read...
1824 // they may have valid packet pointers.......
1826 OSCMesg * new_inbox =(OSCMesg*)malloc ( new_size * sizeof(*new_inbox) );
1827 err = (!new_inbox);
1829 if( !err ) {
1830 int _read_tail = _inbox_size - _in_read;
1831 memcpy( (void*)new_inbox, (void*)(_inbox+_in_read), (_read_tail) * sizeof(*_inbox) );
1832 memcpy( (void*)(new_inbox+_read_tail), (void*)_inbox, (_in_read ) * sizeof(*_inbox) );
1834 // update indices
1835 _in_read = 0;
1836 _in_write = (_in_write + _read_tail);
1838 free ( _inbox );
1839 _inbox = new_inbox;
1842 else err = true;
1846 if( !err ) {
1847 // new inbox elements need their payload pointers init to NULL
1848 for( int i = _inbox_size; i < new_size; i++ ) _inbox[i].payload = NULL;
1850 else {
1851 // fprintf(stderr, "fuck! fucking buffer reallocation error!\n");
1852 exit(0);
1855 next = (_in_write+1)%new_size; //where we're headed..
1856 _inbox_size = new_size;
1858 // fprintf(stderr, "(%d)", _inbox_size);
1859 // UNLOCK MUTEX
1861 else {
1862 // fprintf(stderr, "max buffer...dropping old mesg %d\n", next);
1863 _in_read = (next+1)%_inbox_size;
1866 _io_mutex->release();
1869 _in_write = next;
1873 OSCMesg*
1874 OSC_Receiver::next_read() {
1875 int next = ( _in_read + 1 ) % _inbox_size;
1876 if( next == _in_write ) return NULL; // can't intrude on write
1878 _in_read = next; //advance
1879 OSCMesg* ret= _inbox + _in_read; // return this pointer
1880 return ret;
1883 void
1884 OSC_Receiver::set_mesg(OSCMesg* mrp, char * buf, int len ) {
1886 // put pointers in the appropriate places
1887 // this means that mrp has no idea whether
1888 // its pointers refer to its own payload
1889 // or to an external buffer
1891 mrp->len = len; //total size of message
1892 mrp->address = buf;
1893 mrp->types = mrp->address + strlen(mrp->address) + 4 - strlen(mrp->address)%4;
1894 if( mrp->types[0] == ',') {
1895 // typed message
1896 mrp->data= mrp->types + strlen(mrp->types) + 4 - strlen(mrp->types)%4;
1898 else {
1899 // untyped message.
1900 // should there be a warning?
1901 // classes that handle mesgs
1902 // should take care of that.
1903 mrp->data = mrp->types;
1904 mrp->types = NULL;
1909 void
1910 OSC_Receiver::handle_mesg( char * buf, int len )
1912 // this is called sequentially by the receiving thread.
1913 if( buf[0] == '#' ) { handle_bundle( buf, len ); return; }
1915 OSCMesg * mrp = write();
1917 if( mrp->payload == NULL ) {
1918 mrp->payload = (char *)malloc( OSCINBUFSIZE * sizeof(char) );
1919 // fprintf(stderr, "oscrecv:mallocing %d bytes\n", OSCINBUFSIZE);
1922 memcpy( (void*)mrp->payload, (const void*)buf, len ); // copy data from buffer to message payload
1923 set_mesg( mrp, mrp->payload, len ); // set pointers for the message to its own payload
1924 mrp->recvtime = 0.000; // GetTime(); // set message time
1926 distribute_message( mrp ); // copy message to any & all matching address spaces
1928 // the distribute message will copy any necessary data into the addr object's private queue.
1929 // so we don't need to buffer here.. ( totally wasting the kick-ass expanding buffer i have in this class...drat )
1931 // next_write();
1934 void
1935 OSC_Receiver::handle_bundle(char*b, int len) {
1937 //no scheduling for now
1938 //just immediately unpack everything
1940 //fprintf(stderr, "bundle (length %d)\n", len);
1942 int off = 16; //skip "#bundle\0timetags"
1944 while ( off < len )
1946 char * z = b+off;
1947 unsigned long size = ntohl(*((unsigned long*)z));
1949 char * m = z+4;
1951 if( m[0] == '#' ) handle_bundle(m,size);
1952 else handle_mesg(m,size);
1954 off += size+4; //beginning of next message
1958 OSC_Address_Space *
1959 OSC_Receiver::new_event ( char * spec) {
1960 OSC_Address_Space * event = new OSC_Address_Space ( spec );
1961 add_address ( event );
1962 return event;
1965 OSC_Address_Space *
1966 OSC_Receiver::new_event ( char * addr, char * type) {
1967 OSC_Address_Space * event = new OSC_Address_Space ( addr, type );
1968 add_address ( event );
1969 return event;
1973 void
1974 OSC_Receiver::add_address ( OSC_Address_Space * src ) {
1975 if( _address_num == _address_size ) {
1976 _address_size *= 2;
1977 _address_space = (OSC_Address_Space **) realloc ( _address_space, _address_size * sizeof( OSC_Address_Space **));
1979 _address_space[_address_num++] = src;
1980 src->setReceiver(this);
1983 void
1984 OSC_Receiver::remove_address ( OSC_Address_Space *odd ) {
1985 for( int i = 0 ; i < _address_num ; i++ ) {
1986 while ( _address_space[i] == odd ) {
1987 _address_space[i] = _address_space[--_address_num];
1993 This function distributes each message to a matching address inside the
1994 chuck shred. There are some issues with this.
1995 bundle simultaneity might be solved via mutex?
1999 void
2000 OSC_Receiver::distribute_message( OSCMesg * msg ) {
2001 for( int i = 0 ; i < _address_num ; i++ ) {
2002 if( _address_space[i]->try_queue_mesg( msg ) ) {
2003 // fprintf ( stderr, "broadcasting %x from %x\n", (uint)_address_space[i]->SELF, (uint)_address_space[i] );
2004 // if the event has any shreds queued, fire them off..
2005 ( (Chuck_Event *) _address_space[i]->SELF )->queue_broadcast();
2011 // OSC SOURCE ( Parser )
2012 // rename to OSC_address ?
2014 // this is an OSC_Address_Space - we register it to a particular receiver
2015 // the receiver matches an incoming message against registered
2016 // address and sends the message to all that match.
2018 // OSCMesg may still have pointers to a mysterious void.
2019 // we should copy values locally for string and blob.
2021 // public for of inherited chuck_event mfunc.
2023 char *osc_typename_strings[] = {
2024 "untyped",
2025 "no arguments",
2026 "integer",
2027 "float",
2028 "string",
2029 "blob",
2030 "ERROR: num types exceeded"
2035 OSC_Address_Space::OSC_Address_Space() {
2036 init();
2037 setSpec( "/undefined/default,i" );
2041 OSC_Address_Space::OSC_Address_Space( char * spec ) {
2042 init();
2043 setSpec( spec );
2046 OSC_Address_Space::OSC_Address_Space( char * addr, char * types) {
2047 init();
2048 setSpec( addr, types );
2051 void
2052 OSC_Address_Space::init() {
2053 _receiver = NULL;
2054 SELF = NULL;
2055 _queueSize = 512; // start queue size at 512 // 64.
2056 _dataSize = 0;
2057 _cur_mesg = NULL;
2058 _queue = NULL;
2059 _cur_value = 0;
2060 _current_data = NULL;
2061 _buffer_mutex = new XMutex();
2064 OSC_Address_Space::~OSC_Address_Space() {
2065 if( _queue ) free ( _queue );
2068 void
2069 OSC_Address_Space::setReceiver(OSC_Receiver * recv) {
2070 _receiver = recv;
2073 void
2074 OSC_Address_Space::setSpec( char *addr, char * types ) {
2075 strncpy ( _spec, addr, 512 );
2076 strncat ( _spec, "," , 512);
2077 strncat ( _spec, types, 512 );
2078 scanSpec();
2079 _needparse = true;
2080 parseSpec();
2083 void
2084 OSC_Address_Space::setSpec( char *c ) {
2085 strncpy ( _spec, c, 512);
2086 scanSpec();
2087 _needparse = true;
2088 parseSpec();
2091 void
2092 OSC_Address_Space::scanSpec() { //this allows for sloppy-ish definitions in type string
2093 //assumes that a potential spec is already in _spec;
2094 char * pread;
2095 char * pwrite;
2096 pread = pwrite = (char*)_spec;
2097 bool in_type = false;
2098 while ( *pread != '\0' ) {
2099 if( *pread == ',' || *pread == ' ' ) {
2100 if( !in_type ) {
2101 in_type = true;
2102 *pwrite = ',';
2103 pwrite++;
2104 } // otherwise, we ignore
2105 else if( *pread == ' ' ) {
2106 EM_log(CK_LOG_INFO, "OSC-Address-Space: spaces in OSC type tag string! ignoring");
2109 else {
2110 if( pwrite != pread ) { *pwrite = *pread; }
2111 pwrite++;
2113 pread++;
2115 if( !in_type ) {
2116 //no type args found, add a comma to indicate a zero-arg string.
2117 *(pwrite++) = ',';
2119 *pwrite = '\0'; //if pread terminates, so does pwrite.
2122 void
2123 OSC_Address_Space::parseSpec() {
2125 if( !_needparse ) return;
2127 char * type = strrchr(_spec, ',');
2128 if( !type ) return;
2130 *type = '\0'; //null the address
2131 type++; //point to type string
2133 strcpy ( _address, _spec );
2134 strcpy ( _type , type );
2136 // fprintf(stderr," parsing spec- address %s :: type %s\n", _address, _type);
2138 int n = strlen ( type );
2139 _noArgs = ( n == 0 );
2140 resizeData( ( n < 1 ) ? 1 : n );
2141 _qread = 0;
2142 _qwrite = 1;
2144 _needparse = false;
2147 void
2148 OSC_Address_Space::resizeQueue( int n )
2150 if( n <= _queueSize )
2151 return; // only grows
2153 // lock
2154 _buffer_mutex->acquire();
2156 // it's possible that between the test above and now,
2157 // qread has moved on and we actually DO have space..
2159 EM_log( CK_LOG_INFO, "OSC_Address (%s) -- buffer full ( r:%d , w:%d, of %d(x%d) ), resizing...",
2160 _address, _qread, _qwrite, _queueSize, _dataSize );
2161 // fprintf( stderr, "--- hasMesg ( %d ) nextMesg ( %d )\n", (int) has_mesg(), (int)next_mesg() );
2163 // we're the server... all we know is that the contents of qread are in the current_buffer,
2164 // so we can move the data, but we don't want to move ahead and lose it just yet.
2166 // compute chunk size
2167 size_t chunkSize = _dataSize * sizeof( opsc_data );
2169 // allocate
2170 int _newQSize = n;
2171 opsc_data * _new_queue = (opsc_data *)malloc( _newQSize * chunkSize );
2173 // clear
2174 memset( _new_queue, 0, _newQSize * chunkSize ); // out with the old...
2175 // copy
2176 if( _qread < _qwrite )
2178 // we're doing this because qwrite is out of room.
2179 // so if qwrite is already greater than qread,
2180 // just copy the whole thing to the start of the new buffer ( adding more space to the end )
2181 memcpy( (void*)_new_queue, (const void*)_queue, _queueSize * chunkSize);
2182 // _qwrite and _qread can stay right where they are.
2183 // fprintf(stderr, "resize - case 1\n");
2185 else
2187 // _qread is in front of _qwrite, so we must unwrap, and place _qread at the
2188 // front of the queue, and qwrite at the end, preserving all elements that qread
2189 // is waiting to consume.
2190 int nread = _queueSize - _qread;
2191 memcpy( (void*)_new_queue,
2192 (const void*)(_queue + _qread * _dataSize),
2193 (nread) * chunkSize);
2194 memcpy( (void*)(_new_queue + nread * _dataSize),
2195 (const void*)_queue,
2196 (_qread) * _dataSize * sizeof( opsc_data ));
2197 _qread = 0;
2198 _qwrite += nread;
2199 // EM_log(CK_LOG_INFO, "resize - case 2\n");
2202 _queueSize = _newQSize;
2203 opsc_data * trash = _queue;
2204 _queue = _new_queue;
2205 free ( (void*)trash );
2207 // don't move qread or qwrite until we're done.
2208 _buffer_mutex->release();
2212 void
2213 OSC_Address_Space::resizeData( int n ) {
2214 if( _dataSize == n ) return;
2215 _dataSize = n;
2216 int queueLen = _queueSize * _dataSize * sizeof( opsc_data );
2217 _queue = ( opsc_data * ) realloc ( _queue, queueLen );
2218 memset ( _queue, 0, queueLen );
2219 _current_data = (opsc_data* ) realloc ( _current_data, _dataSize * sizeof( opsc_data) );
2223 bool
2224 OSC_Address_Space::message_matches( OSCMesg * m ) {
2226 //this should test for type as well.
2228 bool addr_match;
2229 if( strcmp ( m->address, _address ) == 0 ) addr_match = true;
2230 else addr_match = PatternMatch( m->address, _address);
2231 if( !addr_match ) return false;
2233 //address AND type must match
2234 //but there should be an option for the blank 'information about this' pattern
2236 char * type = m->types+1;
2237 if( m->types == NULL || strcmp( _type , type ) != 0 ) {
2238 // if( type )
2239 // fprintf(stderr, "error, mismatched type string( %s ) vs ( %s ) \n", _type, type ) ;
2240 // else
2241 // fprintf( stderr, "error, missing type string (expecting %s) \n", _type );
2242 return false;
2244 return true;
2248 bool
2249 OSC_Address_Space::try_queue_mesg( OSCMesg * m )
2251 if( !message_matches( m ) ) return false;
2252 queue_mesg( m );
2253 return true;
2258 bool
2259 OSC_Address_Space::has_mesg() {
2260 // EM_log( CK_LOG_FINER, "OSC has mesg" );
2261 return ( ( _qread + 1 ) % _queueSize != _qwrite );
2265 bool
2266 OSC_Address_Space::next_mesg()
2268 if( has_mesg() )
2270 _buffer_mutex->acquire();
2272 if( !has_mesg() ) return false;
2274 // move qread forward
2275 _qread = ( _qread + 1 ) % _queueSize;
2276 memcpy( _current_data, _queue + _qread * _dataSize, _dataSize * sizeof( opsc_data ) );
2277 _cur_mesg = _current_data;
2278 _cur_value = 0;
2280 _buffer_mutex->release();
2282 return true;
2285 return false;
2288 bool
2289 OSC_Address_Space::vcheck( osc_datatype tt ) {
2291 if( !_cur_mesg ) {
2292 EM_log( CK_LOG_SEVERE, "OscEvent: getVal(): nextMsg() must be called before reading data..." );
2293 return false;
2295 else if( _cur_value < 0 || _cur_value >= _dataSize ) {
2296 EM_log( CK_LOG_SEVERE, "OscEvent: read position %d outside message ...", _cur_value );
2297 return false;
2299 else if( _cur_mesg[_cur_value].t != tt ) {
2300 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] );
2301 return false;
2304 return true;
2307 int4byte
2308 OSC_Address_Space::next_int() {
2309 return ( vcheck(OSC_INT) ) ? _cur_mesg[_cur_value++].i : 0 ;
2312 float
2313 OSC_Address_Space::next_float() {
2314 return ( vcheck(OSC_FLOAT) ) ? _cur_mesg[_cur_value++].f : 0.0 ;
2317 char *
2318 OSC_Address_Space::next_string() {
2319 return ( vcheck(OSC_STRING) ) ? _cur_mesg[_cur_value++].s : NULL ;
2322 char *
2323 OSC_Address_Space::next_string_dup() {
2324 if( !vcheck(OSC_STRING) ) return NULL;
2325 char * alt_c = _cur_mesg[_cur_value++].s;
2326 char * dup_c = (char * ) malloc ( (strlen ( alt_c )+1 ) * sizeof(char) );
2327 strcpy ( dup_c, alt_c );
2328 return dup_c;
2331 char *
2332 OSC_Address_Space::next_blob() {
2333 return ( vcheck(OSC_BLOB) ) ? _cur_mesg[_cur_value++].s : NULL ;
2336 void
2337 OSC_Address_Space::queue_mesg( OSCMesg * m )
2339 // in the server thread.
2340 int nqw = ( _qwrite + 1 ) % _queueSize;
2341 EM_log( CK_LOG_FINE, "OSC address(%s): read: %d write: %d size: %d", _address, _qread, _qwrite, _queueSize );
2343 if( nqw == _qread ) {
2344 if( _queueSize < OSC_ADDRESS_QUEUE_MAX ) {
2345 resizeQueue( _queueSize * 2 );
2346 nqw = ( _qwrite + 1 ) % _queueSize; // _qwrite, _qread may have changed.
2348 else {
2349 EM_log( CK_LOG_INFO, "OSC_Address_Space(%s): message queue reached max size %d...", _address, _queueSize );
2350 EM_log( CK_LOG_INFO, "...(dropping oldest message %d)", _qread );
2352 // bump!
2353 _buffer_mutex->acquire();
2354 _qread = ( _qread + 1 ) % _queueSize;
2355 _buffer_mutex->release();
2359 _vals = _queue + _qwrite * _dataSize;
2361 if( _noArgs ) { // if address takes no arguments,
2362 _vals[0].t = OSC_NOARGS;
2364 else {
2365 char * type = m->types+1;
2366 char * data = m->data;
2368 unsigned int endy;
2369 int i=0;
2371 float *fp;
2372 int *ip;
2373 int clen;
2374 while ( *type != '\0' ) {
2375 switch ( *type ) {
2376 case 'f':
2377 endy = ntohl(*((unsigned long*)data));
2378 fp = (float*)(&endy);
2379 _vals[i].t = OSC_FLOAT;
2380 _vals[i].f = *fp;
2381 data += 4;
2382 break;
2383 case 'i':
2384 endy = ntohl(*((unsigned long*)data));
2385 ip = (int4byte*)(&endy);
2386 _vals[i].t = OSC_INT;
2387 _vals[i].i = *ip;
2388 data += 4;
2389 break;
2390 case 's':
2391 // string
2392 clen = strlen(data) + 1; // terminating!
2393 _vals[i].t = OSC_STRING;
2394 _vals[i].s = (char *) realloc ( _vals[i].s, clen * sizeof(char) );
2395 memcpy ( _vals[i].s, data, clen ); // make a copy of the data...
2396 // fprintf(stderr, "add string |%s| ( %d ) \n", _vals[i].s, clen );
2397 data += (((clen-1) >> 2) + 1) << 2;
2398 // data += clen + 4 - clen % 4;
2399 break;
2400 case 'b':
2401 // blobs
2402 endy = ntohl(*((unsigned long*)data));
2403 clen = *((int*)(&endy));
2404 _vals[i].t = OSC_BLOB;
2405 _vals[i].s = (char* ) realloc ( _vals[i].s, clen * sizeof(char) );
2406 memcpy ( _vals[i].s, data, clen );
2407 data += clen + 4 - clen % 4;
2408 break;
2410 i++;
2411 type++;
2415 _qwrite = nqw;
2417 //review
2419 for( i=0; i < _nvals; i++ ) {
2420 fprintf(stderr, "%d %f : ", i, _val[i] );
2422 fprintf(stderr, "\n");