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
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: util_opsc.cpp
29 // author: Philip L. Davidson (philipd@alumni.princeton.edu)
30 // Ge Wang (gewang@cs.princeton.edu)
31 // Perry R. Cook (prc@cs.princeton.edu)
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"
47 // FROM PLATFORM.H -UDP TRANSMITTER / RECEIVER
49 #if defined(__PLATFORM_WIN32__)
52 #include <sys/types.h>
53 #include <sys/socket.h>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <arpa/inet.h>
62 #if defined(__MACOSX_CORE__)
64 #define SOCKADDR_IN struct sockaddr_in
65 #elif !defined(SOCKADDR_IN)
67 #define SOCKADDR_IN struct sockaddr_in
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).
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
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 ) {
127 if(pattern
[0] == '*')
128 return PatternMatch (pattern
+1,test
);
135 case 0 : return test
[0] == 0;
136 case '?' : return PatternMatch (pattern
+ 1, test
+ 1);
138 if( PatternMatch (pattern
+1, test
) ) {
141 return PatternMatch (pattern
, test
+1);
145 fprintf( stderr
, "[chuck](via OSC): spurious %c in pattern \".../%s/...\"\n", pattern
[0], theWholePattern
);
148 return MatchBrackets (pattern
,test
);
150 return MatchList (pattern
,test
);
152 if(pattern
[1] == 0) {
154 } else if(pattern
[1] == test
[0]) {
155 return PatternMatch (pattern
+2,test
+1);
160 if(pattern
[0] == test
[0]) {
161 return PatternMatch (pattern
+1,test
+1);
169 /* we know that pattern[0] == '[' and test[0] != 0 */
171 static bool MatchBrackets( const char * pattern
, const char * test
)
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
);
182 if(pattern
[1] == '!') {
189 fprintf( stderr
,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern
);
193 if(p
[1] == '-' && p
[2] != 0) {
194 if(test
[0] >= p
[0] && test
[0] <= p
[2]) {
200 if(p
[0] == test
[0]) {
216 fprintf( stderr
,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern
);
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
);
237 restOfPattern
++; /* skip close curly brace */
239 pattern
++; /* skip open curly brace */
243 if(*pattern
== ',') {
244 if(PatternMatch (restOfPattern
, tp
)) {
250 } else if(*pattern
== '}') {
251 return PatternMatch (restOfPattern
, tp
);
252 } else if(*pattern
== *tp
) {
257 while (*pattern
!= ',' && *pattern
!= '}') {
260 if(*pattern
== ',') {
267 // end OSC-pattern-match.h
273 Copyright (c) 1998. The Regents of the University of California (Regents).
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
307 Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
310 //#include "OSC-timetag.h"
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
)
336 printf("***** OSCTT_Compare(%llx, %llx): %d\n", left
, right
,
337 (left
<right
) ? -1 : ((left
== right
) ? 0 : 1));
341 } else if(left
== right
) {
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) {
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);
370 /* No timezone, no DST version ... */
371 result
= (unsigned) SECONDS_FROM_1900_to_1970
+
372 (unsigned) tv
.tv_sec
;
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); */
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;
404 #else /* Not HAS8BYTEINT */
406 OSCTimeTag
OSCTT_CurrentTime(void) {
413 OSCTimeTag
OSCTT_BiggestPossibleTimeTag(void) {
415 result
.seconds
= 0xffffffff;
416 result
.fraction
= 0xffffffff;
420 OSCTimeTag
OSCTT_Immediately(void) {
427 OSCTimeTag
OSCTT_PlusSeconds(OSCTimeTag original
, float secondsOffset
) {
434 int OSCTT_Compare(OSCTimeTag left
, OSCTimeTag right
) {
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
451 Copyright (c) 1996. The Regents of the University of California (Regents).
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.
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
495 #define DONE 4 /* All open bundles have been closed, so can't write
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
;
513 OSC_resetBuffer(buf
);
516 void OSC_resetBuffer(OSCbuf
*buf
) {
517 buf
->bufptr
= buf
->buffer
;
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
) {
543 OSC_errorMessage
= "Packet has unterminated bundles";
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
);
557 OSC_errorMessage
= "Packet has unterminated bundles";
561 return (buf
->bufptr
- buf
->buffer
);
565 #define CheckOverflow(buf, bytesNeeded) { \
566 if((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
567 OSC_errorMessage = "buffer overflow"; \
572 static void PatchMessageSize(OSCbuf
*buf
)
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";
586 if(buf
->state
== DONE
) {
587 OSC_errorMessage
= "This packet is finished; can't open a new bundle";
591 if(++(buf
->bundleDepth
) >= MAX_BUNDLE_NESTING
) {
592 OSC_errorMessage
= "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
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);
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
;
615 buf
->bufptr
+= OSC_padString(buf
->bufptr
, "#bundle");
617 *((OSCTimeTag
*) buf
->bufptr
) = tt
;
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]);
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
631 int4byte temp
= intp
[0];
638 buf
->bufptr
+= sizeof(OSCTimeTag
);
640 buf
->state
= NEED_COUNT
;
642 buf
->gettingFirstUntypedArg
= 0;
643 buf
->typeStringPtr
= 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!";
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 */
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
;
672 buf
->gettingFirstUntypedArg
= 0;
673 buf
->typeStringPtr
= 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!";
686 if(CheckTypeTag(buf
, '\0')) return 9;
688 while (buf
->bundleDepth
> 0) {
689 OSC_closeBundle(buf
);
692 buf
->typeStringPtr
= 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";
705 if(buf
->state
== DONE
) {
706 OSC_errorMessage
= "This packet is finished; can't write another address";
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
;
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;
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;
739 int OSC_writeAddressAndTypes(OSCbuf
*buf
, char *name
, char *types
)
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;
762 static int CheckTypeTag(OSCbuf
*buf
, char expectedType
)
764 if(buf
->typeStringPtr
) {
765 if(*(buf
->typeStringPtr
) != expectedType
) {
766 if(expectedType
== '\0') {
768 "According to the type tag I expected more arguments.";
769 } else if(*(buf
->typeStringPtr
) == '\0') {
771 "According to the type tag I didn't expect any more arguments.";
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
);
781 ++(buf
->typeStringPtr
);
788 int OSC_writeFloatArg(OSCbuf
*buf
, float arg
)
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
);
802 buf
->gettingFirstUntypedArg
= 0;
808 int OSC_writeFloatArgs(OSCbuf
*buf
, int numFloats
, float *args
)
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
]);
824 buf
->gettingFirstUntypedArg
= 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
);
838 buf
->gettingFirstUntypedArg
= 0;
843 int OSC_writeStringArg(OSCbuf
*buf
, char *arg
)
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
857 CheckOverflow(buf
, len
+4); /* Too conservative */
859 OSC_padStringWithAnExtraStupidComma(buf
->bufptr
, arg
);
861 CheckOverflow(buf
, len
);
862 buf
->bufptr
+= OSC_padString(buf
->bufptr
, arg
);
865 buf
->gettingFirstUntypedArg
= 0;
871 /* String utilities */
873 static int strlen(char *s) {
875 for(i=0; s[i] != '\0'; 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
);
894 static int OSC_padString(char *dest
, const char *str
)
898 for(i
= 0; str
[i
] != '\0'; i
++) {
902 return OSC_WritePadding(dest
, i
);
906 static int OSC_padStringWithAnExtraStupidComma(char *dest
, const char *str
)
911 for(i
= 0; str
[i
] != '\0'; i
++) {
915 return OSC_WritePadding(dest
, i
+1);
919 static int OSC_WritePadding(char *dest
, int i
)
924 for(; (i
% STRING_ALIGN_PAD
) != 0; i
++) {
932 // end OSC-client.cpp
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__)
948 #include <sys/types.h>
949 #include <sys/socket.h>
950 #include <sys/time.h>
952 #include <netinet/in.h>
953 #include <netinet/tcp.h>
954 #include <arpa/inet.h>
958 #ifdef __MACOSX_CORE__
960 #define SOCKADDR_IN struct sockaddr_in
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
{
982 void onReceive ( char * mesg
, int mesgLen
) {} // ignore
983 int& port() { return _port
; }
986 class UDP_Port_Listener
{
994 char m_inbuf
[OSCINBUFSIZE
];
997 vector
< UDP_Subscriber
* > m_subscribers
;
998 queue
< UDP_Subscriber
* > m_free
;
1001 UDP_Port_Listener( int port
);
1002 ~UDP_Port_Listener();
1004 bool bind_to_port(int port
);
1008 bool add ( UDP_Subscriber
* );
1009 bool drop ( UDP_Subscriber
* );
1018 class UDP_Port_Manager
{
1022 static UDP_Port_Manager
* _inst
;
1023 map
< int, UDP_Port_Listener
* > _listeners
;
1027 static UDP_Port_Manager
* instance();
1030 bool subscribe ( UDP_Subscriber
* sub
, int port
);
1031 bool unsubscribe ( UDP_Subscriber
* sub
);
1037 class UDP_Receiver
{
1043 SOCKADDR_IN _remote_addr
;
1044 int _remote_addr_len
;
1053 bool bind_to_port(int port
);
1054 int recv_next(char *buffer
, int size
);
1062 class UDP_Transmitter
{
1067 SOCKADDR_IN _host_addr
;
1073 _status
= UDP_NOINIT
;
1075 virtual ~UDP_Transmitter() {}
1078 void set_host(char * hostaddress
, int port
);
1079 int send(char *buffer
, int size
);
1080 udp_stat
status(void) { return _status
; }
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();
1094 UDP_Port_Manager::UDP_Port_Manager() {
1099 UDP_Port_Manager::init() {
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
);
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" );
1118 if( _listeners
.count( sub
->port() ) == 0 ) {
1119 EM_log( CK_LOG_INFO
, "error, cannot unsubscribe: port %d not in use", sub
->port() );
1123 int pp
= sub
->port();
1124 UDP_Port_Listener
* listener
= _listeners
[pp
];
1125 bool ret
= listener
->drop( sub
);
1127 if( listener
->nsubs() == 0 ) {
1128 EM_log( CK_LOG_INFO
, "PortManager: Listener on port %d is empty - removing", sub
->port() );
1130 _listeners
.erase( pp
);
1137 UDP_Port_Listener::UDP_Port_Listener( int port
) :
1138 m_inbufsize( OSCINBUFSIZE
),
1142 m_in
->bind_to_port( port
);
1146 UDP_Port_Listener::~UDP_Port_Listener() {
1147 //fprintf(stderr , "port listener destructor\n");
1149 // usleep( 10 ); // do we need this ?
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();
1165 UDP_Port_Listener::nsubs() { return m_subscribers
.size(); }
1168 UDP_Port_Listener::add( UDP_Subscriber
* sub
) {
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
;
1178 EM_log(CK_LOG_INFO
, "UDP_Port_Listener::add - error subscriber already exists" );
1186 UDP_Port_Listener::drop( UDP_Subscriber
* sub
) {
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
);
1198 EM_log(CK_LOG_INFO
, "UDP_Port_Listener::add - error subscriber already exists" );
1205 THREAD_RETURN ( THREAD_TYPE udp_port_listener_thread
) ( void * data
)
1207 UDP_Port_Listener
* upl
= (UDP_Port_Listener
*) data
;
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" );
1216 mLen
= upl
->recv_mesg();
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
1230 UDP_Port_Listener::listen() {
1231 if( !listening
&& m_in
->status() != UDP_ERROR
) {
1233 m_thread
->start( udp_port_listener_thread
, (void*) this );
1240 UDP_Port_Listener::bind_to_port(int port
) {
1241 return m_in
->bind_to_port( port
);
1245 UDP_Port_Listener::close() {
1246 if( m_in
->status() == UDP_BOUND
) {
1253 UDP_Port_Listener::recv_mesg() {
1254 int mLen
= m_in
->recv_next( m_inbuf
, m_inbufsize
);
1257 EM_log( CK_LOG_INFO
, "recvLen 0 on socket, returning 0" );
1262 vector
<UDP_Subscriber
*>::size_type i
;
1263 for( i
= 0 ; i
< m_subscribers
.size(); i
++ ) {
1264 m_subscribers
[i
]->onReceive( m_inbuf
, mLen
);
1274 UDP_Subscriber::subscribe( int p
) {
1275 if( port() >= 0 ) return false; //already subscribed
1276 else if( UDP_Port_Manager::instance()->subscribe( this, p
) )
1289 UDP_Subscriber::unsubscribe() {
1290 if( port() < 0 ) return false; //currently unsubscribed
1291 else if( UDP_Port_Manager::instance()->unsubscribe( this ) ) {
1296 return false; //could not unsubscribe?
1302 UDP_Receiver::UDP_Receiver()
1304 _status
= UDP_NOINIT
;
1309 UDP_Receiver::init()
1312 _sock
= ck_udp_create();
1313 _status
= ( _sock
!= NULL
) ? UDP_UNBOUND
: UDP_ERROR
;
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
);
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
;
1348 UDP_Receiver::close_sock() {
1350 _status
= UDP_NOINIT
;
1355 UDP_Transmitter::init() {
1357 _sock
= ck_udp_create();
1358 _status
= ( _sock
!= NULL
) ? UDP_READY
: UDP_ERROR
;
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
1375 host
= gethostbyname(hostaddress
); // Get the IP address of the server
1378 fprintf( stderr
, "[chuck](via OSC): UDP_Transmitter: unknown host: %s\n", hostaddress
);
1379 _status
= UDP_ERROR
;
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!");
1397 int ret
= ck_sendto(_sock
, buffer
, bsize
, (struct sockaddr
*) &_host_addr
, sizeof(_host_addr
) );
1398 return ( ret
<= 0 ) ? 0 : ret
;
1402 UDP_Transmitter::close_sock() {
1409 OSC_Transmitter::OSC_Transmitter() {
1410 _out
= new UDP_Transmitter();
1411 _holdMessage
= false;
1415 OSC_Transmitter::OSC_Transmitter( UDP_Transmitter
* out
) {
1417 _holdMessage
= false;
1420 OSC_Transmitter::~OSC_Transmitter() { delete _out
; }
1423 OSC_Transmitter::init() {
1424 if( _out
->status() == UDP_NOINIT
) _out
->init();
1425 OSC_initBuffer(&_osc
, sizeof(_buffer
), _buffer
);
1429 OSC_Transmitter::setHost( char * hadd
, int p
) {
1430 _out
->set_host(hadd
, p
);
1434 OSC_Transmitter::presend( char * buf
, int sz
) {
1439 OSC_Transmitter::openBundle( OSCTimeTag t
) {
1440 OSC_openBundle( &_osc
, t
);
1445 OSC_Transmitter::closeBundle() {
1446 OSC_closeBundle( &_osc
);
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
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
);
1466 for( int j
= 1; !osc_err
&& j
< argnum
; j
++ ) {
1467 switch ( args
[j
] ) {
1469 osc_err
= OSC_writeIntArg ( &_osc
, va_arg(tags
, int) );
1472 osc_err
= OSC_writeFloatArg ( &_osc
, va_arg(tags
, double) );
1475 osc_err
= OSC_writeStringArg ( &_osc
, va_arg(tags
, char *) );
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
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
);
1503 startMessage( spec
, spec
+ off
+ 1 );
1507 OSC_Transmitter::startMessage( char * address
, char * args
)
1509 // OSC_writeAddressAndTypes( &_osc, address, args );
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
!= ' ' ) {
1529 OSC_writeAddressAndTypes( &_osc
, addrfix
, addrfix
+ addrlen
+ 1); //expects the ',' before spec tag.
1530 // delete[] addrfix;
1531 //free ( (void*)addrfix );
1536 OSC_Transmitter::addInt ( int4byte i
) {
1537 int osc_err
= OSC_writeIntArg ( &_osc
, i
);
1539 fprintf ( stderr
, "[chuck](via OSC): error writing packet: %d %s\n", osc_err
, OSC_errorMessage
);
1546 OSC_Transmitter::addFloat ( float f
) {
1547 int osc_err
= OSC_writeFloatArg ( &_osc
, f
);
1549 fprintf ( stderr
, "[chuck](via OSC): error writing packet: %d %s\n", osc_err
, OSC_errorMessage
);
1556 OSC_Transmitter::addString ( char * s
) {
1557 int osc_err
= OSC_writeStringArg ( &_osc
, s
);
1559 fprintf ( stderr
, "[chuck](via OSC): error writing packet: %d %s\n", osc_err
, OSC_errorMessage
);
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 );
1575 OSC_Transmitter::tryMessage() {
1576 if( !packetReady() ) return;
1578 _out
->send( OSC_getPacket(&_osc
), OSC_packetSize(&_osc
) );
1579 OSC_resetBuffer(&_osc
);
1583 OSC_Transmitter::holdMessage(bool b
) {
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
);
1599 OSC_Receiver::OSC_Receiver():
1600 // _listening(false),
1601 // _inbufsize(OSCINBUFSIZE),
1607 _address_space (NULL
),
1608 _address_size ( 2 ),
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();
1626 OSC_Receiver::OSC_Receiver(UDP_Receiver
* in
) {
1632 OSC_Receiver::init(){
1637 OSC_Receiver::~OSC_Receiver()
1640 for( int i
=0; i
< _inbox_size
; i
++ ) {
1641 if( _inbox
[i
].payload
) {
1642 free ( _inbox
[i
].payload
);
1643 _inbox
[i
].payload
= NULL
;
1651 THREAD_RETURN ( THREAD_TYPE osc_recv_thread
) ( void * data
)
1653 OSC_Receiver
* oscar
= (OSC_Receiver
* ) data
;
1656 if( Chuck_VM::our_priority
!= 0x7fffffff )
1657 Chuck_VM::set_priority( Chuck_VM::our_priority
, NULL
);
1664 return (THREAD_RETURN
)0;
1669 OSC_Receiver::port() { return _port
; }
1672 OSC_Receiver::onReceive( char * mesg
, int mesgLen
) {
1673 handle_mesg( mesg
, mesgLen
);
1677 OSC_Receiver::bind_to_port(int port
) {
1679 // _in->bind_to_port(port);
1683 OSC_Receiver::listen( int port
) {
1684 bind_to_port ( port
);
1689 OSC_Receiver::stopListening() {
1694 OSC_Receiver::listen() {
1695 unsubscribe(); //in case we're connected.
1696 return subscribe( _tmp_port
);
1700 _io_thread->start( osc_recv_thread, (void*)this );
1709 OSC_Receiver::close_sock() {
1711 // _in->close_sock();
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 ) {
1724 handle_mesg(_inbuf, _mesglen);
1731 OSC_Receiver::has_mesg() {
1732 // EM_log( CK_LOG_FINER, "OSC has message?" );
1733 return ( _started
&& ( _in_read
+1 ) % _inbox_size
!= _in_write
);
1737 OSC_Receiver::get_mesg(OSCMesg
* bucket
) {
1739 _io_mutex
->acquire();
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();
1750 _io_mutex
->release();
1756 OSC_Receiver::parse( char * mesg
, int mesgLen
) {
1758 // unpack bundles, dump all messages
1759 // any local prep we need here?
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" );
1772 OSC_Receiver::next_write()
1774 // called by the UDP client ( blocks )
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)
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 ;
1814 // okay. read and write may be anywhere.
1815 if( _in_write
> _in_read
) {
1817 _inbox
= (OSCMesg
* ) realloc ((void*)_inbox
, new_size
* sizeof(*_inbox
) );
1819 // indices are still valid
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
) );
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
) );
1837 _in_write
= (_in_write
+ _read_tail
);
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
;
1852 // fprintf(stderr, "fuck! fucking buffer reallocation error!\n");
1856 next
= (_in_write
+1)%new_size
; //where we're headed..
1857 _inbox_size
= new_size
;
1859 // fprintf(stderr, "(%d)", _inbox_size);
1863 // fprintf(stderr, "max buffer...dropping old mesg %d\n", next);
1864 _in_read
= (next
+1)%_inbox_size
;
1867 _io_mutex
->release();
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
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
1894 mrp
->types
= mrp
->address
+ strlen(mrp
->address
) + 4 - strlen(mrp
->address
)%4;
1895 if( mrp
->types
[0] == ',') {
1897 mrp
->data
= mrp
->types
+ strlen(mrp
->types
) + 4 - strlen(mrp
->types
)%4;
1901 // should there be a warning?
1902 // classes that handle mesgs
1903 // should take care of that.
1904 mrp
->data
= mrp
->types
;
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 )
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"
1948 unsigned long size
= ntohl(*((unsigned long*)z
));
1952 if( m
[0] == '#' ) handle_bundle(m
,size
);
1953 else handle_mesg(m
,size
);
1955 off
+= size
+4; //beginning of next message
1960 OSC_Receiver::new_event ( char * spec
) {
1961 OSC_Address_Space
* event
= new OSC_Address_Space ( spec
);
1962 add_address ( event
);
1967 OSC_Receiver::new_event ( char * addr
, char * type
) {
1968 OSC_Address_Space
* event
= new OSC_Address_Space ( addr
, type
);
1969 add_address ( event
);
1975 OSC_Receiver::add_address ( OSC_Address_Space
* src
) {
1976 if( _address_num
== _address_size
) {
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);
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?
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
[] = {
2031 "ERROR: num types exceeded"
2036 OSC_Address_Space::OSC_Address_Space() {
2038 setSpec( "/undefined/default,i" );
2042 OSC_Address_Space::OSC_Address_Space( const char * spec
) {
2047 OSC_Address_Space::OSC_Address_Space( const char * addr
, const char * types
) {
2049 setSpec( addr
, types
);
2053 OSC_Address_Space::init() {
2056 _queueSize
= 512; // start queue size at 512 // 64.
2061 _current_data
= NULL
;
2062 _buffer_mutex
= new XMutex();
2065 OSC_Address_Space::~OSC_Address_Space() {
2066 if( _queue
) free ( _queue
);
2070 OSC_Address_Space::setReceiver(OSC_Receiver
* recv
) {
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 );
2085 OSC_Address_Space::setSpec( const char *c
) {
2086 strncpy ( _spec
, c
, 512);
2093 OSC_Address_Space::scanSpec() { //this allows for sloppy-ish definitions in type string
2094 //assumes that a potential spec is already in _spec;
2097 pread
= pwrite
= (char*)_spec
;
2098 bool in_type
= false;
2099 while ( *pread
!= '\0' ) {
2100 if( *pread
== ',' || *pread
== ' ' ) {
2105 } // otherwise, we ignore
2106 else if( *pread
== ' ' ) {
2107 EM_log(CK_LOG_INFO
, "OSC-Address-Space: spaces in OSC type tag string! ignoring");
2111 if( pwrite
!= pread
) { *pwrite
= *pread
; }
2117 //no type args found, add a comma to indicate a zero-arg string.
2120 *pwrite
= '\0'; //if pread terminates, so does pwrite.
2124 OSC_Address_Space::parseSpec() {
2126 if( !_needparse
) return;
2128 char * type
= strrchr(_spec
, ',');
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
);
2149 OSC_Address_Space::resizeQueue( int n
)
2151 if( n
<= _queueSize
)
2152 return; // only grows
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
);
2172 opsc_data
* _new_queue
= (opsc_data
*)malloc( _newQSize
* chunkSize
);
2175 memset( _new_queue
, 0, _newQSize
* chunkSize
); // out with the old...
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");
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
));
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();
2214 OSC_Address_Space::resizeData( int n
) {
2215 if( _dataSize
== n
) return;
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
) );
2225 OSC_Address_Space::message_matches( OSCMesg
* m
) {
2227 //this should test for type as well.
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 ) {
2240 // fprintf(stderr, "error, mismatched type string( %s ) vs ( %s ) \n", _type, type ) ;
2242 // fprintf( stderr, "error, missing type string (expecting %s) \n", _type );
2250 OSC_Address_Space::try_queue_mesg( OSCMesg
* m
)
2252 if( !message_matches( m
) ) return false;
2260 OSC_Address_Space::has_mesg() {
2261 // EM_log( CK_LOG_FINER, "OSC has mesg" );
2262 return ( ( _qread
+ 1 ) % _queueSize
!= _qwrite
);
2267 OSC_Address_Space::next_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
;
2281 _buffer_mutex
->release();
2290 OSC_Address_Space::vcheck( osc_datatype tt
) {
2293 EM_log( CK_LOG_SEVERE
, "OscEvent: getVal(): nextMsg() must be called before reading data..." );
2296 else if( _cur_value
< 0 || _cur_value
>= _dataSize
) {
2297 EM_log( CK_LOG_SEVERE
, "OscEvent: read position %d outside message ...", _cur_value
);
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
] );
2309 OSC_Address_Space::next_int() {
2310 return ( vcheck(OSC_INT
) ) ? _cur_mesg
[_cur_value
++].i
: 0 ;
2314 OSC_Address_Space::next_float() {
2315 return ( vcheck(OSC_FLOAT
) ) ? _cur_mesg
[_cur_value
++].f
: 0.0 ;
2319 OSC_Address_Space::next_string() {
2320 return ( vcheck(OSC_STRING
) ) ? _cur_mesg
[_cur_value
++].s
: NULL
;
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
);
2333 OSC_Address_Space::next_blob() {
2334 return ( vcheck(OSC_BLOB
) ) ? _cur_mesg
[_cur_value
++].s
: NULL
;
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.
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
);
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
;
2366 char * type
= m
->types
+1;
2367 char * data
= m
->data
;
2375 while ( *type
!= '\0' ) {
2378 endy
= ntohl(*((unsigned long*)data
));
2379 fp
= (float*)(&endy
);
2380 _vals
[i
].t
= OSC_FLOAT
;
2385 endy
= ntohl(*((unsigned long*)data
));
2386 ip
= (int4byte
*)(&endy
);
2387 _vals
[i
].t
= OSC_INT
;
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;
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;
2420 for( i=0; i < _nvals; i++ ) {
2421 fprintf(stderr, "%d %f : ", i, _val[i] );
2423 fprintf(stderr, "\n");