summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra/OSCroute.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/OSCroute.c')
-rw-r--r--apps/plugins/pdbox/PDa/extra/OSCroute.c628
1 files changed, 0 insertions, 628 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/OSCroute.c b/apps/plugins/pdbox/PDa/extra/OSCroute.c
deleted file mode 100644
index 64edbc777f..0000000000
--- a/apps/plugins/pdbox/PDa/extra/OSCroute.c
+++ /dev/null
@@ -1,628 +0,0 @@
1/*
2Written by Adrian Freed, The Center for New Music and Audio Technologies,
3University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04
4The Regents of the University of California (Regents).
5
6Permission to use, copy, modify, distribute, and distribute modified versions
7of this software and its documentation without fee and without a signed
8licensing agreement, is hereby granted, provided that the above copyright
9notice, this paragraph and the following two paragraphs appear in all copies,
10modifications, and distributions.
11
12IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
13SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
14OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
15BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
17REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
20HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
21MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22
23
24The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
25*/
26
27 /* OSC-route.c
28 Max object for OSC-style dispatching
29
30 To-do:
31
32 Match a pattern against a pattern?
33 Declare outlet types / distinguish leaf nodes from other children
34 More sophisticated (2-pass?) allmessages scheme
35 set message?
36
37
38 pd
39 -------------
40 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
41
42
43 */
44
45#ifdef ROCKBOX
46#include "plugin.h"
47#include "../../pdbox.h"
48#else /* ROCKBOX */
49#ifdef WIN32
50 #include <stdlib.h>
51 #include <string.h>
52#endif
53#ifdef __APPLE__
54 #include <stdio.h>
55#endif
56#ifdef UNIX
57 #include <stdio.h>
58#endif
59#endif /* ROCKBOX */
60
61/* structure definition of your object */
62
63#define MAX_NUM 20
64#define OSC_ROUTE_VERSION "1.05"
65#define OSCWarning(x...) post(x)
66
67/* the required include files */
68#include "../src/m_pd.h"
69
70
71#ifndef TRUE
72typedef int Boolean;
73#define TRUE 1
74#define FALSE 0
75#endif
76
77
78/* Fixed byte width types */
79typedef int int4; /* 4 byte int */
80
81Boolean PatternMatch (const char *pattern, const char *test);
82
83
84
85/* Version 1.04: Allows #1 thru #9 as typed-in arguments
86 Version 1.05: Allows "list" messages as well as "message" messages.
87*/
88
89static t_class *OSCroute_class;
90
91typedef struct _OSCroute
92{
93 t_object x_obj; // required header
94 t_int x_num; // Number of address prefixes we store
95 t_int x_complainmode; // Do we print a message if no match?
96 t_int x_sendmode; // use pd internal sends instead of outlets
97 char *x_prefixes[MAX_NUM];
98 void *x_outlets[MAX_NUM+1];
99} t_OSCroute;
100
101t_symbol *ps_list, *ps_complain, *ps_emptySymbol;
102
103/* prototypes */
104
105void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
106void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
107void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
108/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */
109void *OSCroute_new(t_symbol *s, int argc, t_atom *argv);
110void OSCroute_version (t_OSCroute *x);
111/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */
112/* char *dstString); */
113void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
114
115static char *NextSlashOrNull(char *p);
116static void StrCopyUntilSlash(char *target, const char *source);
117
118
119// free
120static void OSCroute_free(t_OSCroute *x)
121{
122#ifdef ROCKBOX
123 (void) x;
124#endif
125 // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
126}
127
128/* initialization routine */
129
130// setup
131#ifdef WIN32
132 OSC_API void OSCroute_setup(void) {
133#else
134void OSCroute_setup(void) {
135#endif
136 OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new,
137 (t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0);
138 class_addlist(OSCroute_class, OSCroute_list);
139 class_addanything(OSCroute_class, OSCroute_anything);
140 class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0);
141 class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd"));
142
143 /*
144 class_addmethod(OSCroute_class, (t_method)OSCroute_connect,
145 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
146 class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect,
147 gensym("disconnect"), 0);
148 class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"),
149 A_GIMME, 0);
150 */
151/* ps_list = gensym("list"); */
152/* ps_complain = gensym("complain"); */
153 ps_emptySymbol = gensym("");
154
155 post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf.");
156 post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved.");
157}
158
159
160
161/* instance creation routine */
162
163void *OSCroute_new(t_symbol *s, int argc, t_atom *argv)
164{
165#ifdef ROCKBOX
166 (void) s;
167#endif
168 t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize
169
170 int i; //{{raf}} n not used
171
172 // EnterCallback();
173
174 if (argc > MAX_NUM) {
175 post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM);
176 // ExitCallback();
177 return 0;
178 }
179
180 x->x_complainmode = 0;
181 x->x_num = 0;
182 for (i = 0; i < argc; ++i) {
183 if (argv[i].a_type == A_SYMBOL) {
184 if (argv[i].a_w.w_symbol->s_name[0] == '/') {
185 /* Now that's a nice prefix */
186 x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
187 ++(x->x_num);
188 } else if (argv[i].a_w.w_symbol->s_name[0] == '#' &&
189 argv[i].a_w.w_symbol->s_name[1] >= '1' &&
190 argv[i].a_w.w_symbol->s_name[1] <= '9') {
191 /* The Max programmer is trying to make a patch that will be
192 a subpatch with arguments. We have to make an outlet for this
193 argument. */
194 x->x_prefixes[i] = "dummy";
195 ++(x->x_num);
196 } else {
197 /* Maybe this is an option we support */
198
199/* if (argv[i].a_w.w_sym == ps_complain) { */
200/* x->x_complainmode = 1; */
201/* } else { */
202/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */
203/* } */
204
205 }
206
207 // no LONG
208
209/* } else if (argv[i].a_type == A_FLOAD) { */
210/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */
211/* char *string = getbytes(12); */
212/* // I can't be bothered to plug this 12 byte memory leak */
213/* if (string == 0) { */
214/* post("* OSC-route: out of memory!"); */
215/* // ExitCallback(); */
216/* return 0; */
217/* } */
218/* sprintf(string, "%d", argv[i].a_w.w_long); */
219/* x->x_prefixes[i] = string; */
220/* ++(x->x_num); */
221
222 } else if (argv[i].a_type == A_FLOAT) {
223 post("* OSC-route: float arguments are not OK.");
224 // ExitCallback();
225 return 0;
226 } else {
227 post("* OSC-route: unrecognized argument type!");
228 // ExitCallback();
229 return 0;
230 }
231 }
232
233
234 /* Have to create the outlets in reverse order */
235 /* well, not in pd ? */
236 // for (i = x->x_num-1; i >= 0; --i) {
237 // for (i = 0; i <= x->x_num-1; i++) {
238 for (i = 0; i <= x->x_num; i++) {
239 // x->x_outlets[i] = listout(x);
240 x->x_outlets[i] = outlet_new(&x->x_obj, &s_list);
241 }
242
243 // ExitCallback();
244 return (x);
245}
246
247
248void OSCroute_version (t_OSCroute *x) {
249#ifdef ROCKBOX
250 (void) x;
251#endif
252 // EnterCallback();
253 post("OSCroute Version " OSC_ROUTE_VERSION
254 ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__);
255 // ExitCallback();
256}
257
258/* I don't know why these aren't defined in some Max #include file. */
259#define ASSIST_INLET 1
260#define ASSIST_OUTLET 2
261
262void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg,
263 char *dstString) {
264#ifdef ROCKBOX
265 (void) box;
266#endif
267 // EnterCallback();
268
269 if (msg==ASSIST_INLET) {
270#ifdef ROCKBOX
271 strcpy(dstString, "Incoming OSC messages");
272#else
273 sprintf(dstString, "Incoming OSC messages");
274#endif
275 } else if (msg==ASSIST_OUTLET) {
276 if (arg < 0 || arg >= x->x_num) {
277 post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg);
278 } else {
279#ifdef ROCKBOX
280 strcpy(dstString, "subaddress + args for prefix ");
281 strcat(dstString, x->x_prefixes[arg]);
282#else
283 sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]);
284#endif
285 }
286 } else {
287 post("* OSCroute_assist: unrecognized message %ld", msg);
288 }
289
290 // ExitCallback();
291}
292
293void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
294#ifdef ROCKBOX
295 (void) s;
296#endif
297 // EnterCallback();
298 if (argc > 0 && argv[0].a_type == A_SYMBOL) {
299 /* Ignore the fact that this is a "list" */
300 OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1);
301 } else {
302 // post("* OSC-route: invalid list beginning with a number");
303 // output on unmatched outlet jdl 20020908
304 if (argv[0].a_type == A_FLOAT) {
305 outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float);
306 } else {
307 post("* OSC-route: unrecognized atom type!");
308 }
309 }
310 // ExitCallback();
311}
312
313
314void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
315 // EnterCallback();
316 OSCroute_doanything(x, s, argc, argv);
317 // ExitCallback();
318}
319
320
321
322
323void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
324 char *pattern, *nextSlash;
325 int i;
326 int matchedAnything;
327 // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc);
328
329 pattern = s->s_name;
330 if (pattern[0] != '/') {
331 post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name);
332 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
333 return;
334 }
335
336 matchedAnything = 0;
337
338 nextSlash = NextSlashOrNull(pattern+1);
339 if (*nextSlash == '\0') {
340 /* last level of the address, so we'll output the argument list */
341
342
343#ifdef NULL_IS_DIFFERENT_FROM_BANG
344 if (argc==0) {
345 post("* OSC-route: why are you matching one level pattern %s with no args?",
346 pattern);
347 return;
348 }
349#endif
350
351 for (i = 0; i < x->x_num; ++i) {
352 if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) {
353 ++matchedAnything;
354
355 // I hate stupid Max lists with a special first element
356 if (argc == 0) {
357 outlet_bang(x->x_outlets[i]);
358 } else if (argv[0].a_type == A_SYMBOL) {
359 // Promote the symbol that was argv[0] to the special symbol
360 outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
361 } else if (argc > 1) {
362 // Multiple arguments starting with a number, so naturally we have
363 // to use a special function to output this "list", since it's what
364 // Max originally meant by "list".
365 outlet_list(x->x_outlets[i], 0L, argc, argv);
366 } else {
367 // There was only one argument, and it was a number, so we output it
368 // not as a list
369/* if (argv[0].a_type == A_LONG) { */
370
371/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */
372 // } else
373 if (argv[0].a_type == A_FLOAT) {
374
375 outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
376 } else {
377 post("* OSC-route: unrecognized atom type!");
378 }
379 }
380 }
381 }
382 } else {
383 /* There's more address after this part, so our output list will begin with
384 the next slash. */
385 t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
386 char patternBegin[1000];
387
388
389 /* Get the first level of the incoming pattern to match against all our prefixes */
390 StrCopyUntilSlash(patternBegin, pattern+1);
391
392 for (i = 0; i < x->x_num; ++i) {
393 if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) {
394 ++matchedAnything;
395 if (restOfPattern == 0) {
396 restOfPattern = gensym(nextSlash);
397 }
398 outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
399 }
400 }
401 }
402
403 if (x->x_complainmode) {
404 if (!matchedAnything) {
405 post("* OSC-route: pattern %s did not match any prefixes", pattern);
406 }
407 }
408
409 // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
410 if (!matchedAnything) {
411 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
412 }
413
414
415}
416
417static char *NextSlashOrNull(char *p) {
418 while (*p != '/' && *p != '\0') {
419 p++;
420 }
421 return p;
422}
423
424static void StrCopyUntilSlash(char *target, const char *source) {
425 while (*source != '/' && *source != '\0') {
426 *target = *source;
427 ++target;
428 ++source;
429 }
430 *target = 0;
431}
432
433static int MyStrCopy(char *target, const char *source) {
434 int i = 0;
435 while (*source != '\0') {
436 *target = *source;
437 ++target;
438 ++source;
439 ++i;
440 }
441 *target = 0;
442 return i;
443}
444
445
446
447void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
448 int i;
449 t_symbol *prefixSymbol = 0;
450 char prefixBuf[1000];
451 char *endOfPrefix;
452 t_atom a[1];
453
454 if (argc >= 1 && argv[0].a_type == A_SYMBOL) {
455 prefixSymbol = argv[0].a_w.w_symbol;
456 endOfPrefix = prefixBuf + MyStrCopy(prefixBuf,
457 prefixSymbol->s_name);
458 } else {
459 prefixSymbol = ps_emptySymbol;
460 prefixBuf[0] = '\0';
461 endOfPrefix = prefixBuf;
462 }
463
464
465 for (i = 0; i < x->x_num; ++i) {
466 post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]);
467 MyStrCopy(endOfPrefix, x->x_prefixes[i]);
468 SETSYMBOL(a, gensym(prefixBuf));
469 outlet_anything(x->x_outlets[i], s, 1, a);
470 }
471}
472
473
474/* --------------------------------------------------- */
475
476
477
478static const char *theWholePattern; /* Just for warning messages */
479
480static Boolean MatchBrackets (const char *pattern, const char *test);
481static Boolean MatchList (const char *pattern, const char *test);
482
483Boolean PatternMatch (const char * pattern, const char * test) {
484 theWholePattern = pattern;
485
486 if (pattern == 0 || pattern[0] == 0) {
487 return test[0] == 0;
488 }
489
490 if (test[0] == 0) {
491 if (pattern[0] == '*')
492 return PatternMatch (pattern+1,test);
493 else
494 return FALSE;
495 }
496
497 switch (pattern[0]) {
498 case 0 : return test[0] == 0;
499 case '?' : return PatternMatch (pattern + 1, test + 1);
500 case '*' :
501 if (PatternMatch (pattern+1, test)) {
502 return TRUE;
503 } else {
504 return PatternMatch (pattern, test+1);
505 }
506 case ']' :
507 case '}' :
508 OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
509 return FALSE;
510 case '[' :
511 return MatchBrackets (pattern,test);
512 case '{' :
513 return MatchList (pattern,test);
514 case '\\' :
515 if (pattern[1] == 0) {
516 return test[0] == 0;
517 } else if (pattern[1] == test[0]) {
518 return PatternMatch (pattern+2,test+1);
519 } else {
520 return FALSE;
521 }
522 default :
523 if (pattern[0] == test[0]) {
524 return PatternMatch (pattern+1,test+1);
525 } else {
526 return FALSE;
527 }
528 }
529}
530
531
532/* we know that pattern[0] == '[' and test[0] != 0 */
533
534static Boolean MatchBrackets (const char *pattern, const char *test) {
535 Boolean result;
536 Boolean negated = FALSE;
537 const char *p = pattern;
538
539 if (pattern[1] == 0) {
540 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
541 return FALSE;
542 }
543
544 if (pattern[1] == '!') {
545 negated = TRUE;
546 p++;
547 }
548
549 while (*p != ']') {
550 if (*p == 0) {
551 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
552 return FALSE;
553 }
554 if (p[1] == '-' && p[2] != 0) {
555 if (test[0] >= p[0] && test[0] <= p[2]) {
556 result = !negated;
557 goto advance;
558 }
559 }
560 if (p[0] == test[0]) {
561 result = !negated;
562 goto advance;
563 }
564 p++;
565 }
566
567 result = negated;
568
569advance:
570
571 if (!result)
572 return FALSE;
573
574 while (*p != ']') {
575 if (*p == 0) {
576 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
577 return FALSE;
578 }
579 p++;
580 }
581
582 return PatternMatch (p+1,test+1);
583}
584
585static Boolean MatchList (const char *pattern, const char *test) {
586
587 const char *restOfPattern, *tp = test;
588
589
590 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
591 if (*restOfPattern == 0) {
592 OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern);
593 return FALSE;
594 }
595 }
596
597 restOfPattern++; /* skip close curly brace */
598
599
600 pattern++; /* skip open curly brace */
601
602 while (1) {
603
604 if (*pattern == ',') {
605 if (PatternMatch (restOfPattern, tp)) {
606 return TRUE;
607 } else {
608 tp = test;
609 ++pattern;
610 }
611 } else if (*pattern == '}') {
612 return PatternMatch (restOfPattern, tp);
613 } else if (*pattern == *tp) {
614 ++pattern;
615 ++tp;
616 } else {
617 tp = test;
618 while (*pattern != ',' && *pattern != '}') {
619 pattern++;
620 }
621 if (*pattern == ',') {
622 pattern++;
623 }
624 }
625 }
626
627}
628