summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra/sendOSC.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/sendOSC.c')
-rw-r--r--apps/plugins/pdbox/PDa/extra/sendOSC.c2920
1 files changed, 1460 insertions, 1460 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/sendOSC.c b/apps/plugins/pdbox/PDa/extra/sendOSC.c
index bc983cc31e..ac7ae37954 100644
--- a/apps/plugins/pdbox/PDa/extra/sendOSC.c
+++ b/apps/plugins/pdbox/PDa/extra/sendOSC.c
@@ -1,1461 +1,1461 @@
1/* 1/*
2Written by Matt Wright, The Center for New Music and Audio Technologies, 2Written by Matt Wright, The Center for New Music and Audio Technologies,
3University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03 3University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
4The Regents of the University of California (Regents). 4The Regents of the University of California (Regents).
5 5
6Permission to use, copy, modify, distribute, and distribute modified versions 6Permission to use, copy, modify, distribute, and distribute modified versions
7of this software and its documentation without fee and without a signed 7of this software and its documentation without fee and without a signed
8licensing agreement, is hereby granted, provided that the above copyright 8licensing agreement, is hereby granted, provided that the above copyright
9notice, this paragraph and the following two paragraphs appear in all copies, 9notice, this paragraph and the following two paragraphs appear in all copies,
10modifications, and distributions. 10modifications, and distributions.
11 11
12IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 12IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
13SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 13SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
14OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 14OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
15BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 16
17REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 17REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 19PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
20HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 20HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
21MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 21MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22 22
23 23
24The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl 24The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
25*/ 25*/
26 26
27 27
28/* sendOSC.c 28/* sendOSC.c
29 29
30 Matt Wright, 6/3/97 30 Matt Wright, 6/3/97
31 based on sendOSC.c, which was based on a version by Adrian Freed 31 based on sendOSC.c, which was based on a version by Adrian Freed
32 32
33 Text-based OpenSoundControl client. User can enter messages via command 33 Text-based OpenSoundControl client. User can enter messages via command
34 line arguments or standard input. 34 line arguments or standard input.
35 35
36 Version 0.1: "play" feature 36 Version 0.1: "play" feature
37 Version 0.2: Message type tags. 37 Version 0.2: Message type tags.
38 38
39 pd version branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/sendOSC/sendOSC.c 39 pd version branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/sendOSC/sendOSC.c
40 ------------- 40 -------------
41 -- added bundle stuff to send. jdl 20020416 41 -- added bundle stuff to send. jdl 20020416
42 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 42 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
43 -- ost_at_test.at + i22_at_test.at, 2000-2002 43 -- ost_at_test.at + i22_at_test.at, 2000-2002
44 modified to compile as pd externel 44 modified to compile as pd externel
45*/ 45*/
46 46
47#define MAX_ARGS 2000 47#define MAX_ARGS 2000
48#define SC_BUFFER_SIZE 64000 48#define SC_BUFFER_SIZE 64000
49 49
50#include "m_pd.h" 50#include "m_pd.h"
51#include "OSC-client.h" 51#include "OSC-client.h"
52 52
53#include <string.h> 53#include <string.h>
54#include <sys/types.h> 54#include <sys/types.h>
55#include <stdlib.h> 55#include <stdlib.h>
56#include <stdio.h> 56#include <stdio.h>
57#include <sys/stat.h> 57#include <sys/stat.h>
58#include <sys/types.h> 58#include <sys/types.h>
59 59
60#ifdef WIN32 60#ifdef WIN32
61#include <winsock2.h> 61#include <winsock2.h>
62#include <io.h> 62#include <io.h>
63#include <errno.h> 63#include <errno.h>
64#include <fcntl.h> 64#include <fcntl.h>
65#include <winsock2.h> 65#include <winsock2.h>
66#include <ctype.h> 66#include <ctype.h>
67#include <signal.h> 67#include <signal.h>
68#else 68#else
69#include <sys/socket.h> 69#include <sys/socket.h>
70#include <netinet/in.h> 70#include <netinet/in.h>
71#include <rpc/rpc.h> 71#include <rpc/rpc.h>
72#include <sys/times.h> 72#include <sys/times.h>
73#include <sys/param.h> 73#include <sys/param.h>
74#include <sys/time.h> 74#include <sys/time.h>
75#include <sys/ioctl.h> 75#include <sys/ioctl.h>
76#include <netdb.h> 76#include <netdb.h>
77#endif 77#endif
78 78
79#ifdef __APPLE__ 79#ifdef __APPLE__
80 #include <string.h> 80 #include <string.h>
81#endif 81#endif
82 82
83#define UNIXDG_PATH "/tmp/htm" 83#define UNIXDG_PATH "/tmp/htm"
84#define UNIXDG_TMP "/tmp/htm.XXXXXX" 84#define UNIXDG_TMP "/tmp/htm.XXXXXX"
85 85
86 86
87 87
88OSCTimeTag OSCTT_Immediately(void) { 88OSCTimeTag OSCTT_Immediately(void) {
89 OSCTimeTag result; 89 OSCTimeTag result;
90 result.seconds = 0; 90 result.seconds = 0;
91 result.fraction = 1; 91 result.fraction = 1;
92 return result; 92 return result;
93} 93}
94 94
95 95
96OSCTimeTag OSCTT_CurrentTime(void) { 96OSCTimeTag OSCTT_CurrentTime(void) {
97 OSCTimeTag result; 97 OSCTimeTag result;
98 result.seconds = 0; 98 result.seconds = 0;
99 result.fraction = 1; 99 result.fraction = 1;
100 return result; 100 return result;
101} 101}
102 102
103OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { 103OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
104 OSCTimeTag result; 104 OSCTimeTag result;
105 result.seconds = 0; 105 result.seconds = 0;
106 result.fraction = 1; 106 result.fraction = 1;
107 return result; 107 return result;
108} 108}
109 109
110 110
111typedef int bool; 111typedef int bool;
112 112
113typedef struct 113typedef struct
114{ 114{
115 float srate; 115 float srate;
116 116
117 struct sockaddr_in serv_addr; /* udp socket */ 117 struct sockaddr_in serv_addr; /* udp socket */
118 #ifndef WIN32 118 #ifndef WIN32
119 struct sockaddr_un userv_addr; /* UNIX socket */ 119 struct sockaddr_un userv_addr; /* UNIX socket */
120 #endif 120 #endif
121 int sockfd; /* socket file descriptor */ 121 int sockfd; /* socket file descriptor */
122 int index, len,uservlen; 122 int index, len,uservlen;
123 void *addr; 123 void *addr;
124 int id; 124 int id;
125} desc; 125} desc;
126 126
127 127
128/* open a socket for HTM communication to given host on given portnumber */ 128/* open a socket for HTM communication to given host on given portnumber */
129/* if host is 0 then UNIX protocol is used (i.e. local communication */ 129/* if host is 0 then UNIX protocol is used (i.e. local communication */
130void *OpenHTMSocket(char *host, int portnumber) 130void *OpenHTMSocket(char *host, int portnumber)
131{ 131{
132 struct sockaddr_in cl_addr; 132 struct sockaddr_in cl_addr;
133 #ifndef WIN32 133 #ifndef WIN32
134 int sockfd; 134 int sockfd;
135 struct sockaddr_un ucl_addr; 135 struct sockaddr_un ucl_addr;
136 #else 136 #else
137 unsigned int sockfd; 137 unsigned int sockfd;
138 #endif 138 #endif
139 139
140 desc *o; 140 desc *o;
141 int oval = 1; 141 int oval = 1;
142 o = malloc(sizeof(*o)); 142 o = malloc(sizeof(*o));
143 if(!o) return 0; 143 if(!o) return 0;
144 144
145 #ifndef WIN32 145 #ifndef WIN32
146 146
147 if(!host) 147 if(!host)
148 { 148 {
149 char *mktemp(char *); 149 char *mktemp(char *);
150 int clilen; 150 int clilen;
151 o->len = sizeof(ucl_addr); 151 o->len = sizeof(ucl_addr);
152 /* 152 /*
153 * Fill in the structure "userv_addr" with the address of the 153 * Fill in the structure "userv_addr" with the address of the
154 * server that we want to send to. 154 * server that we want to send to.
155 */ 155 */
156 156
157 bzero((char *) &o->userv_addr, sizeof(o->userv_addr)); 157 bzero((char *) &o->userv_addr, sizeof(o->userv_addr));
158 o->userv_addr.sun_family = AF_UNIX; 158 o->userv_addr.sun_family = AF_UNIX;
159 strcpy(o->userv_addr.sun_path, UNIXDG_PATH); 159 strcpy(o->userv_addr.sun_path, UNIXDG_PATH);
160 sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber); 160 sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber);
161 o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path); 161 o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path);
162 o->addr = &(o->userv_addr); 162 o->addr = &(o->userv_addr);
163 /* 163 /*
164 * Open a socket (a UNIX domain datagram socket). 164 * Open a socket (a UNIX domain datagram socket).
165 */ 165 */
166 166
167 if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0) 167 if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0)
168 { 168 {
169 /* 169 /*
170 * Bind a local address for us. 170 * Bind a local address for us.
171 * In the UNIX domain we have to choose our own name (that 171 * In the UNIX domain we have to choose our own name (that
172 * should be unique). We'll use mktemp() to create a unique 172 * should be unique). We'll use mktemp() to create a unique
173 * pathname, based on our process id. 173 * pathname, based on our process id.
174 */ 174 */
175 175
176 bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */ 176 bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */
177 ucl_addr.sun_family = AF_UNIX; 177 ucl_addr.sun_family = AF_UNIX;
178 strcpy(ucl_addr.sun_path, UNIXDG_TMP); 178 strcpy(ucl_addr.sun_path, UNIXDG_TMP);
179 179
180 mktemp(ucl_addr.sun_path); 180 mktemp(ucl_addr.sun_path);
181 clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path); 181 clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path);
182 182
183 if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0) 183 if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0)
184 { 184 {
185 perror("client: can't bind local address"); 185 perror("client: can't bind local address");
186 close(sockfd); 186 close(sockfd);
187 sockfd = -1; 187 sockfd = -1;
188 } 188 }
189 } 189 }
190 else 190 else
191 perror("unable to make socket\n"); 191 perror("unable to make socket\n");
192 192
193 }else 193 }else
194 194
195 #endif 195 #endif
196 196
197 { 197 {
198 /* 198 /*
199 * Fill in the structure "serv_addr" with the address of the 199 * Fill in the structure "serv_addr" with the address of the
200 * server that we want to send to. 200 * server that we want to send to.
201 */ 201 */
202 o->len = sizeof(cl_addr); 202 o->len = sizeof(cl_addr);
203 203
204 #ifdef WIN32 204 #ifdef WIN32
205 ZeroMemory((char *)&o->serv_addr, sizeof(o->serv_addr)); 205 ZeroMemory((char *)&o->serv_addr, sizeof(o->serv_addr));
206 #else 206 #else
207 bzero((char *)&o->serv_addr, sizeof(o->serv_addr)); 207 bzero((char *)&o->serv_addr, sizeof(o->serv_addr));
208 #endif 208 #endif
209 209
210 o->serv_addr.sin_family = AF_INET; 210 o->serv_addr.sin_family = AF_INET;
211 211
212 /* MW 6/6/96: Call gethostbyname() instead of inet_addr(), 212 /* MW 6/6/96: Call gethostbyname() instead of inet_addr(),
213 so that host can be either an Internet host name (e.g., 213 so that host can be either an Internet host name (e.g.,
214 "les") or an Internet address in standard dot notation 214 "les") or an Internet address in standard dot notation
215 (e.g., "128.32.122.13") */ 215 (e.g., "128.32.122.13") */
216 { 216 {
217 struct hostent *hostsEntry; 217 struct hostent *hostsEntry;
218 unsigned long address; 218 unsigned long address;
219 219
220 hostsEntry = gethostbyname(host); 220 hostsEntry = gethostbyname(host);
221 if (hostsEntry == NULL) { 221 if (hostsEntry == NULL) {
222 fprintf(stderr, "Couldn't decipher host name \"%s\"\n", host); 222 fprintf(stderr, "Couldn't decipher host name \"%s\"\n", host);
223 #ifndef WIN32 223 #ifndef WIN32
224 herror(NULL); 224 herror(NULL);
225 #endif 225 #endif
226 return 0; 226 return 0;
227 } 227 }
228 address = *((unsigned long *) hostsEntry->h_addr_list[0]); 228 address = *((unsigned long *) hostsEntry->h_addr_list[0]);
229 o->serv_addr.sin_addr.s_addr = address; 229 o->serv_addr.sin_addr.s_addr = address;
230 } 230 }
231 231
232 /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */ 232 /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */
233 233
234 /* End MW changes */ 234 /* End MW changes */
235 235
236 /* 236 /*
237 * Open a socket (a UDP domain datagram socket). 237 * Open a socket (a UDP domain datagram socket).
238 */ 238 */
239 239
240 240
241 #ifdef WIN32 241 #ifdef WIN32
242 o->serv_addr.sin_port = htons((USHORT)portnumber); 242 o->serv_addr.sin_port = htons((USHORT)portnumber);
243 o->addr = &(o->serv_addr); 243 o->addr = &(o->serv_addr);
244 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) { 244 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) {
245 ZeroMemory((char *)&cl_addr, sizeof(cl_addr)); 245 ZeroMemory((char *)&cl_addr, sizeof(cl_addr));
246 cl_addr.sin_family = AF_INET; 246 cl_addr.sin_family = AF_INET;
247 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY); 247 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
248 cl_addr.sin_port = htons(0); 248 cl_addr.sin_port = htons(0);
249 249
250 // enable broadcast: jdl ~2003 250 // enable broadcast: jdl ~2003
251 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) { 251 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
252 perror("setsockopt"); 252 perror("setsockopt");
253 } 253 }
254 254
255 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) { 255 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
256 perror("could not bind\n"); 256 perror("could not bind\n");
257 closesocket(sockfd); 257 closesocket(sockfd);
258 sockfd = -1; 258 sockfd = -1;
259 } 259 }
260 } 260 }
261 else { perror("unable to make socket\n");} 261 else { perror("unable to make socket\n");}
262 #else 262 #else
263 o->serv_addr.sin_port = htons(portnumber); 263 o->serv_addr.sin_port = htons(portnumber);
264 o->addr = &(o->serv_addr); 264 o->addr = &(o->serv_addr);
265 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { 265 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
266 bzero((char *)&cl_addr, sizeof(cl_addr)); 266 bzero((char *)&cl_addr, sizeof(cl_addr));
267 cl_addr.sin_family = AF_INET; 267 cl_addr.sin_family = AF_INET;
268 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY); 268 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
269 cl_addr.sin_port = htons(0); 269 cl_addr.sin_port = htons(0);
270 270
271 // enable broadcast: jdl ~2003 271 // enable broadcast: jdl ~2003
272 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) { 272 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
273 perror("setsockopt"); 273 perror("setsockopt");
274 } 274 }
275 275
276 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) { 276 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
277 perror("could not bind\n"); 277 perror("could not bind\n");
278 close(sockfd); 278 close(sockfd);
279 sockfd = -1; 279 sockfd = -1;
280 } 280 }
281 } 281 }
282 else { perror("unable to make socket\n");} 282 else { perror("unable to make socket\n");}
283 #endif 283 #endif
284 } 284 }
285 #ifdef WIN32 285 #ifdef WIN32
286 if(sockfd == INVALID_SOCKET) { 286 if(sockfd == INVALID_SOCKET) {
287 #else 287 #else
288 if(sockfd < 0) { 288 if(sockfd < 0) {
289 #endif 289 #endif
290 free(o); 290 free(o);
291 o = 0; 291 o = 0;
292 } 292 }
293 else 293 else
294 o->sockfd = sockfd; 294 o->sockfd = sockfd;
295 return o; 295 return o;
296} 296}
297 297
298static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b) 298static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b)
299{ 299{
300 int rcount; 300 int rcount;
301 if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count) 301 if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count)
302 { 302 {
303 printf("sockfd %d count %d rcount %dlength %d\n", sockfd,count,rcount,length); 303 printf("sockfd %d count %d rcount %dlength %d\n", sockfd,count,rcount,length);
304 return FALSE; 304 return FALSE;
305 } 305 }
306 return TRUE; 306 return TRUE;
307} 307}
308 308
309bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer) 309bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer)
310{ 310{
311 desc *o = (desc *)htmsendhandle; 311 desc *o = (desc *)htmsendhandle;
312 return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer); 312 return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer);
313} 313}
314void CloseHTMSocket(void *htmsendhandle) 314void CloseHTMSocket(void *htmsendhandle)
315{ 315{
316 desc *o = (desc *)htmsendhandle; 316 desc *o = (desc *)htmsendhandle;
317 #ifdef WIN32 317 #ifdef WIN32
318 if(SOCKET_ERROR == closesocket(o->sockfd)) { 318 if(SOCKET_ERROR == closesocket(o->sockfd)) {
319 perror("CloseHTMSocket::closesocket failed\n"); 319 perror("CloseHTMSocket::closesocket failed\n");
320 return; 320 return;
321 } 321 }
322 #else 322 #else
323 if(close(o->sockfd) == -1) 323 if(close(o->sockfd) == -1)
324 { 324 {
325 perror("CloseHTMSocket::closesocket failed"); 325 perror("CloseHTMSocket::closesocket failed");
326 return; 326 return;
327 } 327 }
328 #endif 328 #endif
329 329
330 free(o); 330 free(o);
331} 331}
332 332
333 333
334/////////////////////// 334///////////////////////
335// from sendOSC 335// from sendOSC
336 336
337typedef struct { 337typedef struct {
338 //enum {INT, FLOAT, STRING} type; 338 //enum {INT, FLOAT, STRING} type;
339 enum {INT_osc, FLOAT_osc, STRING_osc} type; 339 enum {INT_osc, FLOAT_osc, STRING_osc} type;
340 union { 340 union {
341 int i; 341 int i;
342 float f; 342 float f;
343 char *s; 343 char *s;
344 } datum; 344 } datum;
345} typedArg; 345} typedArg;
346 346
347void CommandLineMode(int argc, char *argv[], void *htmsocket); 347void CommandLineMode(int argc, char *argv[], void *htmsocket);
348OSCTimeTag ParseTimeTag(char *s); 348OSCTimeTag ParseTimeTag(char *s);
349void ParseInteractiveLine(OSCbuf *buf, char *mesg); 349void ParseInteractiveLine(OSCbuf *buf, char *mesg);
350typedArg ParseToken(char *token); 350typedArg ParseToken(char *token);
351int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args); 351int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args);
352void SendBuffer(void *htmsocket, OSCbuf *buf); 352void SendBuffer(void *htmsocket, OSCbuf *buf);
353void SendData(void *htmsocket, int size, char *data); 353void SendData(void *htmsocket, int size, char *data);
354/* defined in OSC-system-dependent.c now */ 354/* defined in OSC-system-dependent.c now */
355 355
356//static void *htmsocket; 356//static void *htmsocket;
357static int exitStatus = 0; 357static int exitStatus = 0;
358static int useTypeTags = 0; 358static int useTypeTags = 0;
359 359
360static char bufferForOSCbuf[SC_BUFFER_SIZE]; 360static char bufferForOSCbuf[SC_BUFFER_SIZE];
361 361
362 362
363///////// 363/////////
364// end from sendOSC 364// end from sendOSC
365 365
366static t_class *sendOSC_class; 366static t_class *sendOSC_class;
367 367
368typedef struct _sendOSC 368typedef struct _sendOSC
369{ 369{
370 t_object x_obj; 370 t_object x_obj;
371 int x_protocol; // UDP/TCP (udp only atm) 371 int x_protocol; // UDP/TCP (udp only atm)
372 t_int x_typetags; // typetag flag 372 t_int x_typetags; // typetag flag
373 void *x_htmsocket; // sending socket 373 void *x_htmsocket; // sending socket
374 int x_bundle; // bundle open flag 374 int x_bundle; // bundle open flag
375 OSCbuf x_oscbuf[1]; // OSCbuffer 375 OSCbuf x_oscbuf[1]; // OSCbuffer
376 t_outlet *x_bdpthout;// bundle-depth floatoutlet 376 t_outlet *x_bdpthout;// bundle-depth floatoutlet
377} t_sendOSC; 377} t_sendOSC;
378 378
379static void *sendOSC_new(t_floatarg udpflag) 379static void *sendOSC_new(t_floatarg udpflag)
380{ 380{
381 t_sendOSC *x = (t_sendOSC *)pd_new(sendOSC_class); 381 t_sendOSC *x = (t_sendOSC *)pd_new(sendOSC_class);
382 outlet_new(&x->x_obj, &s_float); 382 outlet_new(&x->x_obj, &s_float);
383 x->x_htmsocket = 0; // {{raf}} 383 x->x_htmsocket = 0; // {{raf}}
384 // set udp 384 // set udp
385 x->x_protocol = SOCK_STREAM; 385 x->x_protocol = SOCK_STREAM;
386 // set typetags to 1 by default 386 // set typetags to 1 by default
387 x->x_typetags = 1; 387 x->x_typetags = 1;
388 // bunlde is closed 388 // bunlde is closed
389 x->x_bundle = 0; 389 x->x_bundle = 0;
390 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf); 390 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
391 x->x_bdpthout = outlet_new(&x->x_obj, 0); // outlet_float(); 391 x->x_bdpthout = outlet_new(&x->x_obj, 0); // outlet_float();
392 //x->x_oscbuf = 392 //x->x_oscbuf =
393 return (x); 393 return (x);
394} 394}
395 395
396 396
397void sendOSC_openbundle(t_sendOSC *x) 397void sendOSC_openbundle(t_sendOSC *x)
398{ 398{
399 if (x->x_oscbuf->bundleDepth + 1 >= MAX_BUNDLE_NESTING || 399 if (x->x_oscbuf->bundleDepth + 1 >= MAX_BUNDLE_NESTING ||
400 OSC_openBundle(x->x_oscbuf, OSCTT_Immediately())) 400 OSC_openBundle(x->x_oscbuf, OSCTT_Immediately()))
401 { 401 {
402 post("Problem opening bundle: %s\n", OSC_errorMessage); 402 post("Problem opening bundle: %s\n", OSC_errorMessage);
403 return; 403 return;
404 } 404 }
405 x->x_bundle = 1; 405 x->x_bundle = 1;
406 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth); 406 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
407} 407}
408 408
409static void sendOSC_closebundle(t_sendOSC *x) 409static void sendOSC_closebundle(t_sendOSC *x)
410{ 410{
411 if (OSC_closeBundle(x->x_oscbuf)) { 411 if (OSC_closeBundle(x->x_oscbuf)) {
412 post("Problem closing bundle: %s\n", OSC_errorMessage); 412 post("Problem closing bundle: %s\n", OSC_errorMessage);
413 return; 413 return;
414 } 414 }
415 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth); 415 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
416 // in bundle mode we send when bundle is closed? 416 // in bundle mode we send when bundle is closed?
417 if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) { 417 if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) {
418 // post("x_oscbuf: something inside me?"); 418 // post("x_oscbuf: something inside me?");
419 if (x->x_htmsocket) { 419 if (x->x_htmsocket) {
420 SendBuffer(x->x_htmsocket, x->x_oscbuf); 420 SendBuffer(x->x_htmsocket, x->x_oscbuf);
421 } else { 421 } else {
422 post("sendOSC: not connected"); 422 post("sendOSC: not connected");
423 } 423 }
424 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf); 424 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
425 x->x_bundle = 0; 425 x->x_bundle = 0;
426 return; 426 return;
427 } 427 }
428 // post("x_oscbuf: something went wrong"); 428 // post("x_oscbuf: something went wrong");
429} 429}
430 430
431static void sendOSC_settypetags(t_sendOSC *x, t_float *f) 431static void sendOSC_settypetags(t_sendOSC *x, t_float *f)
432 { 432 {
433 x->x_typetags = (int)f; 433 x->x_typetags = (int)f;
434 post("sendOSC.c: setting typetags %d",x->x_typetags); 434 post("sendOSC.c: setting typetags %d",x->x_typetags);
435 } 435 }
436 436
437 437
438static void sendOSC_connect(t_sendOSC *x, t_symbol *hostname, 438static void sendOSC_connect(t_sendOSC *x, t_symbol *hostname,
439 t_floatarg fportno) 439 t_floatarg fportno)
440{ 440{
441 int portno = fportno; 441 int portno = fportno;
442 /* create a socket */ 442 /* create a socket */
443 443
444 // make sure handle is available 444 // make sure handle is available
445 if(x->x_htmsocket == 0) { 445 if(x->x_htmsocket == 0) {
446 // 446 //
447 x->x_htmsocket = OpenHTMSocket(hostname->s_name, portno); 447 x->x_htmsocket = OpenHTMSocket(hostname->s_name, portno);
448 if (!x->x_htmsocket) 448 if (!x->x_htmsocket)
449 post("Couldn't open socket: "); 449 post("Couldn't open socket: ");
450 else { 450 else {
451 post("connected to port %s:%d (hSock=%d)", hostname->s_name, portno, x->x_htmsocket); 451 post("connected to port %s:%d (hSock=%d)", hostname->s_name, portno, x->x_htmsocket);
452 outlet_float(x->x_obj.ob_outlet, 1); 452 outlet_float(x->x_obj.ob_outlet, 1);
453 } 453 }
454 } 454 }
455 else 455 else
456 perror("call to sendOSC_connect() against UNavailable socket handle"); 456 perror("call to sendOSC_connect() against UNavailable socket handle");
457} 457}
458 458
459void sendOSC_disconnect(t_sendOSC *x) 459void sendOSC_disconnect(t_sendOSC *x)
460{ 460{
461 if (x->x_htmsocket) 461 if (x->x_htmsocket)
462 { 462 {
463 post("disconnecting htmsock (hSock=%d)...", x->x_htmsocket); 463 post("disconnecting htmsock (hSock=%d)...", x->x_htmsocket);
464 CloseHTMSocket(x->x_htmsocket); 464 CloseHTMSocket(x->x_htmsocket);
465 x->x_htmsocket = 0; // {{raf}} semi-quasi-semaphorize this 465 x->x_htmsocket = 0; // {{raf}} semi-quasi-semaphorize this
466 outlet_float(x->x_obj.ob_outlet, 0); 466 outlet_float(x->x_obj.ob_outlet, 0);
467 } 467 }
468 else { 468 else {
469 perror("call to sendOSC_disconnect() against unused socket handle"); 469 perror("call to sendOSC_disconnect() against unused socket handle");
470 } 470 }
471} 471}
472 472
473void sendOSC_senduntyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv) 473void sendOSC_senduntyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
474{ 474{
475 char* targv[MAXPDARG]; 475 char* targv[MAXPDARG];
476 char tmparg[MAXPDSTRING]; 476 char tmparg[MAXPDSTRING];
477 char* tmp = tmparg; 477 char* tmp = tmparg;
478 //char testarg[MAXPDSTRING]; 478 //char testarg[MAXPDSTRING];
479 int c; 479 int c;
480 480
481 post("sendOSC: use typetags 0/1 message and plain send method so send untypetagged..."); 481 post("sendOSC: use typetags 0/1 message and plain send method so send untypetagged...");
482 return; 482 return;
483 483
484 //atom_string(argv,testarg, MAXPDSTRING); 484 //atom_string(argv,testarg, MAXPDSTRING);
485 for (c=0;c<argc;c++) { 485 for (c=0;c<argc;c++) {
486 atom_string(argv+c,tmp, 80); 486 atom_string(argv+c,tmp, 80);
487 targv[c] = tmp; 487 targv[c] = tmp;
488 tmp += strlen(tmp)+1; 488 tmp += strlen(tmp)+1;
489 } 489 }
490 490
491 // this sock needs to be larger than 0, not >= .. 491 // this sock needs to be larger than 0, not >= ..
492 if (x->x_htmsocket) 492 if (x->x_htmsocket)
493 { 493 {
494 CommandLineMode(argc, targv, x->x_htmsocket); 494 CommandLineMode(argc, targv, x->x_htmsocket);
495 // post("test %d", c); 495 // post("test %d", c);
496 } 496 }
497 else { 497 else {
498 post("sendOSC: not connected"); 498 post("sendOSC: not connected");
499 } 499 }
500} 500}
501 501
502////////////////////////////////////////////////////////////////////// 502//////////////////////////////////////////////////////////////////////
503// this is the real and only sending routine now, for both typed and 503// this is the real and only sending routine now, for both typed and
504// undtyped mode. 504// undtyped mode.
505 505
506static void sendOSC_sendtyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv) 506static void sendOSC_sendtyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
507{ 507{
508 char* targv[MAX_ARGS]; 508 char* targv[MAX_ARGS];
509 char tmparg[MAXPDSTRING]; 509 char tmparg[MAXPDSTRING];
510 char* tmp = tmparg; 510 char* tmp = tmparg;
511 int c; 511 int c;
512 512
513 char *messageName; 513 char *messageName;
514 char *token; 514 char *token;
515 typedArg args[MAX_ARGS]; 515 typedArg args[MAX_ARGS];
516 int i,j; 516 int i,j;
517 int numArgs = 0; 517 int numArgs = 0;
518 518
519 messageName = ""; 519 messageName = "";
520#ifdef DEBUG 520#ifdef DEBUG
521 post ("sendOSC: messageName: %s", messageName); 521 post ("sendOSC: messageName: %s", messageName);
522#endif 522#endif
523 523
524 524
525 525
526 for (c=0;c<argc;c++) { 526 for (c=0;c<argc;c++) {
527 atom_string(argv+c,tmp, 80); 527 atom_string(argv+c,tmp, 80);
528 528
529#ifdef DEBUG 529#ifdef DEBUG
530 // post ("sendOSC: %d, %s",c, tmp); 530 // post ("sendOSC: %d, %s",c, tmp);
531#endif 531#endif
532 532
533 targv[c] = tmp; 533 targv[c] = tmp;
534 tmp += strlen(tmp)+1; 534 tmp += strlen(tmp)+1;
535 535
536#ifdef DEBUG 536#ifdef DEBUG
537 // post ("sendOSC: %d, %s",c, targv[c]); 537 // post ("sendOSC: %d, %s",c, targv[c]);
538#endif 538#endif
539 } 539 }
540 540
541 // this sock needs to be larger than 0, not >= .. 541 // this sock needs to be larger than 0, not >= ..
542 if (x->x_htmsocket > 0) 542 if (x->x_htmsocket > 0)
543 { 543 {
544#ifdef DEBUG 544#ifdef DEBUG
545 post ("sendOSC: type tags? %d", useTypeTags); 545 post ("sendOSC: type tags? %d", useTypeTags);
546#endif 546#endif
547 547
548 messageName = strtok(targv[0], ","); 548 messageName = strtok(targv[0], ",");
549 j = 1; 549 j = 1;
550 for (i = j; i < argc; i++) { 550 for (i = j; i < argc; i++) {
551 token = strtok(targv[i],","); 551 token = strtok(targv[i],",");
552 args[i-j] = ParseToken(token); 552 args[i-j] = ParseToken(token);
553#ifdef DEBUG 553#ifdef DEBUG
554 printf("cell-cont: %s\n", targv[i]); 554 printf("cell-cont: %s\n", targv[i]);
555 printf(" type-id: %d\n", args[i-j]); 555 printf(" type-id: %d\n", args[i-j]);
556#endif 556#endif
557 numArgs = i; 557 numArgs = i;
558 } 558 }
559 559
560 560
561 if(WriteMessage(x->x_oscbuf, messageName, numArgs, args)) { 561 if(WriteMessage(x->x_oscbuf, messageName, numArgs, args)) {
562 post("sendOSC: usage error, write-msg failed: %s", OSC_errorMessage); 562 post("sendOSC: usage error, write-msg failed: %s", OSC_errorMessage);
563 return; 563 return;
564 } 564 }
565 565
566 if(!x->x_bundle) { 566 if(!x->x_bundle) {
567 SendBuffer(x->x_htmsocket, x->x_oscbuf); 567 SendBuffer(x->x_htmsocket, x->x_oscbuf);
568 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf); 568 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
569 } 569 }
570 570
571 //CommandLineMode(argc, targv, x->x_htmsocket); 571 //CommandLineMode(argc, targv, x->x_htmsocket);
572 //useTypeTags = 0; 572 //useTypeTags = 0;
573 } 573 }
574 else { 574 else {
575 post("sendOSC: not connected"); 575 post("sendOSC: not connected");
576 } 576 }
577} 577}
578 578
579void sendOSC_send(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv) 579void sendOSC_send(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
580{ 580{
581 if(!argc) { 581 if(!argc) {
582 post("not sending empty message."); 582 post("not sending empty message.");
583 return; 583 return;
584 } 584 }
585 if(x->x_typetags) { 585 if(x->x_typetags) {
586 useTypeTags = 1; 586 useTypeTags = 1;
587 sendOSC_sendtyped(x,s,argc,argv); 587 sendOSC_sendtyped(x,s,argc,argv);
588 useTypeTags = 0; 588 useTypeTags = 0;
589 } else { 589 } else {
590 sendOSC_sendtyped(x,s,argc,argv); 590 sendOSC_sendtyped(x,s,argc,argv);
591 } 591 }
592} 592}
593 593
594static void sendOSC_free(t_sendOSC *x) 594static void sendOSC_free(t_sendOSC *x)
595{ 595{
596 sendOSC_disconnect(x); 596 sendOSC_disconnect(x);
597} 597}
598 598
599#ifdef WIN32 599#ifdef WIN32
600 OSC_API void sendOSC_setup(void) { 600 OSC_API void sendOSC_setup(void) {
601#else 601#else
602 void sendOSC_setup(void) { 602 void sendOSC_setup(void) {
603#endif 603#endif
604 sendOSC_class = class_new(gensym("sendOSC"), (t_newmethod)sendOSC_new, 604 sendOSC_class = class_new(gensym("sendOSC"), (t_newmethod)sendOSC_new,
605 (t_method)sendOSC_free, 605 (t_method)sendOSC_free,
606 sizeof(t_sendOSC), 0, A_DEFFLOAT, 0); 606 sizeof(t_sendOSC), 0, A_DEFFLOAT, 0);
607 class_addmethod(sendOSC_class, (t_method)sendOSC_connect, 607 class_addmethod(sendOSC_class, (t_method)sendOSC_connect,
608 gensym("connect"), A_SYMBOL, A_FLOAT, 0); 608 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
609 class_addmethod(sendOSC_class, (t_method)sendOSC_disconnect, 609 class_addmethod(sendOSC_class, (t_method)sendOSC_disconnect,
610 gensym("disconnect"), 0); 610 gensym("disconnect"), 0);
611 class_addmethod(sendOSC_class, (t_method)sendOSC_settypetags, 611 class_addmethod(sendOSC_class, (t_method)sendOSC_settypetags,
612 gensym("typetags"), 612 gensym("typetags"),
613 A_FLOAT, 0); 613 A_FLOAT, 0);
614 class_addmethod(sendOSC_class, (t_method)sendOSC_send, 614 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
615 gensym("send"), 615 gensym("send"),
616 A_GIMME, 0); 616 A_GIMME, 0);
617 class_addmethod(sendOSC_class, (t_method)sendOSC_send, 617 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
618 gensym("senduntyped"), 618 gensym("senduntyped"),
619 A_GIMME, 0); 619 A_GIMME, 0);
620 class_addmethod(sendOSC_class, (t_method)sendOSC_send, 620 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
621 gensym("sendtyped"), 621 gensym("sendtyped"),
622 A_GIMME, 0); 622 A_GIMME, 0);
623 class_addmethod(sendOSC_class, (t_method)sendOSC_openbundle, 623 class_addmethod(sendOSC_class, (t_method)sendOSC_openbundle,
624 gensym("["), 624 gensym("["),
625 0, 0); 625 0, 0);
626 class_addmethod(sendOSC_class, (t_method)sendOSC_closebundle, 626 class_addmethod(sendOSC_class, (t_method)sendOSC_closebundle,
627 gensym("]"), 627 gensym("]"),
628 0, 0); 628 0, 0);
629 class_sethelpsymbol(sendOSC_class, gensym("sendOSC-help.pd")); 629 class_sethelpsymbol(sendOSC_class, gensym("sendOSC-help.pd"));
630} 630}
631 631
632 632
633 633
634 634
635 635
636/* Exit status codes: 636/* Exit status codes:
637 0: successful 637 0: successful
638 2: Message(s) dropped because of buffer overflow 638 2: Message(s) dropped because of buffer overflow
639 3: Socket error 639 3: Socket error
640 4: Usage error 640 4: Usage error
641 5: Internal error 641 5: Internal error
642*/ 642*/
643 643
644void CommandLineMode(int argc, char *argv[], void *htmsocket) { 644void CommandLineMode(int argc, char *argv[], void *htmsocket) {
645 char *messageName; 645 char *messageName;
646 char *token; 646 char *token;
647 typedArg args[MAX_ARGS]; 647 typedArg args[MAX_ARGS];
648 int i,j, numArgs; 648 int i,j, numArgs;
649 OSCbuf buf[1]; 649 OSCbuf buf[1];
650 650
651 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); 651 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
652 652
653 if (argc > 1) { 653 if (argc > 1) {
654 post("argc (%d) > 1", argc); 654 post("argc (%d) > 1", argc);
655 } 655 }
656 656
657 // ParseInteractiveLine(buf, argv); 657 // ParseInteractiveLine(buf, argv);
658 messageName = strtok(argv[0], ","); 658 messageName = strtok(argv[0], ",");
659 659
660 j = 1; 660 j = 1;
661 for (i = j; i < argc; i++) { 661 for (i = j; i < argc; i++) {
662 token = strtok(argv[i],","); 662 token = strtok(argv[i],",");
663 args[i-j] = ParseToken(token); 663 args[i-j] = ParseToken(token);
664#ifdef DEBUG 664#ifdef DEBUG
665 printf("cell-cont: %s\n", argv[i]); 665 printf("cell-cont: %s\n", argv[i]);
666 printf(" type-id: %d\n", args[i-j]); 666 printf(" type-id: %d\n", args[i-j]);
667#endif 667#endif
668 numArgs = i; 668 numArgs = i;
669 } 669 }
670 670
671 if(WriteMessage(buf, messageName, numArgs, args)) { 671 if(WriteMessage(buf, messageName, numArgs, args)) {
672 post("sendOSC: usage error. write-msg failed: %s", OSC_errorMessage); 672 post("sendOSC: usage error. write-msg failed: %s", OSC_errorMessage);
673 return; 673 return;
674 } 674 }
675 675
676 SendBuffer(htmsocket, buf); 676 SendBuffer(htmsocket, buf);
677} 677}
678 678
679#define MAXMESG 2048 679#define MAXMESG 2048
680 680
681void InteractiveMode(void *htmsocket) { 681void InteractiveMode(void *htmsocket) {
682 char mesg[MAXMESG]; 682 char mesg[MAXMESG];
683 OSCbuf buf[1]; 683 OSCbuf buf[1];
684 int bundleDepth = 0; /* At first, we haven't seen "[". */ 684 int bundleDepth = 0; /* At first, we haven't seen "[". */
685 685
686 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); 686 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
687 687
688 while (fgets(mesg, MAXMESG, stdin) != NULL) { 688 while (fgets(mesg, MAXMESG, stdin) != NULL) {
689 if (mesg[0] == '\n') { 689 if (mesg[0] == '\n') {
690 if (bundleDepth > 0) { 690 if (bundleDepth > 0) {
691 /* Ignore blank lines inside a group. */ 691 /* Ignore blank lines inside a group. */
692 } else { 692 } else {
693 /* blank line => repeat previous send */ 693 /* blank line => repeat previous send */
694 SendBuffer(htmsocket, buf); 694 SendBuffer(htmsocket, buf);
695 } 695 }
696 continue; 696 continue;
697 } 697 }
698 698
699 if (bundleDepth == 0) { 699 if (bundleDepth == 0) {
700 OSC_resetBuffer(buf); 700 OSC_resetBuffer(buf);
701 } 701 }
702 702
703 if (mesg[0] == '[') { 703 if (mesg[0] == '[') {
704 OSCTimeTag tt = ParseTimeTag(mesg+1); 704 OSCTimeTag tt = ParseTimeTag(mesg+1);
705 if (OSC_openBundle(buf, tt)) { 705 if (OSC_openBundle(buf, tt)) {
706 post("Problem opening bundle: %s\n", OSC_errorMessage); 706 post("Problem opening bundle: %s\n", OSC_errorMessage);
707 OSC_resetBuffer(buf); 707 OSC_resetBuffer(buf);
708 bundleDepth = 0; 708 bundleDepth = 0;
709 continue; 709 continue;
710 } 710 }
711 bundleDepth++; 711 bundleDepth++;
712 } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') { 712 } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') {
713 if (bundleDepth == 0) { 713 if (bundleDepth == 0) {
714 post("Unexpected ']': not currently in a bundle.\n"); 714 post("Unexpected ']': not currently in a bundle.\n");
715 } else { 715 } else {
716 if (OSC_closeBundle(buf)) { 716 if (OSC_closeBundle(buf)) {
717 post("Problem closing bundle: %s\n", OSC_errorMessage); 717 post("Problem closing bundle: %s\n", OSC_errorMessage);
718 OSC_resetBuffer(buf); 718 OSC_resetBuffer(buf);
719 bundleDepth = 0; 719 bundleDepth = 0;
720 continue; 720 continue;
721 } 721 }
722 722
723 bundleDepth--; 723 bundleDepth--;
724 if (bundleDepth == 0) { 724 if (bundleDepth == 0) {
725 SendBuffer(htmsocket, buf); 725 SendBuffer(htmsocket, buf);
726 } 726 }
727 } 727 }
728 } else { 728 } else {
729 ParseInteractiveLine(buf, mesg); 729 ParseInteractiveLine(buf, mesg);
730 if (bundleDepth != 0) { 730 if (bundleDepth != 0) {
731 /* Don't send anything until we close all bundles */ 731 /* Don't send anything until we close all bundles */
732 } else { 732 } else {
733 SendBuffer(htmsocket, buf); 733 SendBuffer(htmsocket, buf);
734 } 734 }
735 } 735 }
736 } 736 }
737} 737}
738 738
739OSCTimeTag ParseTimeTag(char *s) { 739OSCTimeTag ParseTimeTag(char *s) {
740 char *p, *newline; 740 char *p, *newline;
741 typedArg arg; 741 typedArg arg;
742 742
743 p = s; 743 p = s;
744 while (isspace(*p)) p++; 744 while (isspace(*p)) p++;
745 if (*p == '\0') return OSCTT_Immediately(); 745 if (*p == '\0') return OSCTT_Immediately();
746 746
747 if (*p == '+') { 747 if (*p == '+') {
748 /* Time tag is for some time in the future. It should be a 748 /* Time tag is for some time in the future. It should be a
749 number of seconds as an int or float */ 749 number of seconds as an int or float */
750 750
751 newline = strchr(s, '\n'); 751 newline = strchr(s, '\n');
752 if (newline != NULL) *newline = '\0'; 752 if (newline != NULL) *newline = '\0';
753 753
754 p++; /* Skip '+' */ 754 p++; /* Skip '+' */
755 while (isspace(*p)) p++; 755 while (isspace(*p)) p++;
756 756
757 arg = ParseToken(p); 757 arg = ParseToken(p);
758 if (arg.type == STRING_osc) { 758 if (arg.type == STRING_osc) {
759 post("warning: inscrutable time tag request: %s\n", s); 759 post("warning: inscrutable time tag request: %s\n", s);
760 return OSCTT_Immediately(); 760 return OSCTT_Immediately();
761 } else if (arg.type == INT_osc) { 761 } else if (arg.type == INT_osc) {
762 return OSCTT_PlusSeconds(OSCTT_CurrentTime(), 762 return OSCTT_PlusSeconds(OSCTT_CurrentTime(),
763 (float) arg.datum.i); 763 (float) arg.datum.i);
764 } else if (arg.type == FLOAT_osc) { 764 } else if (arg.type == FLOAT_osc) {
765 return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f); 765 return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f);
766 } else { 766 } else {
767 error("This can't happen!"); 767 error("This can't happen!");
768 } 768 }
769 } 769 }
770 770
771 if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) { 771 if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) {
772 /* They specified the 8-byte tag in hex */ 772 /* They specified the 8-byte tag in hex */
773 OSCTimeTag tt; 773 OSCTimeTag tt;
774 if (sscanf(p, "%llx", &tt) != 1) { 774 if (sscanf(p, "%llx", &tt) != 1) {
775 post("warning: couldn't parse time tag %s\n", s); 775 post("warning: couldn't parse time tag %s\n", s);
776 return OSCTT_Immediately(); 776 return OSCTT_Immediately();
777 } 777 }
778#ifndef HAS8BYTEINT 778#ifndef HAS8BYTEINT
779 if (ntohl(1) != 1) { 779 if (ntohl(1) != 1) {
780 /* tt is a struct of seconds and fractional part, 780 /* tt is a struct of seconds and fractional part,
781 and this machine is little-endian, so sscanf 781 and this machine is little-endian, so sscanf
782 wrote each half of the time tag in the wrong half 782 wrote each half of the time tag in the wrong half
783 of the struct. */ 783 of the struct. */
784 int temp; 784 int temp;
785 temp = tt.seconds; 785 temp = tt.seconds;
786 tt.seconds = tt.fraction ; 786 tt.seconds = tt.fraction ;
787 tt.fraction = temp; 787 tt.fraction = temp;
788 } 788 }
789#endif 789#endif
790 return tt; 790 return tt;
791 } 791 }
792 792
793 post("warning: invalid time tag: %s\n", s); 793 post("warning: invalid time tag: %s\n", s);
794 return OSCTT_Immediately(); 794 return OSCTT_Immediately();
795} 795}
796 796
797 797
798void ParseInteractiveLine(OSCbuf *buf, char *mesg) { 798void ParseInteractiveLine(OSCbuf *buf, char *mesg) {
799 char *messageName, *token, *p; 799 char *messageName, *token, *p;
800 typedArg args[MAX_ARGS]; 800 typedArg args[MAX_ARGS];
801 int thisArg; 801 int thisArg;
802 802
803 p = mesg; 803 p = mesg;
804 while (isspace(*p)) p++; 804 while (isspace(*p)) p++;
805 if (*p == '\0') return; 805 if (*p == '\0') return;
806 806
807 messageName = p; 807 messageName = p;
808 808
809 if (strcmp(messageName, "play\n") == 0) { 809 if (strcmp(messageName, "play\n") == 0) {
810 /* Special kludge feature to save typing */ 810 /* Special kludge feature to save typing */
811 typedArg arg; 811 typedArg arg;
812 812
813 if (OSC_openBundle(buf, OSCTT_Immediately())) { 813 if (OSC_openBundle(buf, OSCTT_Immediately())) {
814 post("Problem opening bundle: %s\n", OSC_errorMessage); 814 post("Problem opening bundle: %s\n", OSC_errorMessage);
815 return; 815 return;
816 } 816 }
817 817
818 arg.type = INT_osc; 818 arg.type = INT_osc;
819 arg.datum.i = 0; 819 arg.datum.i = 0;
820 WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg); 820 WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg);
821 821
822 arg.type = FLOAT_osc; 822 arg.type = FLOAT_osc;
823 arg.datum.i = 0.0f; 823 arg.datum.i = 0.0f;
824 WriteMessage(buf, "/voices/0/tm/goto", 1, &arg); 824 WriteMessage(buf, "/voices/0/tm/goto", 1, &arg);
825 825
826 if (OSC_closeBundle(buf)) { 826 if (OSC_closeBundle(buf)) {
827 post("Problem closing bundle: %s\n", OSC_errorMessage); 827 post("Problem closing bundle: %s\n", OSC_errorMessage);
828 } 828 }
829 829
830 return; 830 return;
831 } 831 }
832 832
833 while (!isspace(*p) && *p != '\0') p++; 833 while (!isspace(*p) && *p != '\0') p++;
834 if (isspace(*p)) { 834 if (isspace(*p)) {
835 *p = '\0'; 835 *p = '\0';
836 p++; 836 p++;
837 } 837 }
838 838
839 thisArg = 0; 839 thisArg = 0;
840 while (*p != '\0') { 840 while (*p != '\0') {
841 /* flush leading whitespace */ 841 /* flush leading whitespace */
842 while (isspace(*p)) p++; 842 while (isspace(*p)) p++;
843 if (*p == '\0') break; 843 if (*p == '\0') break;
844 844
845 if (*p == '"') { 845 if (*p == '"') {
846 /* A string argument: scan for close quotes */ 846 /* A string argument: scan for close quotes */
847 p++; 847 p++;
848 args[thisArg].type = STRING_osc; 848 args[thisArg].type = STRING_osc;
849 args[thisArg].datum.s = p; 849 args[thisArg].datum.s = p;
850 850
851 while (*p != '"') { 851 while (*p != '"') {
852 if (*p == '\0') { 852 if (*p == '\0') {
853 post("Unterminated quote mark: ignoring line\n"); 853 post("Unterminated quote mark: ignoring line\n");
854 return; 854 return;
855 } 855 }
856 p++; 856 p++;
857 } 857 }
858 *p = '\0'; 858 *p = '\0';
859 p++; 859 p++;
860 } else { 860 } else {
861 token = p; 861 token = p;
862 while (!isspace(*p) && (*p != '\0')) p++; 862 while (!isspace(*p) && (*p != '\0')) p++;
863 if (isspace(*p)) { 863 if (isspace(*p)) {
864 *p = '\0'; 864 *p = '\0';
865 p++; 865 p++;
866 } 866 }
867 args[thisArg] = ParseToken(token); 867 args[thisArg] = ParseToken(token);
868 } 868 }
869 thisArg++; 869 thisArg++;
870 if (thisArg >= MAX_ARGS) { 870 if (thisArg >= MAX_ARGS) {
871 post("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n", 871 post("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n",
872 MAX_ARGS); 872 MAX_ARGS);
873 break; 873 break;
874 } 874 }
875 } 875 }
876 876
877 if (WriteMessage(buf, messageName, thisArg, args) != 0) { 877 if (WriteMessage(buf, messageName, thisArg, args) != 0) {
878 post("Problem sending message: %s\n", OSC_errorMessage); 878 post("Problem sending message: %s\n", OSC_errorMessage);
879 } 879 }
880} 880}
881 881
882typedArg ParseToken(char *token) { 882typedArg ParseToken(char *token) {
883 char *p = token; 883 char *p = token;
884 typedArg returnVal; 884 typedArg returnVal;
885 885
886 /* It might be an int, a float, or a string */ 886 /* It might be an int, a float, or a string */
887 887
888 if (*p == '-') p++; 888 if (*p == '-') p++;
889 889
890 if (isdigit(*p) || *p == '.') { 890 if (isdigit(*p) || *p == '.') {
891 while (isdigit(*p)) p++; 891 while (isdigit(*p)) p++;
892 if (*p == '\0') { 892 if (*p == '\0') {
893 returnVal.type = INT_osc; 893 returnVal.type = INT_osc;
894 returnVal.datum.i = atoi(token); 894 returnVal.datum.i = atoi(token);
895 return returnVal; 895 return returnVal;
896 } 896 }
897 if (*p == '.') { 897 if (*p == '.') {
898 p++; 898 p++;
899 while (isdigit(*p)) p++; 899 while (isdigit(*p)) p++;
900 if (*p == '\0') { 900 if (*p == '\0') {
901 returnVal.type = FLOAT_osc; 901 returnVal.type = FLOAT_osc;
902 returnVal.datum.f = atof(token); 902 returnVal.datum.f = atof(token);
903 return returnVal; 903 return returnVal;
904 } 904 }
905 } 905 }
906 } 906 }
907 907
908 returnVal.type = STRING_osc; 908 returnVal.type = STRING_osc;
909 returnVal.datum.s = token; 909 returnVal.datum.s = token;
910 return returnVal; 910 return returnVal;
911} 911}
912 912
913int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) { 913int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) {
914 int j, returnVal; 914 int j, returnVal;
915 const int wmERROR = -1; 915 const int wmERROR = -1;
916 916
917 returnVal = 0; 917 returnVal = 0;
918 918
919#ifdef DEBUG 919#ifdef DEBUG
920 printf("WriteMessage: %s ", messageName); 920 printf("WriteMessage: %s ", messageName);
921 921
922 for (j = 0; j < numArgs; j++) { 922 for (j = 0; j < numArgs; j++) {
923 switch (args[j].type) { 923 switch (args[j].type) {
924 case INT_osc: 924 case INT_osc:
925 printf("%d ", args[j].datum.i); 925 printf("%d ", args[j].datum.i);
926 break; 926 break;
927 927
928 case FLOAT_osc: 928 case FLOAT_osc:
929 printf("%f ", args[j].datum.f); 929 printf("%f ", args[j].datum.f);
930 break; 930 break;
931 931
932 case STRING_osc: 932 case STRING_osc:
933 printf("%s ", args[j].datum.s); 933 printf("%s ", args[j].datum.s);
934 break; 934 break;
935 935
936 default: 936 default:
937 error("Unrecognized arg type, (not exiting)"); 937 error("Unrecognized arg type, (not exiting)");
938 return(wmERROR); 938 return(wmERROR);
939 } 939 }
940 } 940 }
941 printf("\n"); 941 printf("\n");
942#endif 942#endif
943 943
944 if (!useTypeTags) { 944 if (!useTypeTags) {
945 returnVal = OSC_writeAddress(buf, messageName); 945 returnVal = OSC_writeAddress(buf, messageName);
946 if (returnVal) { 946 if (returnVal) {
947 post("Problem writing address: %s\n", OSC_errorMessage); 947 post("Problem writing address: %s\n", OSC_errorMessage);
948 } 948 }
949 } else { 949 } else {
950 /* First figure out the type tags */ 950 /* First figure out the type tags */
951 char typeTags[MAX_ARGS+2]; 951 char typeTags[MAX_ARGS+2];
952 int i; 952 int i;
953 953
954 typeTags[0] = ','; 954 typeTags[0] = ',';
955 955
956 for (i = 0; i < numArgs; ++i) { 956 for (i = 0; i < numArgs; ++i) {
957 switch (args[i].type) { 957 switch (args[i].type) {
958 case INT_osc: 958 case INT_osc:
959 typeTags[i+1] = 'i'; 959 typeTags[i+1] = 'i';
960 break; 960 break;
961 961
962 case FLOAT_osc: 962 case FLOAT_osc:
963 typeTags[i+1] = 'f'; 963 typeTags[i+1] = 'f';
964 break; 964 break;
965 965
966 case STRING_osc: 966 case STRING_osc:
967 typeTags[i+1] = 's'; 967 typeTags[i+1] = 's';
968 break; 968 break;
969 969
970 default: 970 default:
971 error("Unrecognized arg type (not exiting)"); 971 error("Unrecognized arg type (not exiting)");
972 return(wmERROR); 972 return(wmERROR);
973 } 973 }
974 } 974 }
975 typeTags[i+1] = '\0'; 975 typeTags[i+1] = '\0';
976 976
977 returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags); 977 returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags);
978 if (returnVal) { 978 if (returnVal) {
979 post("Problem writing address: %s\n", OSC_errorMessage); 979 post("Problem writing address: %s\n", OSC_errorMessage);
980 } 980 }
981 } 981 }
982 982
983 for (j = 0; j < numArgs; j++) { 983 for (j = 0; j < numArgs; j++) {
984 switch (args[j].type) { 984 switch (args[j].type) {
985 case INT_osc: 985 case INT_osc:
986 if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) { 986 if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) {
987 return returnVal; 987 return returnVal;
988 } 988 }
989 break; 989 break;
990 990
991 case FLOAT_osc: 991 case FLOAT_osc:
992 if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) { 992 if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) {
993 return returnVal; 993 return returnVal;
994 } 994 }
995 break; 995 break;
996 996
997 case STRING_osc: 997 case STRING_osc:
998 if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) { 998 if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) {
999 return returnVal; 999 return returnVal;
1000 } 1000 }
1001 break; 1001 break;
1002 1002
1003 default: 1003 default:
1004 error("Unrecognized arg type (not exiting)"); 1004 error("Unrecognized arg type (not exiting)");
1005 returnVal = wmERROR; 1005 returnVal = wmERROR;
1006 } 1006 }
1007 } 1007 }
1008 return returnVal; 1008 return returnVal;
1009} 1009}
1010 1010
1011void SendBuffer(void *htmsocket, OSCbuf *buf) { 1011void SendBuffer(void *htmsocket, OSCbuf *buf) {
1012#ifdef DEBUG 1012#ifdef DEBUG
1013 printf("Sending buffer...\n"); 1013 printf("Sending buffer...\n");
1014#endif 1014#endif
1015 if (OSC_isBufferEmpty(buf)) { 1015 if (OSC_isBufferEmpty(buf)) {
1016 post("SendBuffer() called but buffer empty"); 1016 post("SendBuffer() called but buffer empty");
1017 return; 1017 return;
1018 } 1018 }
1019 if (!OSC_isBufferDone(buf)) { 1019 if (!OSC_isBufferDone(buf)) {
1020 error("SendBuffer() called but buffer not ready!, not exiting"); 1020 error("SendBuffer() called but buffer not ready!, not exiting");
1021 return; //{{raf}} 1021 return; //{{raf}}
1022 } 1022 }
1023 SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf)); 1023 SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf));
1024} 1024}
1025 1025
1026void SendData(void *htmsocket, int size, char *data) { 1026void SendData(void *htmsocket, int size, char *data) {
1027 if (!SendHTMSocket(htmsocket, size, data)) { 1027 if (!SendHTMSocket(htmsocket, size, data)) {
1028 post("SendData::SendHTMSocket()failure -- not connected"); 1028 post("SendData::SendHTMSocket()failure -- not connected");
1029 CloseHTMSocket(htmsocket); 1029 CloseHTMSocket(htmsocket);
1030 } 1030 }
1031} 1031}
1032 1032
1033 1033
1034 1034
1035/* ---------------------- 1035/* ----------------------
1036 OSC-client code 1036 OSC-client code
1037 1037
1038 */ 1038 */
1039 1039
1040/* Here are the possible values of the state field: */ 1040/* Here are the possible values of the state field: */
1041 1041
1042#define EMPTY 0 /* Nothing written to packet yet */ 1042#define EMPTY 0 /* Nothing written to packet yet */
1043#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */ 1043#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
1044#define NEED_COUNT 2 /* Just opened a bundle; must write message name or 1044#define NEED_COUNT 2 /* Just opened a bundle; must write message name or
1045 open another bundle */ 1045 open another bundle */
1046#define GET_ARGS 3 /* Getting arguments to a message. If we see a message 1046#define GET_ARGS 3 /* Getting arguments to a message. If we see a message
1047 name or a bundle open/close then the current message 1047 name or a bundle open/close then the current message
1048 will end. */ 1048 will end. */
1049#define DONE 4 /* All open bundles have been closed, so can't write 1049#define DONE 4 /* All open bundles have been closed, so can't write
1050 anything else */ 1050 anything else */
1051 1051
1052#ifdef WIN32 1052#ifdef WIN32
1053 #include <winsock2.h> 1053 #include <winsock2.h>
1054 #include <io.h> 1054 #include <io.h>
1055 #include <stdio.h> 1055 #include <stdio.h>
1056 #include <errno.h> 1056 #include <errno.h>
1057 #include <fcntl.h> 1057 #include <fcntl.h>
1058 #include <sys/types.h> 1058 #include <sys/types.h>
1059 #include <sys/stat.h> 1059 #include <sys/stat.h>
1060#endif 1060#endif
1061 1061
1062#ifdef __APPLE__ 1062#ifdef __APPLE__
1063 #include <sys/types.h> 1063 #include <sys/types.h>
1064#endif 1064#endif
1065 1065
1066#ifdef unix 1066#ifdef unix
1067 #include <netinet/in.h> 1067 #include <netinet/in.h>
1068 #include <stdio.h> 1068 #include <stdio.h>
1069#endif 1069#endif
1070 1070
1071 1071
1072char *OSC_errorMessage; 1072char *OSC_errorMessage;
1073 1073
1074static int OSC_padString(char *dest, char *str); 1074static int OSC_padString(char *dest, char *str);
1075static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str); 1075static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
1076static int OSC_WritePadding(char *dest, int i); 1076static int OSC_WritePadding(char *dest, int i);
1077static int CheckTypeTag(OSCbuf *buf, char expectedType); 1077static int CheckTypeTag(OSCbuf *buf, char expectedType);
1078 1078
1079void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) { 1079void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
1080 buf->buffer = byteArray; 1080 buf->buffer = byteArray;
1081 buf->size = size; 1081 buf->size = size;
1082 OSC_resetBuffer(buf); 1082 OSC_resetBuffer(buf);
1083} 1083}
1084 1084
1085void OSC_resetBuffer(OSCbuf *buf) { 1085void OSC_resetBuffer(OSCbuf *buf) {
1086 buf->bufptr = buf->buffer; 1086 buf->bufptr = buf->buffer;
1087 buf->state = EMPTY; 1087 buf->state = EMPTY;
1088 buf->bundleDepth = 0; 1088 buf->bundleDepth = 0;
1089 buf->prevCounts[0] = 0; 1089 buf->prevCounts[0] = 0;
1090 buf->gettingFirstUntypedArg = 0; 1090 buf->gettingFirstUntypedArg = 0;
1091 buf->typeStringPtr = 0; 1091 buf->typeStringPtr = 0;
1092} 1092}
1093 1093
1094int OSC_isBufferEmpty(OSCbuf *buf) { 1094int OSC_isBufferEmpty(OSCbuf *buf) {
1095 return buf->bufptr == buf->buffer; 1095 return buf->bufptr == buf->buffer;
1096} 1096}
1097 1097
1098int OSC_freeSpaceInBuffer(OSCbuf *buf) { 1098int OSC_freeSpaceInBuffer(OSCbuf *buf) {
1099 return buf->size - (buf->bufptr - buf->buffer); 1099 return buf->size - (buf->bufptr - buf->buffer);
1100} 1100}
1101 1101
1102int OSC_isBufferDone(OSCbuf *buf) { 1102int OSC_isBufferDone(OSCbuf *buf) {
1103 return (buf->state == DONE || buf->state == ONE_MSG_ARGS); 1103 return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
1104} 1104}
1105 1105
1106char *OSC_getPacket(OSCbuf *buf) { 1106char *OSC_getPacket(OSCbuf *buf) {
1107#ifdef ERROR_CHECK_GETPACKET 1107#ifdef ERROR_CHECK_GETPACKET
1108 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { 1108 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
1109 return buf->buffer; 1109 return buf->buffer;
1110 } else { 1110 } else {
1111 OSC_errorMessage = "Packet has unterminated bundles"; 1111 OSC_errorMessage = "Packet has unterminated bundles";
1112 return 0; 1112 return 0;
1113 } 1113 }
1114#else 1114#else
1115 return buf->buffer; 1115 return buf->buffer;
1116#endif 1116#endif
1117} 1117}
1118 1118
1119int OSC_packetSize(OSCbuf *buf) { 1119int OSC_packetSize(OSCbuf *buf) {
1120#ifdef ERROR_CHECK_PACKETSIZE 1120#ifdef ERROR_CHECK_PACKETSIZE
1121 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { 1121 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
1122 return (buf->bufptr - buf->buffer); 1122 return (buf->bufptr - buf->buffer);
1123 } else { 1123 } else {
1124 OSC_errorMessage = "Packet has unterminated bundles"; 1124 OSC_errorMessage = "Packet has unterminated bundles";
1125 return 0; 1125 return 0;
1126 } 1126 }
1127#else 1127#else
1128 return (buf->bufptr - buf->buffer); 1128 return (buf->bufptr - buf->buffer);
1129#endif 1129#endif
1130} 1130}
1131 1131
1132#define CheckOverflow(buf, bytesNeeded) { if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) {OSC_errorMessage = "buffer overflow"; return 1;}} 1132#define CheckOverflow(buf, bytesNeeded) { if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) {OSC_errorMessage = "buffer overflow"; return 1;}}
1133 1133
1134static void PatchMessageSize(OSCbuf *buf) { 1134static void PatchMessageSize(OSCbuf *buf) {
1135 int4byte size; 1135 int4byte size;
1136 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; 1136 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
1137 *(buf->thisMsgSize) = htonl(size); 1137 *(buf->thisMsgSize) = htonl(size);
1138} 1138}
1139 1139
1140int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) { 1140int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
1141 if (buf->state == ONE_MSG_ARGS) { 1141 if (buf->state == ONE_MSG_ARGS) {
1142 OSC_errorMessage = "Can't open a bundle in a one-message packet"; 1142 OSC_errorMessage = "Can't open a bundle in a one-message packet";
1143 return 3; 1143 return 3;
1144 } 1144 }
1145 1145
1146 if (buf->state == DONE) { 1146 if (buf->state == DONE) {
1147 OSC_errorMessage = "This packet is finished; can't open a new bundle"; 1147 OSC_errorMessage = "This packet is finished; can't open a new bundle";
1148 return 4; 1148 return 4;
1149 } 1149 }
1150 1150
1151 if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) { 1151 if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
1152 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h"; 1152 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
1153 return 2; 1153 return 2;
1154 } 1154 }
1155 1155
1156 if (CheckTypeTag(buf, '\0')) return 9; 1156 if (CheckTypeTag(buf, '\0')) return 9;
1157 1157
1158 if (buf->state == GET_ARGS) { 1158 if (buf->state == GET_ARGS) {
1159 PatchMessageSize(buf); 1159 PatchMessageSize(buf);
1160 } 1160 }
1161 1161
1162 if (buf->state == EMPTY) { 1162 if (buf->state == EMPTY) {
1163 /* Need 16 bytes for "#bundle" and time tag */ 1163 /* Need 16 bytes for "#bundle" and time tag */
1164 CheckOverflow(buf, 16); 1164 CheckOverflow(buf, 16);
1165 } else { 1165 } else {
1166 /* This bundle is inside another bundle, so we need to leave 1166 /* This bundle is inside another bundle, so we need to leave
1167 a blank size count for the size of this current bundle. */ 1167 a blank size count for the size of this current bundle. */
1168 CheckOverflow(buf, 20); 1168 CheckOverflow(buf, 20);
1169 *((int4byte *)buf->bufptr) = 0xaaaaaaaa; 1169 *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
1170 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr; 1170 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
1171 1171
1172 buf->bufptr += 4; 1172 buf->bufptr += 4;
1173 } 1173 }
1174 1174
1175 buf->bufptr += OSC_padString(buf->bufptr, "#bundle"); 1175 buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
1176 1176
1177 1177
1178 *((OSCTimeTag *) buf->bufptr) = tt; 1178 *((OSCTimeTag *) buf->bufptr) = tt;
1179 1179
1180 if (htonl(1) != 1) { 1180 if (htonl(1) != 1) {
1181 /* Byte swap the 8-byte integer time tag */ 1181 /* Byte swap the 8-byte integer time tag */
1182 int4byte *intp = (int4byte *)buf->bufptr; 1182 int4byte *intp = (int4byte *)buf->bufptr;
1183 intp[0] = htonl(intp[0]); 1183 intp[0] = htonl(intp[0]);
1184 intp[1] = htonl(intp[1]); 1184 intp[1] = htonl(intp[1]);
1185 1185
1186#ifdef HAS8BYTEINT 1186#ifdef HAS8BYTEINT
1187 { /* tt is a 64-bit int so we have to swap the two 32-bit words. 1187 { /* tt is a 64-bit int so we have to swap the two 32-bit words.
1188 (Otherwise tt is a struct of two 32-bit words, and even though 1188 (Otherwise tt is a struct of two 32-bit words, and even though
1189 each word was wrong-endian, they were in the right order 1189 each word was wrong-endian, they were in the right order
1190 in the struct.) */ 1190 in the struct.) */
1191 int4byte temp = intp[0]; 1191 int4byte temp = intp[0];
1192 intp[0] = intp[1]; 1192 intp[0] = intp[1];
1193 intp[1] = temp; 1193 intp[1] = temp;
1194 } 1194 }
1195#endif 1195#endif
1196 } 1196 }
1197 1197
1198 buf->bufptr += sizeof(OSCTimeTag); 1198 buf->bufptr += sizeof(OSCTimeTag);
1199 1199
1200 buf->state = NEED_COUNT; 1200 buf->state = NEED_COUNT;
1201 1201
1202 buf->gettingFirstUntypedArg = 0; 1202 buf->gettingFirstUntypedArg = 0;
1203 buf->typeStringPtr = 0; 1203 buf->typeStringPtr = 0;
1204 return 0; 1204 return 0;
1205} 1205}
1206 1206
1207 1207
1208int OSC_closeBundle(OSCbuf *buf) { 1208int OSC_closeBundle(OSCbuf *buf) {
1209 if (buf->bundleDepth == 0) { 1209 if (buf->bundleDepth == 0) {
1210 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ 1210 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
1211 OSC_errorMessage = "Can't close bundle; no bundle is open!"; 1211 OSC_errorMessage = "Can't close bundle; no bundle is open!";
1212 return 5; 1212 return 5;
1213 } 1213 }
1214 1214
1215 if (CheckTypeTag(buf, '\0')) return 9; 1215 if (CheckTypeTag(buf, '\0')) return 9;
1216 1216
1217 if (buf->state == GET_ARGS) { 1217 if (buf->state == GET_ARGS) {
1218 PatchMessageSize(buf); 1218 PatchMessageSize(buf);
1219 } 1219 }
1220 1220
1221 if (buf->bundleDepth == 1) { 1221 if (buf->bundleDepth == 1) {
1222 /* Closing the last bundle: No bundle size to patch */ 1222 /* Closing the last bundle: No bundle size to patch */
1223 buf->state = DONE; 1223 buf->state = DONE;
1224 } else { 1224 } else {
1225 /* Closing a sub-bundle: patch bundle size */ 1225 /* Closing a sub-bundle: patch bundle size */
1226 int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4; 1226 int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
1227 *(buf->prevCounts[buf->bundleDepth]) = htonl(size); 1227 *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
1228 buf->state = NEED_COUNT; 1228 buf->state = NEED_COUNT;
1229 } 1229 }
1230 1230
1231 --buf->bundleDepth; 1231 --buf->bundleDepth;
1232 buf->gettingFirstUntypedArg = 0; 1232 buf->gettingFirstUntypedArg = 0;
1233 buf->typeStringPtr = 0; 1233 buf->typeStringPtr = 0;
1234 return 0; 1234 return 0;
1235} 1235}
1236 1236
1237 1237
1238int OSC_closeAllBundles(OSCbuf *buf) { 1238int OSC_closeAllBundles(OSCbuf *buf) {
1239 if (buf->bundleDepth == 0) { 1239 if (buf->bundleDepth == 0) {
1240 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ 1240 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
1241 OSC_errorMessage = "Can't close all bundles; no bundle is open!"; 1241 OSC_errorMessage = "Can't close all bundles; no bundle is open!";
1242 return 6; 1242 return 6;
1243 } 1243 }
1244 1244
1245 if (CheckTypeTag(buf, '\0')) return 9; 1245 if (CheckTypeTag(buf, '\0')) return 9;
1246 1246
1247 while (buf->bundleDepth > 0) { 1247 while (buf->bundleDepth > 0) {
1248 OSC_closeBundle(buf); 1248 OSC_closeBundle(buf);
1249 } 1249 }
1250 buf->typeStringPtr = 0; 1250 buf->typeStringPtr = 0;
1251 return 0; 1251 return 0;
1252} 1252}
1253 1253
1254int OSC_writeAddress(OSCbuf *buf, char *name) { 1254int OSC_writeAddress(OSCbuf *buf, char *name) {
1255 int4byte paddedLength; 1255 int4byte paddedLength;
1256 1256
1257 if (buf->state == ONE_MSG_ARGS) { 1257 if (buf->state == ONE_MSG_ARGS) {
1258 OSC_errorMessage = "This packet is not a bundle, so you can't write another address"; 1258 OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
1259 return 7; 1259 return 7;
1260 } 1260 }
1261 1261
1262 if (buf->state == DONE) { 1262 if (buf->state == DONE) {
1263 OSC_errorMessage = "This packet is finished; can't write another address"; 1263 OSC_errorMessage = "This packet is finished; can't write another address";
1264 return 8; 1264 return 8;
1265 } 1265 }
1266 1266
1267 if (CheckTypeTag(buf, '\0')) return 9; 1267 if (CheckTypeTag(buf, '\0')) return 9;
1268 1268
1269 paddedLength = OSC_effectiveStringLength(name); 1269 paddedLength = OSC_effectiveStringLength(name);
1270 1270
1271 if (buf->state == EMPTY) { 1271 if (buf->state == EMPTY) {
1272 /* This will be a one-message packet, so no sizes to worry about */ 1272 /* This will be a one-message packet, so no sizes to worry about */
1273 CheckOverflow(buf, paddedLength); 1273 CheckOverflow(buf, paddedLength);
1274 buf->state = ONE_MSG_ARGS; 1274 buf->state = ONE_MSG_ARGS;
1275 } else { 1275 } else {
1276 /* GET_ARGS or NEED_COUNT */ 1276 /* GET_ARGS or NEED_COUNT */
1277 CheckOverflow(buf, 4+paddedLength); 1277 CheckOverflow(buf, 4+paddedLength);
1278 if (buf->state == GET_ARGS) { 1278 if (buf->state == GET_ARGS) {
1279 /* Close the old message */ 1279 /* Close the old message */
1280 PatchMessageSize(buf); 1280 PatchMessageSize(buf);
1281 } 1281 }
1282 buf->thisMsgSize = (int4byte *)buf->bufptr; 1282 buf->thisMsgSize = (int4byte *)buf->bufptr;
1283 *(buf->thisMsgSize) = 0xbbbbbbbb; 1283 *(buf->thisMsgSize) = 0xbbbbbbbb;
1284 buf->bufptr += 4; 1284 buf->bufptr += 4;
1285 buf->state = GET_ARGS; 1285 buf->state = GET_ARGS;
1286 } 1286 }
1287 1287
1288 /* Now write the name */ 1288 /* Now write the name */
1289 buf->bufptr += OSC_padString(buf->bufptr, name); 1289 buf->bufptr += OSC_padString(buf->bufptr, name);
1290 buf->typeStringPtr = 0; 1290 buf->typeStringPtr = 0;
1291 buf->gettingFirstUntypedArg = 1; 1291 buf->gettingFirstUntypedArg = 1;
1292 1292
1293 return 0; 1293 return 0;
1294} 1294}
1295 1295
1296int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) { 1296int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) {
1297 int result; 1297 int result;
1298 int4byte paddedLength; 1298 int4byte paddedLength;
1299 1299
1300 if (CheckTypeTag(buf, '\0')) return 9; 1300 if (CheckTypeTag(buf, '\0')) return 9;
1301 1301
1302 result = OSC_writeAddress(buf, name); 1302 result = OSC_writeAddress(buf, name);
1303 1303
1304 if (result) return result; 1304 if (result) return result;
1305 1305
1306 paddedLength = OSC_effectiveStringLength(types); 1306 paddedLength = OSC_effectiveStringLength(types);
1307 1307
1308 CheckOverflow(buf, paddedLength); 1308 CheckOverflow(buf, paddedLength);
1309 1309
1310 buf->typeStringPtr = buf->bufptr + 1; /* skip comma */ 1310 buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
1311 buf->bufptr += OSC_padString(buf->bufptr, types); 1311 buf->bufptr += OSC_padString(buf->bufptr, types);
1312 1312
1313 buf->gettingFirstUntypedArg = 0; 1313 buf->gettingFirstUntypedArg = 0;
1314 return 0; 1314 return 0;
1315} 1315}
1316 1316
1317static int CheckTypeTag(OSCbuf *buf, char expectedType) { 1317static int CheckTypeTag(OSCbuf *buf, char expectedType) {
1318 if (buf->typeStringPtr) { 1318 if (buf->typeStringPtr) {
1319 if (*(buf->typeStringPtr) != expectedType) { 1319 if (*(buf->typeStringPtr) != expectedType) {
1320 if (expectedType == '\0') { 1320 if (expectedType == '\0') {
1321 OSC_errorMessage = 1321 OSC_errorMessage =
1322 "According to the type tag I expected more arguments."; 1322 "According to the type tag I expected more arguments.";
1323 } else if (*(buf->typeStringPtr) == '\0') { 1323 } else if (*(buf->typeStringPtr) == '\0') {
1324 OSC_errorMessage = 1324 OSC_errorMessage =
1325 "According to the type tag I didn't expect any more arguments."; 1325 "According to the type tag I didn't expect any more arguments.";
1326 } else { 1326 } else {
1327 OSC_errorMessage = 1327 OSC_errorMessage =
1328 "According to the type tag I expected an argument of a different type."; 1328 "According to the type tag I expected an argument of a different type.";
1329 printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr); 1329 printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
1330 } 1330 }
1331 return 9; 1331 return 9;
1332 } 1332 }
1333 ++(buf->typeStringPtr); 1333 ++(buf->typeStringPtr);
1334 } 1334 }
1335 return 0; 1335 return 0;
1336} 1336}
1337 1337
1338 1338
1339int OSC_writeFloatArg(OSCbuf *buf, float arg) { 1339int OSC_writeFloatArg(OSCbuf *buf, float arg) {
1340 int4byte *intp; 1340 int4byte *intp;
1341 //int result; 1341 //int result;
1342 1342
1343 CheckOverflow(buf, 4); 1343 CheckOverflow(buf, 4);
1344 1344
1345 if (CheckTypeTag(buf, 'f')) return 9; 1345 if (CheckTypeTag(buf, 'f')) return 9;
1346 1346
1347 /* Pretend arg is a long int so we can use htonl() */ 1347 /* Pretend arg is a long int so we can use htonl() */
1348 intp = ((int4byte *) &arg); 1348 intp = ((int4byte *) &arg);
1349 *((int4byte *) buf->bufptr) = htonl(*intp); 1349 *((int4byte *) buf->bufptr) = htonl(*intp);
1350 1350
1351 buf->bufptr += 4; 1351 buf->bufptr += 4;
1352 1352
1353 buf->gettingFirstUntypedArg = 0; 1353 buf->gettingFirstUntypedArg = 0;
1354 return 0; 1354 return 0;
1355} 1355}
1356 1356
1357 1357
1358 1358
1359int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) { 1359int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
1360 int i; 1360 int i;
1361 int4byte *intp; 1361 int4byte *intp;
1362 1362
1363 CheckOverflow(buf, 4 * numFloats); 1363 CheckOverflow(buf, 4 * numFloats);
1364 1364
1365 /* Pretend args are long ints so we can use htonl() */ 1365 /* Pretend args are long ints so we can use htonl() */
1366 intp = ((int4byte *) args); 1366 intp = ((int4byte *) args);
1367 1367
1368 for (i = 0; i < numFloats; i++) { 1368 for (i = 0; i < numFloats; i++) {
1369 if (CheckTypeTag(buf, 'f')) return 9; 1369 if (CheckTypeTag(buf, 'f')) return 9;
1370 *((int4byte *) buf->bufptr) = htonl(intp[i]); 1370 *((int4byte *) buf->bufptr) = htonl(intp[i]);
1371 buf->bufptr += 4; 1371 buf->bufptr += 4;
1372 } 1372 }
1373 1373
1374 buf->gettingFirstUntypedArg = 0; 1374 buf->gettingFirstUntypedArg = 0;
1375 return 0; 1375 return 0;
1376} 1376}
1377 1377
1378int OSC_writeIntArg(OSCbuf *buf, int4byte arg) { 1378int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
1379 CheckOverflow(buf, 4); 1379 CheckOverflow(buf, 4);
1380 if (CheckTypeTag(buf, 'i')) return 9; 1380 if (CheckTypeTag(buf, 'i')) return 9;
1381 1381
1382 *((int4byte *) buf->bufptr) = htonl(arg); 1382 *((int4byte *) buf->bufptr) = htonl(arg);
1383 buf->bufptr += 4; 1383 buf->bufptr += 4;
1384 1384
1385 buf->gettingFirstUntypedArg = 0; 1385 buf->gettingFirstUntypedArg = 0;
1386 return 0; 1386 return 0;
1387} 1387}
1388 1388
1389int OSC_writeStringArg(OSCbuf *buf, char *arg) { 1389int OSC_writeStringArg(OSCbuf *buf, char *arg) {
1390 int len; 1390 int len;
1391 1391
1392 if (CheckTypeTag(buf, 's')) return 9; 1392 if (CheckTypeTag(buf, 's')) return 9;
1393 1393
1394 len = OSC_effectiveStringLength(arg); 1394 len = OSC_effectiveStringLength(arg);
1395 1395
1396 if (buf->gettingFirstUntypedArg && arg[0] == ',') { 1396 if (buf->gettingFirstUntypedArg && arg[0] == ',') {
1397 /* This un-type-tagged message starts with a string 1397 /* This un-type-tagged message starts with a string
1398 that starts with a comma, so we have to escape it 1398 that starts with a comma, so we have to escape it
1399 (with a double comma) so it won't look like a type 1399 (with a double comma) so it won't look like a type
1400 tag string. */ 1400 tag string. */
1401 1401
1402 CheckOverflow(buf, len+4); /* Too conservative */ 1402 CheckOverflow(buf, len+4); /* Too conservative */
1403 buf->bufptr += 1403 buf->bufptr +=
1404 OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg); 1404 OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
1405 1405
1406 } else { 1406 } else {
1407 CheckOverflow(buf, len); 1407 CheckOverflow(buf, len);
1408 buf->bufptr += OSC_padString(buf->bufptr, arg); 1408 buf->bufptr += OSC_padString(buf->bufptr, arg);
1409 } 1409 }
1410 1410
1411 buf->gettingFirstUntypedArg = 0; 1411 buf->gettingFirstUntypedArg = 0;
1412 return 0; 1412 return 0;
1413 1413
1414} 1414}
1415 1415
1416/* String utilities */ 1416/* String utilities */
1417 1417
1418#define STRING_ALIGN_PAD 4 1418#define STRING_ALIGN_PAD 4
1419int OSC_effectiveStringLength(char *string) { 1419int OSC_effectiveStringLength(char *string) {
1420 int len = strlen(string) + 1; /* We need space for the null char. */ 1420 int len = strlen(string) + 1; /* We need space for the null char. */
1421 1421
1422 /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */ 1422 /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
1423 if ((len % STRING_ALIGN_PAD) != 0) { 1423 if ((len % STRING_ALIGN_PAD) != 0) {
1424 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD); 1424 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
1425 } 1425 }
1426 return len; 1426 return len;
1427} 1427}
1428 1428
1429static int OSC_padString(char *dest, char *str) { 1429static int OSC_padString(char *dest, char *str) {
1430 int i; 1430 int i;
1431 1431
1432 for (i = 0; str[i] != '\0'; i++) { 1432 for (i = 0; str[i] != '\0'; i++) {
1433 dest[i] = str[i]; 1433 dest[i] = str[i];
1434 } 1434 }
1435 1435
1436 return OSC_WritePadding(dest, i); 1436 return OSC_WritePadding(dest, i);
1437} 1437}
1438 1438
1439static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) { 1439static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) {
1440 int i; 1440 int i;
1441 1441
1442 dest[0] = ','; 1442 dest[0] = ',';
1443 for (i = 0; str[i] != '\0'; i++) { 1443 for (i = 0; str[i] != '\0'; i++) {
1444 dest[i+1] = str[i]; 1444 dest[i+1] = str[i];
1445 } 1445 }
1446 1446
1447 return OSC_WritePadding(dest, i+1); 1447 return OSC_WritePadding(dest, i+1);
1448} 1448}
1449 1449
1450static int OSC_WritePadding(char *dest, int i) { 1450static int OSC_WritePadding(char *dest, int i) {
1451 dest[i] = '\0'; 1451 dest[i] = '\0';
1452 i++; 1452 i++;
1453 1453
1454 for (; (i % STRING_ALIGN_PAD) != 0; i++) { 1454 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
1455 dest[i] = '\0'; 1455 dest[i] = '\0';
1456 } 1456 }
1457 1457
1458 return i; 1458 return i;
1459} 1459}
1460 1460
1461 1461