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"
46 // FROM PLATFORM.H -UDP TRANSMITTER / RECEIVER
48 #if defined(__PLATFORM_WIN32__)
51 #include <sys/types.h>
52 #include <sys/socket.h>
55 #include <netinet/in.h>
56 #include <netinet/tcp.h>
57 #include <arpa/inet.h>
61 #if defined(__MACOSX_CORE__)
63 #define SOCKADDR_IN struct sockaddr_in
64 #elif !defined(SOCKADDR_IN)
66 #define SOCKADDR_IN struct sockaddr_in
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).
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
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 ) {
126 if(pattern
[0] == '*')
127 return PatternMatch (pattern
+1,test
);
134 case 0 : return test
[0] == 0;
135 case '?' : return PatternMatch (pattern
+ 1, test
+ 1);
137 if( PatternMatch (pattern
+1, test
) ) {
140 return PatternMatch (pattern
, test
+1);
144 fprintf( stderr
, "[chuck](via OSC): spurious %c in pattern \".../%s/...\"\n", pattern
[0], theWholePattern
);
147 return MatchBrackets (pattern
,test
);
149 return MatchList (pattern
,test
);
151 if(pattern
[1] == 0) {
153 } else if(pattern
[1] == test
[0]) {
154 return PatternMatch (pattern
+2,test
+1);
159 if(pattern
[0] == test
[0]) {
160 return PatternMatch (pattern
+1,test
+1);
168 /* we know that pattern[0] == '[' and test[0] != 0 */
170 static bool MatchBrackets( const char * pattern
, const char * test
)
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
);
181 if(pattern
[1] == '!') {
188 fprintf( stderr
,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern
);
192 if(p
[1] == '-' && p
[2] != 0) {
193 if(test
[0] >= p
[0] && test
[0] <= p
[2]) {
199 if(p
[0] == test
[0]) {
215 fprintf( stderr
,"[chuck](via OSC): unterminated [ in pattern \".../%s/...\"\n", theWholePattern
);
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
);
236 restOfPattern
++; /* skip close curly brace */
238 pattern
++; /* skip open curly brace */
242 if(*pattern
== ',') {
243 if(PatternMatch (restOfPattern
, tp
)) {
249 } else if(*pattern
== '}') {
250 return PatternMatch (restOfPattern
, tp
);
251 } else if(*pattern
== *tp
) {
256 while (*pattern
!= ',' && *pattern
!= '}') {
259 if(*pattern
== ',') {
266 // end OSC-pattern-match.h
272 Copyright (c) 1998. The Regents of the University of California (Regents).
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
306 Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
309 //#include "OSC-timetag.h"
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
)
335 printf("***** OSCTT_Compare(%llx, %llx): %d\n", left
, right
,
336 (left
<right
) ? -1 : ((left
== right
) ? 0 : 1));
340 } else if(left
== right
) {
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) {
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);
369 /* No timezone, no DST version ... */
370 result
= (unsigned) SECONDS_FROM_1900_to_1970
+
371 (unsigned) tv
.tv_sec
;
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); */
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;
403 #else /* Not HAS8BYTEINT */
405 OSCTimeTag
OSCTT_CurrentTime(void) {
412 OSCTimeTag
OSCTT_BiggestPossibleTimeTag(void) {
414 result
.seconds
= 0xffffffff;
415 result
.fraction
= 0xffffffff;
419 OSCTimeTag
OSCTT_Immediately(void) {
426 OSCTimeTag
OSCTT_PlusSeconds(OSCTimeTag original
, float secondsOffset
) {
433 int OSCTT_Compare(OSCTimeTag left
, OSCTimeTag right
) {
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
450 Copyright (c) 1996. The Regents of the University of California (Regents).
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.
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
494 #define DONE 4 /* All open bundles have been closed, so can't write
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
;
512 OSC_resetBuffer(buf
);
515 void OSC_resetBuffer(OSCbuf
*buf
) {
516 buf
->bufptr
= buf
->buffer
;
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
) {
542 OSC_errorMessage
= "Packet has unterminated bundles";
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
);
556 OSC_errorMessage
= "Packet has unterminated bundles";
560 return (buf
->bufptr
- buf
->buffer
);
564 #define CheckOverflow(buf, bytesNeeded) { \
565 if((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
566 OSC_errorMessage = "buffer overflow"; \
571 static void PatchMessageSize(OSCbuf
*buf
)
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";
585 if(buf
->state
== DONE
) {
586 OSC_errorMessage
= "This packet is finished; can't open a new bundle";
590 if(++(buf
->bundleDepth
) >= MAX_BUNDLE_NESTING
) {
591 OSC_errorMessage
= "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
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);
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
;
614 buf
->bufptr
+= OSC_padString(buf
->bufptr
, "#bundle");
616 *((OSCTimeTag
*) buf
->bufptr
) = tt
;
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]);
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
630 int4byte temp
= intp
[0];
637 buf
->bufptr
+= sizeof(OSCTimeTag
);
639 buf
->state
= NEED_COUNT
;
641 buf
->gettingFirstUntypedArg
= 0;
642 buf
->typeStringPtr
= 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!";
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 */
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
;
671 buf
->gettingFirstUntypedArg
= 0;
672 buf
->typeStringPtr
= 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!";
685 if(CheckTypeTag(buf
, '\0')) return 9;
687 while (buf
->bundleDepth
> 0) {
688 OSC_closeBundle(buf
);
691 buf
->typeStringPtr
= 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";
704 if(buf
->state
== DONE
) {
705 OSC_errorMessage
= "This packet is finished; can't write another address";
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
;
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;
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;
738 int OSC_writeAddressAndTypes(OSCbuf
*buf
, char *name
, char *types
)
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;
761 static int CheckTypeTag(OSCbuf
*buf
, char expectedType
)
763 if(buf
->typeStringPtr
) {
764 if(*(buf
->typeStringPtr
) != expectedType
) {
765 if(expectedType
== '\0') {
767 "According to the type tag I expected more arguments.";
768 } else if(*(buf
->typeStringPtr
) == '\0') {
770 "According to the type tag I didn't expect any more arguments.";
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
);
780 ++(buf
->typeStringPtr
);
787 int OSC_writeFloatArg(OSCbuf
*buf
, float arg
)
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
);
801 buf
->gettingFirstUntypedArg
= 0;
807 int OSC_writeFloatArgs(OSCbuf
*buf
, int numFloats
, float *args
)
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
]);
823 buf
->gettingFirstUntypedArg
= 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
);
837 buf
->gettingFirstUntypedArg
= 0;
842 int OSC_writeStringArg(OSCbuf
*buf
, char *arg
)
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
856 CheckOverflow(buf
, len
+4); /* Too conservative */
858 OSC_padStringWithAnExtraStupidComma(buf
->bufptr
, arg
);
860 CheckOverflow(buf
, len
);
861 buf
->bufptr
+= OSC_padString(buf
->bufptr
, arg
);
864 buf
->gettingFirstUntypedArg
= 0;
870 /* String utilities */
872 static int strlen(char *s) {
874 for(i=0; s[i] != '\0'; 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
);
893 static int OSC_padString(char *dest
, char *str
)
897 for(i
= 0; str
[i
] != '\0'; i
++) {
901 return OSC_WritePadding(dest
, i
);
905 static int OSC_padStringWithAnExtraStupidComma(char *dest
, char *str
)
910 for(i
= 0; str
[i
] != '\0'; i
++) {
914 return OSC_WritePadding(dest
, i
+1);
918 static int OSC_WritePadding(char *dest
, int i
)
923 for(; (i
% STRING_ALIGN_PAD
) != 0; i
++) {
931 // end OSC-client.cpp
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__)
947 #include <sys/types.h>
948 #include <sys/socket.h>
949 #include <sys/time.h>
951 #include <netinet/in.h>
952 #include <netinet/tcp.h>
953 #include <arpa/inet.h>
957 #ifdef __MACOSX_CORE__
959 #define SOCKADDR_IN struct sockaddr_in
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
{
981 void onReceive ( char * mesg
, int mesgLen
) {} // ignore
982 int& port() { return _port
; }
985 class UDP_Port_Listener
{
993 char m_inbuf
[OSCINBUFSIZE
];
996 vector
< UDP_Subscriber
* > m_subscribers
;
997 queue
< UDP_Subscriber
* > m_free
;
1000 UDP_Port_Listener( int port
);
1001 ~UDP_Port_Listener();
1003 bool bind_to_port(int port
);
1007 bool add ( UDP_Subscriber
* );
1008 bool drop ( UDP_Subscriber
* );
1017 class UDP_Port_Manager
{
1021 static UDP_Port_Manager
* _inst
;
1022 map
< int, UDP_Port_Listener
* > _listeners
;
1026 static UDP_Port_Manager
* instance();
1029 bool subscribe ( UDP_Subscriber
* sub
, int port
);
1030 bool unsubscribe ( UDP_Subscriber
* sub
);
1036 class UDP_Receiver
{
1042 SOCKADDR_IN _remote_addr
;
1043 int _remote_addr_len
;
1052 bool bind_to_port(int port
);
1053 int recv_next(char *buffer
, int size
);
1061 class UDP_Transmitter
{
1066 SOCKADDR_IN _host_addr
;
1072 _status
= UDP_NOINIT
;
1074 virtual ~UDP_Transmitter() {}
1077 void set_host(char * hostaddress
, int port
);
1078 int send(char *buffer
, int size
);
1079 udp_stat
status(void) { return _status
; }
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();
1093 UDP_Port_Manager::UDP_Port_Manager() {
1098 UDP_Port_Manager::init() {
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
);
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" );
1117 if( _listeners
.count( sub
->port() ) == 0 ) {
1118 EM_log( CK_LOG_INFO
, "error, cannot unsubscribe: port %d not in use", sub
->port() );
1122 int pp
= sub
->port();
1123 UDP_Port_Listener
* listener
= _listeners
[pp
];
1124 bool ret
= listener
->drop( sub
);
1126 if( listener
->nsubs() == 0 ) {
1127 EM_log( CK_LOG_INFO
, "PortManager: Listener on port %d is empty - removing", sub
->port() );
1129 _listeners
.erase( pp
);
1136 UDP_Port_Listener::UDP_Port_Listener( int port
) :
1137 m_inbufsize( OSCINBUFSIZE
),
1141 m_in
->bind_to_port( port
);
1145 UDP_Port_Listener::~UDP_Port_Listener() {
1146 //fprintf(stderr , "port listener destructor\n");
1148 // usleep( 10 ); // do we need this ?
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();
1164 UDP_Port_Listener::nsubs() { return m_subscribers
.size(); }
1167 UDP_Port_Listener::add( UDP_Subscriber
* sub
) {
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
;
1177 EM_log(CK_LOG_INFO
, "UDP_Port_Listener::add - error subscriber already exists" );
1185 UDP_Port_Listener::drop( UDP_Subscriber
* sub
) {
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
);
1197 EM_log(CK_LOG_INFO
, "UDP_Port_Listener::add - error subscriber already exists" );
1204 THREAD_RETURN ( THREAD_TYPE udp_port_listener_thread
) ( void * data
)
1206 UDP_Port_Listener
* upl
= (UDP_Port_Listener
*) data
;
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" );
1215 mLen
= upl
->recv_mesg();
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
1229 UDP_Port_Listener::listen() {
1230 if( !listening
&& m_in
->status() != UDP_ERROR
) {
1232 m_thread
->start( udp_port_listener_thread
, (void*) this );
1239 UDP_Port_Listener::bind_to_port(int port
) {
1240 return m_in
->bind_to_port( port
);
1244 UDP_Port_Listener::close() {
1245 if( m_in
->status() == UDP_BOUND
) {
1252 UDP_Port_Listener::recv_mesg() {
1253 int mLen
= m_in
->recv_next( m_inbuf
, m_inbufsize
);
1256 EM_log( CK_LOG_INFO
, "recvLen 0 on socket, returning 0" );
1261 vector
<UDP_Subscriber
*>::size_type i
;
1262 for( i
= 0 ; i
< m_subscribers
.size(); i
++ ) {
1263 m_subscribers
[i
]->onReceive( m_inbuf
, mLen
);
1273 UDP_Subscriber::subscribe( int p
) {
1274 if( port() >= 0 ) return false; //already subscribed
1275 else if( UDP_Port_Manager::instance()->subscribe( this, p
) )
1288 UDP_Subscriber::unsubscribe() {
1289 if( port() < 0 ) return false; //currently unsubscribed
1290 else if( UDP_Port_Manager::instance()->unsubscribe( this ) ) {
1295 return false; //could not unsubscribe?
1301 UDP_Receiver::UDP_Receiver()
1303 _status
= UDP_NOINIT
;
1308 UDP_Receiver::init()
1311 _sock
= ck_udp_create();
1312 _status
= ( _sock
!= NULL
) ? UDP_UNBOUND
: UDP_ERROR
;
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
);
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
;
1347 UDP_Receiver::close_sock() {
1349 _status
= UDP_NOINIT
;
1354 UDP_Transmitter::init() {
1356 _sock
= ck_udp_create();
1357 _status
= ( _sock
!= NULL
) ? UDP_READY
: UDP_ERROR
;
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
1374 host
= gethostbyname(hostaddress
); // Get the IP address of the server
1377 fprintf( stderr
, "[chuck](via OSC): UDP_Transmitter: unknown host: %s\n", hostaddress
);
1378 _status
= UDP_ERROR
;
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!");
1396 int ret
= ck_sendto(_sock
, buffer
, bsize
, (struct sockaddr
*) &_host_addr
, sizeof(_host_addr
) );
1397 return ( ret
<= 0 ) ? 0 : ret
;
1401 UDP_Transmitter::close_sock() {
1408 OSC_Transmitter::OSC_Transmitter() {
1409 _out
= new UDP_Transmitter();
1410 _holdMessage
= false;
1414 OSC_Transmitter::OSC_Transmitter( UDP_Transmitter
* out
) {
1416 _holdMessage
= false;
1419 OSC_Transmitter::~OSC_Transmitter() { delete _out
; }
1422 OSC_Transmitter::init() {
1423 if( _out
->status() == UDP_NOINIT
) _out
->init();
1424 OSC_initBuffer(&_osc
, sizeof(_buffer
), _buffer
);
1428 OSC_Transmitter::setHost( char * hadd
, int p
) {
1429 _out
->set_host(hadd
, p
);
1433 OSC_Transmitter::presend( char * buf
, int sz
) {
1438 OSC_Transmitter::openBundle( OSCTimeTag t
) {
1439 OSC_openBundle( &_osc
, t
);
1444 OSC_Transmitter::closeBundle() {
1445 OSC_closeBundle( &_osc
);
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
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
);
1465 for( int j
= 1; !osc_err
&& j
< argnum
; j
++ ) {
1466 switch ( args
[j
] ) {
1468 osc_err
= OSC_writeIntArg ( &_osc
, va_arg(tags
, int) );
1471 osc_err
= OSC_writeFloatArg ( &_osc
, va_arg(tags
, double) );
1474 osc_err
= OSC_writeStringArg ( &_osc
, va_arg(tags
, char *) );
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
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
);
1502 startMessage( spec
, spec
+ off
+ 1 );
1506 OSC_Transmitter::startMessage( char * address
, char * args
)
1508 // OSC_writeAddressAndTypes( &_osc, address, args );
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
!= ' ' ) {
1528 OSC_writeAddressAndTypes( &_osc
, addrfix
, addrfix
+ addrlen
+ 1); //expects the ',' before spec tag.
1529 // delete[] addrfix;
1530 //free ( (void*)addrfix );
1535 OSC_Transmitter::addInt ( int4byte i
) {
1536 int osc_err
= OSC_writeIntArg ( &_osc
, i
);
1538 fprintf ( stderr
, "[chuck](via OSC): error writing packet: %d %s\n", osc_err
, OSC_errorMessage
);
1545 OSC_Transmitter::addFloat ( float f
) {
1546 int osc_err
= OSC_writeFloatArg ( &_osc
, f
);
1548 fprintf ( stderr
, "[chuck](via OSC): error writing packet: %d %s\n", osc_err
, OSC_errorMessage
);
1555 OSC_Transmitter::addString ( char * s
) {
1556 int osc_err
= OSC_writeStringArg ( &_osc
, s
);
1558 fprintf ( stderr
, "[chuck](via OSC): error writing packet: %d %s\n", osc_err
, OSC_errorMessage
);
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 );
1574 OSC_Transmitter::tryMessage() {
1575 if( !packetReady() ) return;
1577 _out
->send( OSC_getPacket(&_osc
), OSC_packetSize(&_osc
) );
1578 OSC_resetBuffer(&_osc
);
1582 OSC_Transmitter::holdMessage(bool b
) {
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
);
1598 OSC_Receiver::OSC_Receiver():
1599 // _listening(false),
1600 // _inbufsize(OSCINBUFSIZE),
1606 _address_space (NULL
),
1607 _address_size ( 2 ),
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();
1625 OSC_Receiver::OSC_Receiver(UDP_Receiver
* in
) {
1631 OSC_Receiver::init(){
1636 OSC_Receiver::~OSC_Receiver()
1639 for( int i
=0; i
< _inbox_size
; i
++ ) {
1640 if( _inbox
[i
].payload
) {
1641 free ( _inbox
[i
].payload
);
1642 _inbox
[i
].payload
= NULL
;
1650 THREAD_RETURN ( THREAD_TYPE osc_recv_thread
) ( void * data
)
1652 OSC_Receiver
* oscar
= (OSC_Receiver
* ) data
;
1655 if( Chuck_VM::our_priority
!= 0x7fffffff )
1656 Chuck_VM::set_priority( Chuck_VM::our_priority
, NULL
);
1663 return (THREAD_RETURN
)0;
1668 OSC_Receiver::port() { return _port
; }
1671 OSC_Receiver::onReceive( char * mesg
, int mesgLen
) {
1672 handle_mesg( mesg
, mesgLen
);
1676 OSC_Receiver::bind_to_port(int port
) {
1678 // _in->bind_to_port(port);
1682 OSC_Receiver::listen( int port
) {
1683 bind_to_port ( port
);
1688 OSC_Receiver::stopListening() {
1693 OSC_Receiver::listen() {
1694 unsubscribe(); //in case we're connected.
1695 return subscribe( _tmp_port
);
1699 _io_thread->start( osc_recv_thread, (void*)this );
1708 OSC_Receiver::close_sock() {
1710 // _in->close_sock();
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 ) {
1723 handle_mesg(_inbuf, _mesglen);
1730 OSC_Receiver::has_mesg() {
1731 // EM_log( CK_LOG_FINER, "OSC has message?" );
1732 return ( _started
&& ( _in_read
+1 ) % _inbox_size
!= _in_write
);
1736 OSC_Receiver::get_mesg(OSCMesg
* bucket
) {
1738 _io_mutex
->acquire();
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();
1749 _io_mutex
->release();
1755 OSC_Receiver::parse( char * mesg
, int mesgLen
) {
1757 // unpack bundles, dump all messages
1758 // any local prep we need here?
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" );
1771 OSC_Receiver::next_write()
1773 // called by the UDP client ( blocks )
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)
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 ;
1813 // okay. read and write may be anywhere.
1814 if( _in_write
> _in_read
) {
1816 _inbox
= (OSCMesg
* ) realloc ((void*)_inbox
, new_size
* sizeof(*_inbox
) );
1818 // indices are still valid
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
) );
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
) );
1836 _in_write
= (_in_write
+ _read_tail
);
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
;
1851 // fprintf(stderr, "fuck! fucking buffer reallocation error!\n");
1855 next
= (_in_write
+1)%new_size
; //where we're headed..
1856 _inbox_size
= new_size
;
1858 // fprintf(stderr, "(%d)", _inbox_size);
1862 // fprintf(stderr, "max buffer...dropping old mesg %d\n", next);
1863 _in_read
= (next
+1)%_inbox_size
;
1866 _io_mutex
->release();
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
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
1893 mrp
->types
= mrp
->address
+ strlen(mrp
->address
) + 4 - strlen(mrp
->address
)%4;
1894 if( mrp
->types
[0] == ',') {
1896 mrp
->data
= mrp
->types
+ strlen(mrp
->types
) + 4 - strlen(mrp
->types
)%4;
1900 // should there be a warning?
1901 // classes that handle mesgs
1902 // should take care of that.
1903 mrp
->data
= mrp
->types
;
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 )
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"
1947 unsigned long size
= ntohl(*((unsigned long*)z
));
1951 if( m
[0] == '#' ) handle_bundle(m
,size
);
1952 else handle_mesg(m
,size
);
1954 off
+= size
+4; //beginning of next message
1959 OSC_Receiver::new_event ( char * spec
) {
1960 OSC_Address_Space
* event
= new OSC_Address_Space ( spec
);
1961 add_address ( event
);
1966 OSC_Receiver::new_event ( char * addr
, char * type
) {
1967 OSC_Address_Space
* event
= new OSC_Address_Space ( addr
, type
);
1968 add_address ( event
);
1974 OSC_Receiver::add_address ( OSC_Address_Space
* src
) {
1975 if( _address_num
== _address_size
) {
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);
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?
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
[] = {
2030 "ERROR: num types exceeded"
2035 OSC_Address_Space::OSC_Address_Space() {
2037 setSpec( "/undefined/default,i" );
2041 OSC_Address_Space::OSC_Address_Space( char * spec
) {
2046 OSC_Address_Space::OSC_Address_Space( char * addr
, char * types
) {
2048 setSpec( addr
, types
);
2052 OSC_Address_Space::init() {
2055 _queueSize
= 512; // start queue size at 512 // 64.
2060 _current_data
= NULL
;
2061 _buffer_mutex
= new XMutex();
2064 OSC_Address_Space::~OSC_Address_Space() {
2065 if( _queue
) free ( _queue
);
2069 OSC_Address_Space::setReceiver(OSC_Receiver
* recv
) {
2074 OSC_Address_Space::setSpec( char *addr
, char * types
) {
2075 strncpy ( _spec
, addr
, 512 );
2076 strncat ( _spec
, "," , 512);
2077 strncat ( _spec
, types
, 512 );
2084 OSC_Address_Space::setSpec( char *c
) {
2085 strncpy ( _spec
, c
, 512);
2092 OSC_Address_Space::scanSpec() { //this allows for sloppy-ish definitions in type string
2093 //assumes that a potential spec is already in _spec;
2096 pread
= pwrite
= (char*)_spec
;
2097 bool in_type
= false;
2098 while ( *pread
!= '\0' ) {
2099 if( *pread
== ',' || *pread
== ' ' ) {
2104 } // otherwise, we ignore
2105 else if( *pread
== ' ' ) {
2106 EM_log(CK_LOG_INFO
, "OSC-Address-Space: spaces in OSC type tag string! ignoring");
2110 if( pwrite
!= pread
) { *pwrite
= *pread
; }
2116 //no type args found, add a comma to indicate a zero-arg string.
2119 *pwrite
= '\0'; //if pread terminates, so does pwrite.
2123 OSC_Address_Space::parseSpec() {
2125 if( !_needparse
) return;
2127 char * type
= strrchr(_spec
, ',');
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
);
2148 OSC_Address_Space::resizeQueue( int n
)
2150 if( n
<= _queueSize
)
2151 return; // only grows
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
);
2171 opsc_data
* _new_queue
= (opsc_data
*)malloc( _newQSize
* chunkSize
);
2174 memset( _new_queue
, 0, _newQSize
* chunkSize
); // out with the old...
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");
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
));
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();
2213 OSC_Address_Space::resizeData( int n
) {
2214 if( _dataSize
== n
) return;
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
) );
2224 OSC_Address_Space::message_matches( OSCMesg
* m
) {
2226 //this should test for type as well.
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 ) {
2239 // fprintf(stderr, "error, mismatched type string( %s ) vs ( %s ) \n", _type, type ) ;
2241 // fprintf( stderr, "error, missing type string (expecting %s) \n", _type );
2249 OSC_Address_Space::try_queue_mesg( OSCMesg
* m
)
2251 if( !message_matches( m
) ) return false;
2259 OSC_Address_Space::has_mesg() {
2260 // EM_log( CK_LOG_FINER, "OSC has mesg" );
2261 return ( ( _qread
+ 1 ) % _queueSize
!= _qwrite
);
2266 OSC_Address_Space::next_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
;
2280 _buffer_mutex
->release();
2289 OSC_Address_Space::vcheck( osc_datatype tt
) {
2292 EM_log( CK_LOG_SEVERE
, "OscEvent: getVal(): nextMsg() must be called before reading data..." );
2295 else if( _cur_value
< 0 || _cur_value
>= _dataSize
) {
2296 EM_log( CK_LOG_SEVERE
, "OscEvent: read position %d outside message ...", _cur_value
);
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
] );
2308 OSC_Address_Space::next_int() {
2309 return ( vcheck(OSC_INT
) ) ? _cur_mesg
[_cur_value
++].i
: 0 ;
2313 OSC_Address_Space::next_float() {
2314 return ( vcheck(OSC_FLOAT
) ) ? _cur_mesg
[_cur_value
++].f
: 0.0 ;
2318 OSC_Address_Space::next_string() {
2319 return ( vcheck(OSC_STRING
) ) ? _cur_mesg
[_cur_value
++].s
: NULL
;
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
);
2332 OSC_Address_Space::next_blob() {
2333 return ( vcheck(OSC_BLOB
) ) ? _cur_mesg
[_cur_value
++].s
: NULL
;
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.
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
);
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
;
2365 char * type
= m
->types
+1;
2366 char * data
= m
->data
;
2374 while ( *type
!= '\0' ) {
2377 endy
= ntohl(*((unsigned long*)data
));
2378 fp
= (float*)(&endy
);
2379 _vals
[i
].t
= OSC_FLOAT
;
2384 endy
= ntohl(*((unsigned long*)data
));
2385 ip
= (int4byte
*)(&endy
);
2386 _vals
[i
].t
= OSC_INT
;
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;
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;
2419 for( i=0; i < _nvals; i++ ) {
2420 fprintf(stderr, "%d %f : ", i, _val[i] );
2422 fprintf(stderr, "\n");