1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
7 * changed the canvas_restore in "g_canvas.c", so that it might accept $args as well (like "pd $0_test")
8 * so you can make multiple & distinguishable templates
9 * 1511:forum::für::umläute:2001
10 * change marked with IOhannes
33 t_binbuf
*binbuf_new(void)
35 t_binbuf
*x
= (t_binbuf
*)t_getbytes(sizeof(*x
));
37 x
->b_vec
= t_getbytes(0);
41 void binbuf_free(t_binbuf
*x
)
43 t_freebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
));
44 t_freebytes(x
, sizeof(*x
));
47 t_binbuf
*binbuf_duplicate(t_binbuf
*y
)
49 t_binbuf
*x
= (t_binbuf
*)t_getbytes(sizeof(*x
));
51 x
->b_vec
= t_getbytes(x
->b_n
* sizeof(*x
->b_vec
));
52 memcpy(x
->b_vec
, y
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
));
56 void binbuf_clear(t_binbuf
*x
)
58 x
->b_vec
= t_resizebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
), 0);
62 /* convert text to a binbuf */
63 void binbuf_text(t_binbuf
*x
, char *text
, size_t size
)
65 char buf
[MAXPDSTRING
+1], *bufp
, *ebuf
= buf
+MAXPDSTRING
;
66 const char *textp
= text
, *etext
= text
+size
;
68 int nalloc
= 16, natom
= 0;
69 t_freebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
));
70 x
->b_vec
= t_getbytes(nalloc
* sizeof(*x
->b_vec
));
76 /* skip leading space */
77 while ((textp
!= etext
) && (*textp
== ' ' || *textp
== '\n'
78 || *textp
== '\r' || *textp
== '\t')) textp
++;
79 if (textp
== etext
) break;
80 if (*textp
== ';') SETSEMI(ap
), textp
++;
81 else if (*textp
== ',') SETCOMMA(ap
), textp
++;
84 /* it's an atom other than a comma or semi */
86 int floatstate
= 0, slash
= 0, lastslash
= 0,
87 firstslash
= (*textp
== '\\');
97 int digit
= (c
>= '0' && c
<= '9'),
98 dot
= (c
== '.'), minus
= (c
== '-'),
99 plusminus
= (minus
|| (c
== '+')),
100 expon
= (c
== 'e' || c
== 'E');
101 if (floatstate
== 0) /* beginning */
103 if (minus
) floatstate
= 1;
104 else if (digit
) floatstate
= 2;
105 else if (dot
) floatstate
= 3;
106 else floatstate
= -1;
108 else if (floatstate
== 1) /* got minus */
110 if (digit
) floatstate
= 2;
111 else if (dot
) floatstate
= 3;
112 else floatstate
= -1;
114 else if (floatstate
== 2) /* got digits */
116 if (dot
) floatstate
= 4;
117 else if (expon
) floatstate
= 6;
118 else if (!digit
) floatstate
= -1;
120 else if (floatstate
== 3) /* got '.' without digits */
122 if (digit
) floatstate
= 5;
123 else floatstate
= -1;
125 else if (floatstate
== 4) /* got '.' after digits */
127 if (digit
) floatstate
= 5;
128 else if (expon
) floatstate
= 6;
129 else floatstate
= -1;
131 else if (floatstate
== 5) /* got digits after . */
133 if (expon
) floatstate
= 6;
134 else if (!digit
) floatstate
= -1;
136 else if (floatstate
== 6) /* got 'e' */
138 if (plusminus
) floatstate
= 7;
139 else if (digit
) floatstate
= 8;
140 else floatstate
= -1;
142 else if (floatstate
== 7) /* got plus or minus */
144 if (digit
) floatstate
= 8;
145 else floatstate
= -1;
147 else if (floatstate
== 8) /* got digits */
149 if (!digit
) floatstate
= -1;
154 while (textp
!= etext
&& bufp
!= ebuf
&&
155 (slash
|| (*textp
!= ' ' && *textp
!= '\n' && *textp
!= '\r'
156 && *textp
!= '\t' &&*textp
!= ',' && *textp
!= ';')));
161 if (*buf
== '$' && buf
[1] >= '0' && buf
[1] <= '9' && !firstslash
)
163 for (bufp
= buf
+2; *bufp
; bufp
++)
164 if (*bufp
< '0' || *bufp
> '9')
166 SETDOLLSYM(ap
, gensym(buf
+1));
169 SETDOLLAR(ap
, atoi(buf
+1));
174 if (floatstate
== 2 || floatstate
== 4 || floatstate
== 5 ||
176 SETFLOAT(ap
, atof(buf
));
177 else SETSYMBOL(ap
, gensym(buf
));
184 x
->b_vec
= t_resizebytes(x
->b_vec
, nalloc
* sizeof(*x
->b_vec
),
185 nalloc
* (2*sizeof(*x
->b_vec
)));
187 ap
= x
->b_vec
+ natom
;
189 if (textp
== etext
) break;
191 /* reallocate the vector to exactly the right size */
192 x
->b_vec
= t_resizebytes(x
->b_vec
, nalloc
* sizeof(*x
->b_vec
),
193 natom
* sizeof(*x
->b_vec
));
197 /* convert a binbuf to text; no null termination. */
198 void binbuf_gettext(t_binbuf
*x
, char **bufp
, int *lengthp
)
200 char *buf
= getbytes(0), *newbuf
;
202 char string
[MAXPDSTRING
];
206 for (ap
= x
->b_vec
, indx
= x
->b_n
; indx
--; ap
++)
209 if ((ap
->a_type
== A_SEMI
|| ap
->a_type
== A_COMMA
) &&
210 length
&& buf
[length
-1] == ' ') length
--;
211 atom_string(ap
, string
, MAXPDSTRING
);
212 newlength
= length
+ strlen(string
) + 1;
213 if (!(newbuf
= resizebytes(buf
, length
, newlength
))) break;
215 strcpy(buf
+ length
, string
);
217 if (ap
->a_type
== A_SEMI
) buf
[length
-1] = '\n';
218 else buf
[length
-1] = ' ';
220 if (length
&& buf
[length
-1] == ' ')
222 if (newbuf
= t_resizebytes(buf
, length
, length
-1))
232 /* LATER improve the out-of-space behavior below. Also fix this so that
233 writing to file doesn't buffer everything together. */
235 void binbuf_add(t_binbuf
*x
, int argc
, t_atom
*argv
)
237 int newsize
= x
->b_n
+ argc
, i
;
239 if (ap
= t_resizebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
),
240 newsize
* sizeof(*x
->b_vec
)))
244 error("binbuf_addmessage: out of space");
248 startpost("binbuf_add: ");
249 postatom(argc
, argv
);
252 for (ap
= x
->b_vec
+ x
->b_n
, i
= argc
; i
--; ap
++)
257 #define MAXADDMESSV 100
258 void binbuf_addv(t_binbuf
*x
, char *fmt
, ...)
261 t_atom arg
[MAXADDMESSV
], *at
=arg
;
268 if (nargs
>= MAXADDMESSV
)
270 error("binbuf_addmessv: only %d allowed", MAXADDMESSV
);
275 case 'i': SETFLOAT(at
, va_arg(ap
, t_int
)); break;
276 case 'f': SETFLOAT(at
, va_arg(ap
, double)); break;
277 case 's': SETSYMBOL(at
, va_arg(ap
, t_symbol
*)); break;
278 case ';': SETSEMI(at
); break;
279 case ',': SETCOMMA(at
); break;
287 binbuf_add(x
, nargs
, arg
);
290 /* add a binbuf to another one for saving. Semicolons and commas go to
291 symbols ";", "'",; the symbol ";" goes to "\;", etc. */
293 void binbuf_addbinbuf(t_binbuf
*x
, t_binbuf
*y
)
295 t_binbuf
*z
= binbuf_new();
298 binbuf_add(z
, y
->b_n
, y
->b_vec
);
299 for (i
= 0, ap
= z
->b_vec
; i
< z
->b_n
; i
++, ap
++)
301 char tbuf
[MAXPDSTRING
];
307 SETSYMBOL(ap
, gensym(";"));
310 SETSYMBOL(ap
, gensym(","));
313 sprintf(tbuf
, "$%d", ap
->a_w
.w_index
);
314 SETSYMBOL(ap
, gensym(tbuf
));
317 sprintf(tbuf
, "$%s", ap
->a_w
.w_symbol
->s_name
);
318 SETSYMBOL(ap
, gensym(tbuf
));
321 /* FIXME make this general */
322 if (!strcmp(ap
->a_w
.w_symbol
->s_name
, ";"))
323 SETSYMBOL(ap
, gensym(";"));
324 else if (!strcmp(ap
->a_w
.w_symbol
->s_name
, ","))
325 SETSYMBOL(ap
, gensym(","));
328 bug("binbuf_addbinbuf");
332 binbuf_add(x
, z
->b_n
, z
->b_vec
);
335 void binbuf_addsemi(t_binbuf
*x
)
339 binbuf_add(x
, 1, &a
);
342 /* Supply atoms to a binbuf from a message, making the opposite changes
343 from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
345 void binbuf_restore(t_binbuf
*x
, int argc
, t_atom
*argv
)
347 int newsize
= x
->b_n
+ argc
, i
;
349 if (ap
= t_resizebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
),
350 newsize
* sizeof(*x
->b_vec
)))
354 error("binbuf_addmessage: out of space");
358 for (ap
= x
->b_vec
+ x
->b_n
, i
= argc
; i
--; ap
++)
360 if (argv
->a_type
== A_SYMBOL
)
362 char *str
= argv
->a_w
.w_symbol
->s_name
;
363 if (!strcmp(str
, ";")) SETSEMI(ap
);
364 else if (!strcmp(str
, ",")) SETCOMMA(ap
);
365 else if (str
[0] == '$' && str
[1] >= '0' && str
[1] <= '9')
369 for (str2
= str
+ 2; *str2
; str2
++)
370 if (*str2
< '0' || *str2
> '9')
373 SETDOLLSYM(ap
, gensym(str
+ 1));
377 sscanf(argv
->a_w
.w_symbol
->s_name
+ 1, "%d", &dollar
);
378 SETDOLLAR(ap
, dollar
);
384 else *ap
= *(argv
++);
390 #define MSTACKSIZE 2048
392 void binbuf_print(t_binbuf
*x
)
394 int i
, startedpost
= 0, newline
= 1;
395 for (i
= 0; i
< x
->b_n
; i
++)
399 if (startedpost
) endpost();
403 postatom(1, x
->b_vec
+ i
);
404 if (x
->b_vec
[i
].a_type
== A_SEMI
)
408 if (startedpost
) endpost();
411 int binbuf_getnatom(t_binbuf
*x
)
416 t_atom
*binbuf_getvec(t_binbuf
*x
)
421 int canvas_getdollarzero( void);
423 t_symbol
*binbuf_realizedollsym(t_symbol
*s
, int ac
, t_atom
*av
, int tonew
)
425 int argno
= atol(s
->s_name
), lastnum
;
426 char buf
[MAXPDSTRING
], c
, *sp
;
427 for (lastnum
= 0, sp
= s
->s_name
; ((c
= *sp
) && c
>= '0' && c
<= '9');
429 if (!c
|| argno
< 0 || argno
> ac
)
433 else sprintf(buf
, "$%d", argno
);
436 sprintf(buf
, "%d", canvas_getdollarzero());
438 atom_string(av
+(argno
-1), buf
, MAXPDSTRING
/2-1);
439 strncat(buf
, sp
, MAXPDSTRING
/2-1);
440 return (gensym(buf
));
443 void binbuf_eval(t_binbuf
*x
, t_pd
*target
, int argc
, t_atom
*argv
)
445 static t_atom mstack
[MSTACKSIZE
], *msp
= mstack
, *ems
= mstack
+MSTACKSIZE
;
446 t_atom
*stackwas
= msp
;
447 t_atom
*at
= x
->b_vec
;
457 while (ac
&& (at
->a_type
== A_SEMI
|| at
->a_type
== A_COMMA
))
460 if (at
->a_type
== A_DOLLAR
)
462 if (at
->a_w
.w_index
<= 0 || at
->a_w
.w_index
> argc
)
464 error("$%d: not enough arguments supplied",
468 else if (argv
[at
->a_w
.w_index
-1].a_type
!= A_SYMBOL
)
470 error("$%d: symbol needed as message destination",
474 else s
= argv
[at
->a_w
.w_index
-1].a_w
.w_symbol
;
476 else if (at
->a_type
== A_DOLLSYM
)
478 if (!(s
= binbuf_realizedollsym(at
->a_w
.w_symbol
,
481 error("$%s: not enough arguments supplied",
482 at
->a_w
.w_symbol
->s_name
);
486 else s
= atom_getsymbol(at
);
487 if (!(target
= s
->s_thing
))
489 error("%s: no such object", s
->s_name
);
492 while (ac
&& at
->a_type
!= A_SEMI
);
493 /* LATER eat args until semicolon and continue */
508 if (!ac
) goto gotmess
;
511 error("message stack overflow");
517 /* semis and commas in new message just get bashed to
518 a symbol. This is needed so you can pass them to "expr." */
519 if (target
== &pd_objectmaker
)
521 SETSYMBOL(msp
, gensym(";"));
530 if (target
== &pd_objectmaker
)
532 SETSYMBOL(msp
, gensym(","));
541 if (at
->a_w
.w_index
> 0 && at
->a_w
.w_index
<= argc
)
542 *msp
= argv
[at
->a_w
.w_index
-1];
543 else if (at
->a_w
.w_index
== 0)
544 SETFLOAT(msp
, canvas_getdollarzero());
547 if (target
== &pd_objectmaker
)
551 error("$%d: argument number out of range",
558 s9
= binbuf_realizedollsym(at
->a_w
.w_symbol
, argc
, argv
,
559 target
== &pd_objectmaker
);
565 bug("bad item in binbuf");
576 switch (stackwas
->a_type
)
579 typedmess(target
, stackwas
->a_w
.w_symbol
, nargs
-1, stackwas
+1);
582 if (nargs
== 1) pd_float(target
, stackwas
->a_w
.w_float
);
583 else pd_list(target
, 0, nargs
, stackwas
);
599 static int binbuf_doopen(char *s
, int mode
)
601 char namebuf
[MAXPDSTRING
];
605 sys_bashfilename(s
, namebuf
);
606 return (open(namebuf
, mode
));
609 static FILE *binbuf_dofopen(char *s
, char *mode
)
611 char namebuf
[MAXPDSTRING
];
612 sys_bashfilename(s
, namebuf
);
613 return (fopen(namebuf
, mode
));
616 int binbuf_read(t_binbuf
*b
, char *filename
, char *dirname
, int crflag
)
622 char namebuf
[MAXPDSTRING
];
626 strcat(namebuf
, dirname
), strcat(namebuf
, "/");
627 strcat(namebuf
, filename
);
629 if ((fd
= binbuf_doopen(namebuf
, 0)) < 0)
631 fprintf(stderr
, "open: ");
635 if ((length
= lseek(fd
, 0, SEEK_END
)) < 0 || lseek(fd
, 0, SEEK_SET
) < 0
636 || !(buf
= t_getbytes(length
)))
638 fprintf(stderr
, "lseek: ");
643 if ((readret
= read(fd
, buf
, length
)) < length
)
645 fprintf(stderr
, "read (%d %ld) -> %d\n", fd
, length
, readret
);
648 t_freebytes(buf
, length
);
651 /* optionally map carriage return to semicolon */
655 for (i
= 0; i
< length
; i
++)
659 binbuf_text(b
, buf
, length
);
662 startpost("binbuf_read "); postatom(b
->b_n
, b
->b_vec
); endpost();
665 t_freebytes(buf
, length
);
670 int binbuf_read_via_path(t_binbuf
*b
, char *filename
, char *dirname
,
674 char buf
[MAXPDSTRING
], *bufptr
;
675 if ((filedesc
= open_via_path(
676 dirname
, filename
, "", buf
, &bufptr
, MAXPDSTRING
, 0)) < 0)
678 error("%s: can't open", filename
);
681 else close (filedesc
);
682 if (binbuf_read(b
, bufptr
, buf
, crflag
))
687 #define WBUFSIZE 4096
688 static t_binbuf
*binbuf_convert(t_binbuf
*oldb
, int maxtopd
);
690 /* write a binbuf to a text file. If "crflag" is set we suppress
692 int binbuf_write(t_binbuf
*x
, char *filename
, char *dir
, int crflag
)
695 char sbuf
[WBUFSIZE
], fbuf
[MAXPDSTRING
], *bp
= sbuf
, *ep
= sbuf
+ WBUFSIZE
;
697 int indx
, deleteit
= 0;
702 strcat(fbuf
, dir
), strcat(fbuf
, "/");
703 strcat(fbuf
, filename
);
704 if (!strcmp(filename
+ strlen(filename
) - 4, ".pat"))
706 x
= binbuf_convert(x
, 0);
710 if (!(f
= binbuf_dofopen(fbuf
, "w")))
712 fprintf(stderr
, "open: ");
716 for (ap
= x
->b_vec
, indx
= x
->b_n
; indx
--; ap
++)
719 /* estimate how many characters will be needed. Printing out
720 symbols may need extra characters for inserting backslashes. */
721 if (ap
->a_type
== A_SYMBOL
|| ap
->a_type
== A_DOLLSYM
)
722 length
= 80 + strlen(ap
->a_w
.w_symbol
->s_name
);
724 if (ep
- bp
< length
)
726 if (fwrite(sbuf
, bp
-sbuf
, 1, f
) < 1)
733 if ((ap
->a_type
== A_SEMI
|| ap
->a_type
== A_COMMA
) &&
734 bp
> sbuf
&& bp
[-1] == ' ') bp
--;
735 if (!crflag
|| ap
->a_type
!= A_SEMI
)
737 atom_string(ap
, bp
, (ep
-bp
)-2);
742 if (ap
->a_type
== A_SEMI
|| (!crflag
&& ncolumn
> 65))
753 if (fwrite(sbuf
, bp
-sbuf
, 1, f
) < 1)
770 /* The following routine attempts to convert from max to pd or back. The
771 max to pd direction is working OK but you will need to make lots of
772 abstractions for objects like "gate" which don't exist in Pd. conversion
773 from Pd to Max hasn't been tested for patches with subpatches yet! */
775 #define MAXSTACK 1000
777 #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \
778 !strcmp((a)->a_w.w_symbol->s_name, (b)))
780 static t_binbuf
*binbuf_convert(t_binbuf
*oldb
, int maxtopd
)
782 t_binbuf
*newb
= binbuf_new();
783 t_atom
*vec
= oldb
->b_vec
;
784 t_int n
= oldb
->b_n
, nextindex
, stackdepth
= 0, stack
[MAXSTACK
],
786 t_atom outmess
[MAXSTACK
], *nextmess
;
788 binbuf_addv(newb
, "ss;", gensym("max"), gensym("v2"));
789 for (nextindex
= 0; nextindex
< n
; )
792 char *first
, *second
;
793 for (endmess
= nextindex
; endmess
< n
&& vec
[endmess
].a_type
!= A_SEMI
;
796 if (endmess
== n
) break;
797 if (endmess
== nextindex
|| endmess
== nextindex
+ 1
798 || vec
[nextindex
].a_type
!= A_SYMBOL
||
799 vec
[nextindex
+1].a_type
!= A_SYMBOL
)
801 nextindex
= endmess
+ 1;
804 natom
= endmess
- nextindex
;
805 if (natom
> MAXSTACK
-10) natom
= MAXSTACK
-10;
806 nextmess
= vec
+ nextindex
;
807 first
= nextmess
->a_w
.w_symbol
->s_name
;
808 second
= (nextmess
+1)->a_w
.w_symbol
->s_name
;
811 /* case 1: importing a ".pat" file into Pd. */
813 /* dollar signs in file translate to symbols */
814 for (i
= 0; i
< natom
; i
++)
816 if (nextmess
[i
].a_type
== A_DOLLAR
)
819 sprintf(buf
, "$%d", nextmess
[i
].a_w
.w_index
);
820 SETSYMBOL(nextmess
+i
, gensym(buf
));
822 else if (nextmess
[i
].a_type
== A_DOLLSYM
)
825 sprintf(buf
, "$%s", nextmess
[i
].a_w
.w_symbol
->s_name
);
826 SETSYMBOL(nextmess
+i
, gensym(buf
));
829 if (!strcmp(first
, "#N"))
831 if (!strcmp(second
, "vpatcher"))
833 if (stackdepth
>= MAXSTACK
)
835 post("too many embedded patches");
838 stack
[stackdepth
] = nobj
;
841 binbuf_addv(newb
, "ssfffff;",
842 gensym("#N"), gensym("canvas"),
843 atom_getfloatarg(2, natom
, nextmess
),
844 atom_getfloatarg(3, natom
, nextmess
),
845 atom_getfloatarg(4, natom
, nextmess
) -
846 atom_getfloatarg(2, natom
, nextmess
),
847 atom_getfloatarg(5, natom
, nextmess
) -
848 atom_getfloatarg(3, natom
, nextmess
),
849 (float)sys_defaultfont
);
852 if (!strcmp(first
, "#P"))
854 /* drop initial "hidden" flag */
855 if (!strcmp(second
, "hidden"))
859 second
= (nextmess
+1)->a_w
.w_symbol
->s_name
;
861 if (natom
>= 7 && !strcmp(second
, "newobj")
862 && (ISSYMBOL(&nextmess
[6], "patcher") ||
863 ISSYMBOL(&nextmess
[6], "p")))
865 binbuf_addv(newb
, "ssffss;",
866 gensym("#X"), gensym("restore"),
867 atom_getfloatarg(2, natom
, nextmess
),
868 atom_getfloatarg(3, natom
, nextmess
),
869 gensym("pd"), atom_getsymbolarg(7, natom
, nextmess
));
870 if (stackdepth
) stackdepth
--;
871 nobj
= stack
[stackdepth
];
874 else if (!strcmp(second
, "newex") || !strcmp(second
, "newobj"))
876 t_symbol
*classname
=
877 atom_getsymbolarg(6, natom
, nextmess
);
878 if (classname
== gensym("trigger") ||
879 classname
== gensym("t"))
881 for (i
= 7; i
< natom
; i
++)
882 if (nextmess
[i
].a_type
== A_SYMBOL
&&
883 nextmess
[i
].a_w
.w_symbol
== gensym("i"))
884 nextmess
[i
].a_w
.w_symbol
= gensym("f");
886 if (classname
== gensym("table"))
887 classname
= gensym("TABLE");
888 SETSYMBOL(outmess
, gensym("#X"));
889 SETSYMBOL(outmess
+ 1, gensym("obj"));
890 outmess
[2] = nextmess
[2];
891 outmess
[3] = nextmess
[3];
892 SETSYMBOL(outmess
+4, classname
);
893 for (i
= 7; i
< natom
; i
++)
894 outmess
[i
-2] = nextmess
[i
];
895 SETSEMI(outmess
+ natom
- 2);
896 binbuf_add(newb
, natom
- 1, outmess
);
899 else if (!strcmp(second
, "message") ||
900 !strcmp(second
, "comment"))
902 SETSYMBOL(outmess
, gensym("#X"));
903 SETSYMBOL(outmess
+ 1, gensym(
904 (strcmp(second
, "message") ? "text" : "msg")));
905 outmess
[2] = nextmess
[2];
906 outmess
[3] = nextmess
[3];
907 for (i
= 6; i
< natom
; i
++)
908 outmess
[i
-2] = nextmess
[i
];
909 SETSEMI(outmess
+ natom
- 2);
910 binbuf_add(newb
, natom
- 1, outmess
);
913 else if (!strcmp(second
, "button"))
915 binbuf_addv(newb
, "ssffs;",
916 gensym("#X"), gensym("obj"),
917 atom_getfloatarg(2, natom
, nextmess
),
918 atom_getfloatarg(3, natom
, nextmess
),
922 else if (!strcmp(second
, "number") || !strcmp(second
, "flonum"))
924 binbuf_addv(newb
, "ssff;",
925 gensym("#X"), gensym("floatatom"),
926 atom_getfloatarg(2, natom
, nextmess
),
927 atom_getfloatarg(3, natom
, nextmess
));
930 else if (!strcmp(second
, "slider"))
932 float inc
= atom_getfloatarg(7, natom
, nextmess
);
935 binbuf_addv(newb
, "ssffsffffffsssfffffffff;",
936 gensym("#X"), gensym("obj"),
937 atom_getfloatarg(2, natom
, nextmess
),
938 atom_getfloatarg(3, natom
, nextmess
),
940 atom_getfloatarg(4, natom
, nextmess
),
941 atom_getfloatarg(5, natom
, nextmess
),
942 atom_getfloatarg(6, natom
, nextmess
),
943 atom_getfloatarg(6, natom
, nextmess
)
944 + (atom_getfloatarg(5, natom
, nextmess
) - 1) * inc
,
946 gensym("empty"), gensym("empty"), gensym("empty"),
947 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
950 else if (!strcmp(second
, "toggle"))
952 binbuf_addv(newb
, "ssffs;",
953 gensym("#X"), gensym("obj"),
954 atom_getfloatarg(2, natom
, nextmess
),
955 atom_getfloatarg(3, natom
, nextmess
),
959 else if (!strcmp(second
, "inlet"))
961 binbuf_addv(newb
, "ssffs;",
962 gensym("#X"), gensym("obj"),
963 atom_getfloatarg(2, natom
, nextmess
),
964 atom_getfloatarg(3, natom
, nextmess
),
965 gensym((natom
> 5 ? "inlet~" : "inlet")));
968 else if (!strcmp(second
, "outlet"))
970 binbuf_addv(newb
, "ssffs;",
971 gensym("#X"), gensym("obj"),
972 atom_getfloatarg(2, natom
, nextmess
),
973 atom_getfloatarg(3, natom
, nextmess
),
974 gensym((natom
> 5 ? "outlet~" : "outlet")));
977 else if (!strcmp(second
, "user"))
979 binbuf_addv(newb
, "ssffs;",
980 gensym("#X"), gensym("obj"),
981 atom_getfloatarg(3, natom
, nextmess
),
982 atom_getfloatarg(4, natom
, nextmess
),
983 atom_getsymbolarg(2, natom
, nextmess
));
986 else if (!strcmp(second
, "connect")||
987 !strcmp(second
, "fasten"))
989 binbuf_addv(newb
, "ssffff;",
990 gensym("#X"), gensym("connect"),
991 nobj
- atom_getfloatarg(2, natom
, nextmess
) - 1,
992 atom_getfloatarg(3, natom
, nextmess
),
993 nobj
- atom_getfloatarg(4, natom
, nextmess
) - 1,
994 atom_getfloatarg(5, natom
, nextmess
));
1000 if (!strcmp(first
, "#N"))
1002 if (!strcmp(second
, "canvas"))
1004 if (stackdepth
>= MAXSTACK
)
1006 post("too many embedded patches");
1009 stack
[stackdepth
] = nobj
;
1012 binbuf_addv(newb
, "ssffff;",
1013 gensym("#N"), gensym("vpatcher"),
1014 atom_getfloatarg(2, natom
, nextmess
),
1015 atom_getfloatarg(3, natom
, nextmess
),
1016 atom_getfloatarg(4, natom
, nextmess
),
1017 atom_getfloatarg(5, natom
, nextmess
));
1020 if (!strcmp(first
, "#X"))
1022 if (natom
>= 5 && !strcmp(second
, "restore")
1023 && (ISSYMBOL (&nextmess
[4], "pd")))
1025 binbuf_addv(newb
, "ss;", gensym("#P"), gensym("pop"));
1026 binbuf_addv(newb
, "ssffffss;",
1027 gensym("#P"), gensym("newobj"),
1028 atom_getfloatarg(2, natom
, nextmess
),
1029 atom_getfloatarg(3, natom
, nextmess
), 50., 1.,
1031 atom_getsymbolarg(5, natom
, nextmess
));
1032 if (stackdepth
) stackdepth
--;
1033 nobj
= stack
[stackdepth
];
1036 else if (!strcmp(second
, "obj"))
1038 t_symbol
*classname
=
1039 atom_getsymbolarg(4, natom
, nextmess
);
1040 if (classname
== gensym("inlet"))
1041 binbuf_addv(newb
, "ssfff;", gensym("#P"),
1043 atom_getfloatarg(2, natom
, nextmess
),
1044 atom_getfloatarg(3, natom
, nextmess
),
1046 else if (classname
== gensym("inlet~"))
1047 binbuf_addv(newb
, "ssffff;", gensym("#P"),
1049 atom_getfloatarg(2, natom
, nextmess
),
1050 atom_getfloatarg(3, natom
, nextmess
),
1052 else if (classname
== gensym("outlet"))
1053 binbuf_addv(newb
, "ssfff;", gensym("#P"),
1055 atom_getfloatarg(2, natom
, nextmess
),
1056 atom_getfloatarg(3, natom
, nextmess
),
1058 else if (classname
== gensym("outlet~"))
1059 binbuf_addv(newb
, "ssffff;", gensym("#P"),
1061 atom_getfloatarg(2, natom
, nextmess
),
1062 atom_getfloatarg(3, natom
, nextmess
),
1064 else if (classname
== gensym("bng"))
1065 binbuf_addv(newb
, "ssffff;", gensym("#P"),
1067 atom_getfloatarg(2, natom
, nextmess
),
1068 atom_getfloatarg(3, natom
, nextmess
),
1069 atom_getfloatarg(5, natom
, nextmess
), 0.);
1070 else if (classname
== gensym("tgl"))
1071 binbuf_addv(newb
, "ssffff;", gensym("#P"),
1073 atom_getfloatarg(2, natom
, nextmess
),
1074 atom_getfloatarg(3, natom
, nextmess
),
1075 atom_getfloatarg(5, natom
, nextmess
), 0.);
1076 else if (classname
== gensym("vsl"))
1077 binbuf_addv(newb
, "ssffffff;", gensym("#P"),
1079 atom_getfloatarg(2, natom
, nextmess
),
1080 atom_getfloatarg(3, natom
, nextmess
),
1081 atom_getfloatarg(5, natom
, nextmess
),
1082 atom_getfloatarg(6, natom
, nextmess
),
1083 (atom_getfloatarg(8, natom
, nextmess
) -
1084 atom_getfloatarg(7, natom
, nextmess
)) /
1085 (atom_getfloatarg(6, natom
, nextmess
) == 1? 1 :
1086 atom_getfloatarg(6, natom
, nextmess
) - 1),
1087 atom_getfloatarg(7, natom
, nextmess
));
1090 SETSYMBOL(outmess
, gensym("#P"));
1091 SETSYMBOL(outmess
+ 1, gensym("newex"));
1092 outmess
[2] = nextmess
[2];
1093 outmess
[3] = nextmess
[3];
1094 SETFLOAT(outmess
+ 4, 50);
1095 SETFLOAT(outmess
+ 5, 1);
1096 for (i
= 4; i
< natom
; i
++)
1097 outmess
[i
+2] = nextmess
[i
];
1098 SETSEMI(outmess
+ natom
+ 2);
1099 binbuf_add(newb
, natom
+ 3, outmess
);
1104 else if (!strcmp(second
, "msg") ||
1105 !strcmp(second
, "text"))
1107 SETSYMBOL(outmess
, gensym("#P"));
1108 SETSYMBOL(outmess
+ 1, gensym(
1109 (strcmp(second
, "msg") ? "comment" : "message")));
1110 outmess
[2] = nextmess
[2];
1111 outmess
[3] = nextmess
[3];
1112 SETFLOAT(outmess
+ 4, 50);
1113 SETFLOAT(outmess
+ 5, 1);
1114 for (i
= 4; i
< natom
; i
++)
1115 outmess
[i
+2] = nextmess
[i
];
1116 SETSEMI(outmess
+ natom
+ 2);
1117 binbuf_add(newb
, natom
+ 3, outmess
);
1120 else if (!strcmp(second
, "floatatom"))
1122 binbuf_addv(newb
, "ssfff;",
1123 gensym("#P"), gensym("flonum"),
1124 atom_getfloatarg(2, natom
, nextmess
),
1125 atom_getfloatarg(3, natom
, nextmess
), 35);
1128 else if (!strcmp(second
, "connect"))
1130 binbuf_addv(newb
, "ssffff;",
1131 gensym("#P"), gensym("connect"),
1132 nobj
- atom_getfloatarg(2, natom
, nextmess
) - 1,
1133 atom_getfloatarg(3, natom
, nextmess
),
1134 nobj
- atom_getfloatarg(4, natom
, nextmess
) - 1,
1135 atom_getfloatarg(5, natom
, nextmess
));
1139 nextindex
= endmess
+ 1;
1142 binbuf_addv(newb
, "ss;", gensym("#P"), gensym("pop"));
1144 binbuf_write(newb
, "import-result.pd", "/tmp", 0);
1149 /* function to support searching */
1150 int binbuf_match(t_binbuf
*inbuf
, t_binbuf
*searchbuf
)
1152 int indexin
, nmatched
;
1153 for (indexin
= 0; indexin
<= inbuf
->b_n
- searchbuf
->b_n
; indexin
++)
1155 for (nmatched
= 0; nmatched
< searchbuf
->b_n
; nmatched
++)
1157 t_atom
*a1
= &inbuf
->b_vec
[indexin
+ nmatched
],
1158 *a2
= &searchbuf
->b_vec
[nmatched
];
1159 if (a1
->a_type
!= a2
->a_type
||
1160 a1
->a_type
== A_SYMBOL
&& a1
->a_w
.w_symbol
!= a2
->a_w
.w_symbol
1162 a1
->a_type
== A_FLOAT
&& a1
->a_w
.w_float
!= a2
->a_w
.w_float
1164 a1
->a_type
== A_DOLLAR
&& a1
->a_w
.w_index
!= a2
->a_w
.w_index
1166 a1
->a_type
== A_DOLLSYM
&& a1
->a_w
.w_symbol
!= a2
->a_w
.w_symbol
)
1175 void pd_doloadbang(void);
1177 /* LATER make this evaluate the file on-the-fly. */
1178 /* LATER figure out how to log errors */
1179 void binbuf_evalfile(t_symbol
*name
, t_symbol
*dir
)
1181 t_binbuf
*b
= binbuf_new();
1182 int import
= !strcmp(name
->s_name
+ strlen(name
->s_name
) - 4, ".pat");
1183 /* set filename so that new canvases can pick them up */
1184 int dspstate
= canvas_suspend_dsp();
1185 glob_setfilename(0, name
, dir
);
1186 if (binbuf_read(b
, name
->s_name
, dir
->s_name
, 0))
1188 perror(name
->s_name
);
1194 t_binbuf
*newb
= binbuf_convert(b
, 1);
1198 binbuf_eval(b
, 0, 0, 0);
1200 glob_setfilename(0, &s_
, &s_
); /* bug fix by Krzysztof Czaja */
1202 canvas_resume_dsp(dspstate
);
1205 void glob_evalfile(t_pd
*ignore
, t_symbol
*name
, t_symbol
*dir
)
1208 /* even though binbuf_evalfile appears to take care of dspstate,
1209 we have to do it again here, because canvas_startdsp() assumes
1210 that all toplevel canvases are visible. LATER check if this
1211 is still necessary -- probably not. */
1213 int dspstate
= canvas_suspend_dsp();
1214 binbuf_evalfile(name
, dir
);
1215 while ((x
!= s__X
.s_thing
) && (x
= s__X
.s_thing
))
1216 vmess(x
, gensym("pop"), "i", 1);
1218 canvas_resume_dsp(dspstate
);
1220 /* Copyright (c) 1997-1999 Miller Puckette.
1221 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
1222 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1226 * changed the canvas_restore in "g_canvas.c", so that it might accept $args as well (like "pd $0_test")
1227 * so you can make multiple & distinguishable templates
1228 * 1511:forum::für::umläute:2001
1229 * change marked with IOhannes
1234 #include "s_stuff.h"
1252 t_binbuf
*binbuf_new(void)
1254 t_binbuf
*x
= (t_binbuf
*)t_getbytes(sizeof(*x
));
1256 x
->b_vec
= t_getbytes(0);
1260 void binbuf_free(t_binbuf
*x
)
1262 t_freebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
));
1263 t_freebytes(x
, sizeof(*x
));
1266 t_binbuf
*binbuf_duplicate(t_binbuf
*y
)
1268 t_binbuf
*x
= (t_binbuf
*)t_getbytes(sizeof(*x
));
1270 x
->b_vec
= t_getbytes(x
->b_n
* sizeof(*x
->b_vec
));
1271 memcpy(x
->b_vec
, y
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
));
1275 void binbuf_clear(t_binbuf
*x
)
1277 x
->b_vec
= t_resizebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
), 0);
1281 /* convert text to a binbuf */
1282 void binbuf_text(t_binbuf
*x
, char *text
, size_t size
)
1284 char buf
[MAXPDSTRING
+1], *bufp
, *ebuf
= buf
+MAXPDSTRING
;
1285 const char *textp
= text
, *etext
= text
+size
;
1287 int nalloc
= 16, natom
= 0;
1288 t_freebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
));
1289 x
->b_vec
= t_getbytes(nalloc
* sizeof(*x
->b_vec
));
1295 /* skip leading space */
1296 while ((textp
!= etext
) && (*textp
== ' ' || *textp
== '\n'
1297 || *textp
== '\r' || *textp
== '\t')) textp
++;
1298 if (textp
== etext
) break;
1299 if (*textp
== ';') SETSEMI(ap
), textp
++;
1300 else if (*textp
== ',') SETCOMMA(ap
), textp
++;
1303 /* it's an atom other than a comma or semi */
1305 int floatstate
= 0, slash
= 0, lastslash
= 0,
1306 firstslash
= (*textp
== '\\');
1310 c
= *bufp
= *textp
++;
1312 slash
= (c
== '\\');
1314 if (floatstate
>= 0)
1316 int digit
= (c
>= '0' && c
<= '9'),
1317 dot
= (c
== '.'), minus
= (c
== '-'),
1318 plusminus
= (minus
|| (c
== '+')),
1319 expon
= (c
== 'e' || c
== 'E');
1320 if (floatstate
== 0) /* beginning */
1322 if (minus
) floatstate
= 1;
1323 else if (digit
) floatstate
= 2;
1324 else if (dot
) floatstate
= 3;
1325 else floatstate
= -1;
1327 else if (floatstate
== 1) /* got minus */
1329 if (digit
) floatstate
= 2;
1330 else if (dot
) floatstate
= 3;
1331 else floatstate
= -1;
1333 else if (floatstate
== 2) /* got digits */
1335 if (dot
) floatstate
= 4;
1336 else if (expon
) floatstate
= 6;
1337 else if (!digit
) floatstate
= -1;
1339 else if (floatstate
== 3) /* got '.' without digits */
1341 if (digit
) floatstate
= 5;
1342 else floatstate
= -1;
1344 else if (floatstate
== 4) /* got '.' after digits */
1346 if (digit
) floatstate
= 5;
1347 else if (expon
) floatstate
= 6;
1348 else floatstate
= -1;
1350 else if (floatstate
== 5) /* got digits after . */
1352 if (expon
) floatstate
= 6;
1353 else if (!digit
) floatstate
= -1;
1355 else if (floatstate
== 6) /* got 'e' */
1357 if (plusminus
) floatstate
= 7;
1358 else if (digit
) floatstate
= 8;
1359 else floatstate
= -1;
1361 else if (floatstate
== 7) /* got plus or minus */
1363 if (digit
) floatstate
= 8;
1364 else floatstate
= -1;
1366 else if (floatstate
== 8) /* got digits */
1368 if (!digit
) floatstate
= -1;
1373 while (textp
!= etext
&& bufp
!= ebuf
&&
1374 (slash
|| (*textp
!= ' ' && *textp
!= '\n' && *textp
!= '\r'
1375 && *textp
!= '\t' &&*textp
!= ',' && *textp
!= ';')));
1378 post("buf %s", buf
);
1380 if (*buf
== '$' && buf
[1] >= '0' && buf
[1] <= '9' && !firstslash
)
1382 for (bufp
= buf
+2; *bufp
; bufp
++)
1383 if (*bufp
< '0' || *bufp
> '9')
1385 SETDOLLSYM(ap
, gensym(buf
+1));
1388 SETDOLLAR(ap
, atoi(buf
+1));
1393 if (floatstate
== 2 || floatstate
== 4 || floatstate
== 5 ||
1395 SETFLOAT(ap
, atof(buf
));
1396 else SETSYMBOL(ap
, gensym(buf
));
1401 if (natom
== nalloc
)
1403 x
->b_vec
= t_resizebytes(x
->b_vec
, nalloc
* sizeof(*x
->b_vec
),
1404 nalloc
* (2*sizeof(*x
->b_vec
)));
1405 nalloc
= nalloc
* 2;
1406 ap
= x
->b_vec
+ natom
;
1408 if (textp
== etext
) break;
1410 /* reallocate the vector to exactly the right size */
1411 x
->b_vec
= t_resizebytes(x
->b_vec
, nalloc
* sizeof(*x
->b_vec
),
1412 natom
* sizeof(*x
->b_vec
));
1416 /* convert a binbuf to text; no null termination. */
1417 void binbuf_gettext(t_binbuf
*x
, char **bufp
, int *lengthp
)
1419 char *buf
= getbytes(0), *newbuf
;
1421 char string
[MAXPDSTRING
];
1425 for (ap
= x
->b_vec
, indx
= x
->b_n
; indx
--; ap
++)
1428 if ((ap
->a_type
== A_SEMI
|| ap
->a_type
== A_COMMA
) &&
1429 length
&& buf
[length
-1] == ' ') length
--;
1430 atom_string(ap
, string
, MAXPDSTRING
);
1431 newlength
= length
+ strlen(string
) + 1;
1432 if (!(newbuf
= resizebytes(buf
, length
, newlength
))) break;
1434 strcpy(buf
+ length
, string
);
1436 if (ap
->a_type
== A_SEMI
) buf
[length
-1] = '\n';
1437 else buf
[length
-1] = ' ';
1439 if (length
&& buf
[length
-1] == ' ')
1441 if (newbuf
= t_resizebytes(buf
, length
, length
-1))
1451 /* LATER improve the out-of-space behavior below. Also fix this so that
1452 writing to file doesn't buffer everything together. */
1454 void binbuf_add(t_binbuf
*x
, int argc
, t_atom
*argv
)
1456 int newsize
= x
->b_n
+ argc
, i
;
1458 if (ap
= t_resizebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
),
1459 newsize
* sizeof(*x
->b_vec
)))
1463 error("binbuf_addmessage: out of space");
1467 startpost("binbuf_add: ");
1468 postatom(argc
, argv
);
1471 for (ap
= x
->b_vec
+ x
->b_n
, i
= argc
; i
--; ap
++)
1476 #define MAXADDMESSV 100
1477 void binbuf_addv(t_binbuf
*x
, char *fmt
, ...)
1480 t_atom arg
[MAXADDMESSV
], *at
=arg
;
1487 if (nargs
>= MAXADDMESSV
)
1489 error("binbuf_addmessv: only %d allowed", MAXADDMESSV
);
1494 case 'i': SETFLOAT(at
, va_arg(ap
, t_int
)); break;
1495 case 'f': SETFLOAT(at
, va_arg(ap
, double)); break;
1496 case 's': SETSYMBOL(at
, va_arg(ap
, t_symbol
*)); break;
1497 case ';': SETSEMI(at
); break;
1498 case ',': SETCOMMA(at
); break;
1506 binbuf_add(x
, nargs
, arg
);
1509 /* add a binbuf to another one for saving. Semicolons and commas go to
1510 symbols ";", "'",; the symbol ";" goes to "\;", etc. */
1512 void binbuf_addbinbuf(t_binbuf
*x
, t_binbuf
*y
)
1514 t_binbuf
*z
= binbuf_new();
1517 binbuf_add(z
, y
->b_n
, y
->b_vec
);
1518 for (i
= 0, ap
= z
->b_vec
; i
< z
->b_n
; i
++, ap
++)
1520 char tbuf
[MAXPDSTRING
];
1526 SETSYMBOL(ap
, gensym(";"));
1529 SETSYMBOL(ap
, gensym(","));
1532 sprintf(tbuf
, "$%d", ap
->a_w
.w_index
);
1533 SETSYMBOL(ap
, gensym(tbuf
));
1536 sprintf(tbuf
, "$%s", ap
->a_w
.w_symbol
->s_name
);
1537 SETSYMBOL(ap
, gensym(tbuf
));
1540 /* FIXME make this general */
1541 if (!strcmp(ap
->a_w
.w_symbol
->s_name
, ";"))
1542 SETSYMBOL(ap
, gensym(";"));
1543 else if (!strcmp(ap
->a_w
.w_symbol
->s_name
, ","))
1544 SETSYMBOL(ap
, gensym(","));
1547 bug("binbuf_addbinbuf");
1551 binbuf_add(x
, z
->b_n
, z
->b_vec
);
1554 void binbuf_addsemi(t_binbuf
*x
)
1558 binbuf_add(x
, 1, &a
);
1561 /* Supply atoms to a binbuf from a message, making the opposite changes
1562 from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
1564 void binbuf_restore(t_binbuf
*x
, int argc
, t_atom
*argv
)
1566 int newsize
= x
->b_n
+ argc
, i
;
1568 if (ap
= t_resizebytes(x
->b_vec
, x
->b_n
* sizeof(*x
->b_vec
),
1569 newsize
* sizeof(*x
->b_vec
)))
1573 error("binbuf_addmessage: out of space");
1577 for (ap
= x
->b_vec
+ x
->b_n
, i
= argc
; i
--; ap
++)
1579 if (argv
->a_type
== A_SYMBOL
)
1581 char *str
= argv
->a_w
.w_symbol
->s_name
;
1582 if (!strcmp(str
, ";")) SETSEMI(ap
);
1583 else if (!strcmp(str
, ",")) SETCOMMA(ap
);
1584 else if (str
[0] == '$' && str
[1] >= '0' && str
[1] <= '9')
1588 for (str2
= str
+ 2; *str2
; str2
++)
1589 if (*str2
< '0' || *str2
> '9')
1592 SETDOLLSYM(ap
, gensym(str
+ 1));
1596 sscanf(argv
->a_w
.w_symbol
->s_name
+ 1, "%d", &dollar
);
1597 SETDOLLAR(ap
, dollar
);
1603 else *ap
= *(argv
++);
1609 #define MSTACKSIZE 2048
1611 void binbuf_print(t_binbuf
*x
)
1613 int i
, startedpost
= 0, newline
= 1;
1614 for (i
= 0; i
< x
->b_n
; i
++)
1618 if (startedpost
) endpost();
1622 postatom(1, x
->b_vec
+ i
);
1623 if (x
->b_vec
[i
].a_type
== A_SEMI
)
1627 if (startedpost
) endpost();
1630 int binbuf_getnatom(t_binbuf
*x
)
1635 t_atom
*binbuf_getvec(t_binbuf
*x
)
1640 int canvas_getdollarzero( void);
1642 t_symbol
*binbuf_realizedollsym(t_symbol
*s
, int ac
, t_atom
*av
, int tonew
)
1644 int argno
= atol(s
->s_name
), lastnum
;
1645 char buf
[MAXPDSTRING
], c
, *sp
;
1646 for (lastnum
= 0, sp
= s
->s_name
; ((c
= *sp
) && c
>= '0' && c
<= '9');
1648 if (!c
|| argno
< 0 || argno
> ac
)
1652 else sprintf(buf
, "$%d", argno
);
1654 else if (argno
== 0)
1655 sprintf(buf
, "%d", canvas_getdollarzero());
1657 atom_string(av
+(argno
-1), buf
, MAXPDSTRING
/2-1);
1658 strncat(buf
, sp
, MAXPDSTRING
/2-1);
1659 return (gensym(buf
));
1662 void binbuf_eval(t_binbuf
*x
, t_pd
*target
, int argc
, t_atom
*argv
)
1664 static t_atom mstack
[MSTACKSIZE
], *msp
= mstack
, *ems
= mstack
+MSTACKSIZE
;
1665 t_atom
*stackwas
= msp
;
1666 t_atom
*at
= x
->b_vec
;
1676 while (ac
&& (at
->a_type
== A_SEMI
|| at
->a_type
== A_COMMA
))
1679 if (at
->a_type
== A_DOLLAR
)
1681 if (at
->a_w
.w_index
<= 0 || at
->a_w
.w_index
> argc
)
1683 error("$%d: not enough arguments supplied",
1687 else if (argv
[at
->a_w
.w_index
-1].a_type
!= A_SYMBOL
)
1689 error("$%d: symbol needed as message destination",
1693 else s
= argv
[at
->a_w
.w_index
-1].a_w
.w_symbol
;
1695 else if (at
->a_type
== A_DOLLSYM
)
1697 if (!(s
= binbuf_realizedollsym(at
->a_w
.w_symbol
,
1700 error("$%s: not enough arguments supplied",
1701 at
->a_w
.w_symbol
->s_name
);
1705 else s
= atom_getsymbol(at
);
1706 if (!(target
= s
->s_thing
))
1708 error("%s: no such object", s
->s_name
);
1711 while (ac
&& at
->a_type
!= A_SEMI
);
1712 /* LATER eat args until semicolon and continue */
1723 nexttarget
= target
;
1727 if (!ac
) goto gotmess
;
1730 error("message stack overflow");
1736 /* semis and commas in new message just get bashed to
1737 a symbol. This is needed so you can pass them to "expr." */
1738 if (target
== &pd_objectmaker
)
1740 SETSYMBOL(msp
, gensym(";"));
1749 if (target
== &pd_objectmaker
)
1751 SETSYMBOL(msp
, gensym(","));
1760 if (at
->a_w
.w_index
> 0 && at
->a_w
.w_index
<= argc
)
1761 *msp
= argv
[at
->a_w
.w_index
-1];
1762 else if (at
->a_w
.w_index
== 0)
1763 SETFLOAT(msp
, canvas_getdollarzero());
1766 if (target
== &pd_objectmaker
)
1770 error("$%d: argument number out of range",
1777 s9
= binbuf_realizedollsym(at
->a_w
.w_symbol
, argc
, argv
,
1778 target
== &pd_objectmaker
);
1784 bug("bad item in binbuf");
1795 switch (stackwas
->a_type
)
1798 typedmess(target
, stackwas
->a_w
.w_symbol
, nargs
-1, stackwas
+1);
1801 if (nargs
== 1) pd_float(target
, stackwas
->a_w
.w_float
);
1802 else pd_list(target
, 0, nargs
, stackwas
);
1808 target
= nexttarget
;
1818 static int binbuf_doopen(char *s
, int mode
)
1820 char namebuf
[MAXPDSTRING
];
1824 sys_bashfilename(s
, namebuf
);
1825 return (open(namebuf
, mode
));
1828 static FILE *binbuf_dofopen(char *s
, char *mode
)
1830 char namebuf
[MAXPDSTRING
];
1831 sys_bashfilename(s
, namebuf
);
1832 return (fopen(namebuf
, mode
));
1835 int binbuf_read(t_binbuf
*b
, char *filename
, char *dirname
, int crflag
)
1841 char namebuf
[MAXPDSTRING
];
1845 strcat(namebuf
, dirname
), strcat(namebuf
, "/");
1846 strcat(namebuf
, filename
);
1848 if ((fd
= binbuf_doopen(namebuf
, 0)) < 0)
1850 fprintf(stderr
, "open: ");
1854 if ((length
= lseek(fd
, 0, SEEK_END
)) < 0 || lseek(fd
, 0, SEEK_SET
) < 0
1855 || !(buf
= t_getbytes(length
)))
1857 fprintf(stderr
, "lseek: ");
1862 if ((readret
= read(fd
, buf
, length
)) < length
)
1864 fprintf(stderr
, "read (%d %ld) -> %d\n", fd
, length
, readret
);
1867 t_freebytes(buf
, length
);
1870 /* optionally map carriage return to semicolon */
1874 for (i
= 0; i
< length
; i
++)
1878 binbuf_text(b
, buf
, length
);
1881 startpost("binbuf_read "); postatom(b
->b_n
, b
->b_vec
); endpost();
1884 t_freebytes(buf
, length
);
1889 int binbuf_read_via_path(t_binbuf
*b
, char *filename
, char *dirname
,
1893 char buf
[MAXPDSTRING
], *bufptr
;
1894 if ((filedesc
= open_via_path(
1895 dirname
, filename
, "", buf
, &bufptr
, MAXPDSTRING
, 0)) < 0)
1897 error("%s: can't open", filename
);
1900 else close (filedesc
);
1901 if (binbuf_read(b
, bufptr
, buf
, crflag
))
1906 #define WBUFSIZE 4096
1907 static t_binbuf
*binbuf_convert(t_binbuf
*oldb
, int maxtopd
);
1909 /* write a binbuf to a text file. If "crflag" is set we suppress
1911 int binbuf_write(t_binbuf
*x
, char *filename
, char *dir
, int crflag
)
1914 char sbuf
[WBUFSIZE
], fbuf
[MAXPDSTRING
], *bp
= sbuf
, *ep
= sbuf
+ WBUFSIZE
;
1916 int indx
, deleteit
= 0;
1921 strcat(fbuf
, dir
), strcat(fbuf
, "/");
1922 strcat(fbuf
, filename
);
1923 if (!strcmp(filename
+ strlen(filename
) - 4, ".pat"))
1925 x
= binbuf_convert(x
, 0);
1929 if (!(f
= binbuf_dofopen(fbuf
, "w")))
1931 fprintf(stderr
, "open: ");
1932 sys_unixerror(fbuf
);
1935 for (ap
= x
->b_vec
, indx
= x
->b_n
; indx
--; ap
++)
1938 /* estimate how many characters will be needed. Printing out
1939 symbols may need extra characters for inserting backslashes. */
1940 if (ap
->a_type
== A_SYMBOL
|| ap
->a_type
== A_DOLLSYM
)
1941 length
= 80 + strlen(ap
->a_w
.w_symbol
->s_name
);
1943 if (ep
- bp
< length
)
1945 if (fwrite(sbuf
, bp
-sbuf
, 1, f
) < 1)
1947 sys_unixerror(fbuf
);
1952 if ((ap
->a_type
== A_SEMI
|| ap
->a_type
== A_COMMA
) &&
1953 bp
> sbuf
&& bp
[-1] == ' ') bp
--;
1954 if (!crflag
|| ap
->a_type
!= A_SEMI
)
1956 atom_string(ap
, bp
, (ep
-bp
)-2);
1957 length
= strlen(bp
);
1961 if (ap
->a_type
== A_SEMI
|| (!crflag
&& ncolumn
> 65))
1972 if (fwrite(sbuf
, bp
-sbuf
, 1, f
) < 1)
1974 sys_unixerror(fbuf
);
1989 /* The following routine attempts to convert from max to pd or back. The
1990 max to pd direction is working OK but you will need to make lots of
1991 abstractions for objects like "gate" which don't exist in Pd. conversion
1992 from Pd to Max hasn't been tested for patches with subpatches yet! */
1994 #define MAXSTACK 1000
1996 #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \
1997 !strcmp((a)->a_w.w_symbol->s_name, (b)))
1999 static t_binbuf
*binbuf_convert(t_binbuf
*oldb
, int maxtopd
)
2001 t_binbuf
*newb
= binbuf_new();
2002 t_atom
*vec
= oldb
->b_vec
;
2003 t_int n
= oldb
->b_n
, nextindex
, stackdepth
= 0, stack
[MAXSTACK
],
2005 t_atom outmess
[MAXSTACK
], *nextmess
;
2007 binbuf_addv(newb
, "ss;", gensym("max"), gensym("v2"));
2008 for (nextindex
= 0; nextindex
< n
; )
2011 char *first
, *second
;
2012 for (endmess
= nextindex
; endmess
< n
&& vec
[endmess
].a_type
!= A_SEMI
;
2015 if (endmess
== n
) break;
2016 if (endmess
== nextindex
|| endmess
== nextindex
+ 1
2017 || vec
[nextindex
].a_type
!= A_SYMBOL
||
2018 vec
[nextindex
+1].a_type
!= A_SYMBOL
)
2020 nextindex
= endmess
+ 1;
2023 natom
= endmess
- nextindex
;
2024 if (natom
> MAXSTACK
-10) natom
= MAXSTACK
-10;
2025 nextmess
= vec
+ nextindex
;
2026 first
= nextmess
->a_w
.w_symbol
->s_name
;
2027 second
= (nextmess
+1)->a_w
.w_symbol
->s_name
;
2030 /* case 1: importing a ".pat" file into Pd. */
2032 /* dollar signs in file translate to symbols */
2033 for (i
= 0; i
< natom
; i
++)
2035 if (nextmess
[i
].a_type
== A_DOLLAR
)
2038 sprintf(buf
, "$%d", nextmess
[i
].a_w
.w_index
);
2039 SETSYMBOL(nextmess
+i
, gensym(buf
));
2041 else if (nextmess
[i
].a_type
== A_DOLLSYM
)
2044 sprintf(buf
, "$%s", nextmess
[i
].a_w
.w_symbol
->s_name
);
2045 SETSYMBOL(nextmess
+i
, gensym(buf
));
2048 if (!strcmp(first
, "#N"))
2050 if (!strcmp(second
, "vpatcher"))
2052 if (stackdepth
>= MAXSTACK
)
2054 post("too many embedded patches");
2057 stack
[stackdepth
] = nobj
;
2060 binbuf_addv(newb
, "ssfffff;",
2061 gensym("#N"), gensym("canvas"),
2062 atom_getfloatarg(2, natom
, nextmess
),
2063 atom_getfloatarg(3, natom
, nextmess
),
2064 atom_getfloatarg(4, natom
, nextmess
) -
2065 atom_getfloatarg(2, natom
, nextmess
),
2066 atom_getfloatarg(5, natom
, nextmess
) -
2067 atom_getfloatarg(3, natom
, nextmess
),
2068 (float)sys_defaultfont
);
2071 if (!strcmp(first
, "#P"))
2073 /* drop initial "hidden" flag */
2074 if (!strcmp(second
, "hidden"))
2078 second
= (nextmess
+1)->a_w
.w_symbol
->s_name
;
2080 if (natom
>= 7 && !strcmp(second
, "newobj")
2081 && (ISSYMBOL(&nextmess
[6], "patcher") ||
2082 ISSYMBOL(&nextmess
[6], "p")))
2084 binbuf_addv(newb
, "ssffss;",
2085 gensym("#X"), gensym("restore"),
2086 atom_getfloatarg(2, natom
, nextmess
),
2087 atom_getfloatarg(3, natom
, nextmess
),
2088 gensym("pd"), atom_getsymbolarg(7, natom
, nextmess
));
2089 if (stackdepth
) stackdepth
--;
2090 nobj
= stack
[stackdepth
];
2093 else if (!strcmp(second
, "newex") || !strcmp(second
, "newobj"))
2095 t_symbol
*classname
=
2096 atom_getsymbolarg(6, natom
, nextmess
);
2097 if (classname
== gensym("trigger") ||
2098 classname
== gensym("t"))
2100 for (i
= 7; i
< natom
; i
++)
2101 if (nextmess
[i
].a_type
== A_SYMBOL
&&
2102 nextmess
[i
].a_w
.w_symbol
== gensym("i"))
2103 nextmess
[i
].a_w
.w_symbol
= gensym("f");
2105 if (classname
== gensym("table"))
2106 classname
= gensym("TABLE");
2107 SETSYMBOL(outmess
, gensym("#X"));
2108 SETSYMBOL(outmess
+ 1, gensym("obj"));
2109 outmess
[2] = nextmess
[2];
2110 outmess
[3] = nextmess
[3];
2111 SETSYMBOL(outmess
+4, classname
);
2112 for (i
= 7; i
< natom
; i
++)
2113 outmess
[i
-2] = nextmess
[i
];
2114 SETSEMI(outmess
+ natom
- 2);
2115 binbuf_add(newb
, natom
- 1, outmess
);
2118 else if (!strcmp(second
, "message") ||
2119 !strcmp(second
, "comment"))
2121 SETSYMBOL(outmess
, gensym("#X"));
2122 SETSYMBOL(outmess
+ 1, gensym(
2123 (strcmp(second
, "message") ? "text" : "msg")));
2124 outmess
[2] = nextmess
[2];
2125 outmess
[3] = nextmess
[3];
2126 for (i
= 6; i
< natom
; i
++)
2127 outmess
[i
-2] = nextmess
[i
];
2128 SETSEMI(outmess
+ natom
- 2);
2129 binbuf_add(newb
, natom
- 1, outmess
);
2132 else if (!strcmp(second
, "button"))
2134 binbuf_addv(newb
, "ssffs;",
2135 gensym("#X"), gensym("obj"),
2136 atom_getfloatarg(2, natom
, nextmess
),
2137 atom_getfloatarg(3, natom
, nextmess
),
2141 else if (!strcmp(second
, "number") || !strcmp(second
, "flonum"))
2143 binbuf_addv(newb
, "ssff;",
2144 gensym("#X"), gensym("floatatom"),
2145 atom_getfloatarg(2, natom
, nextmess
),
2146 atom_getfloatarg(3, natom
, nextmess
));
2149 else if (!strcmp(second
, "slider"))
2151 float inc
= atom_getfloatarg(7, natom
, nextmess
);
2154 binbuf_addv(newb
, "ssffsffffffsssfffffffff;",
2155 gensym("#X"), gensym("obj"),
2156 atom_getfloatarg(2, natom
, nextmess
),
2157 atom_getfloatarg(3, natom
, nextmess
),
2159 atom_getfloatarg(4, natom
, nextmess
),
2160 atom_getfloatarg(5, natom
, nextmess
),
2161 atom_getfloatarg(6, natom
, nextmess
),
2162 atom_getfloatarg(6, natom
, nextmess
)
2163 + (atom_getfloatarg(5, natom
, nextmess
) - 1) * inc
,
2165 gensym("empty"), gensym("empty"), gensym("empty"),
2166 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
2169 else if (!strcmp(second
, "toggle"))
2171 binbuf_addv(newb
, "ssffs;",
2172 gensym("#X"), gensym("obj"),
2173 atom_getfloatarg(2, natom
, nextmess
),
2174 atom_getfloatarg(3, natom
, nextmess
),
2178 else if (!strcmp(second
, "inlet"))
2180 binbuf_addv(newb
, "ssffs;",
2181 gensym("#X"), gensym("obj"),
2182 atom_getfloatarg(2, natom
, nextmess
),
2183 atom_getfloatarg(3, natom
, nextmess
),
2184 gensym((natom
> 5 ? "inlet~" : "inlet")));
2187 else if (!strcmp(second
, "outlet"))
2189 binbuf_addv(newb
, "ssffs;",
2190 gensym("#X"), gensym("obj"),
2191 atom_getfloatarg(2, natom
, nextmess
),
2192 atom_getfloatarg(3, natom
, nextmess
),
2193 gensym((natom
> 5 ? "outlet~" : "outlet")));
2196 else if (!strcmp(second
, "user"))
2198 binbuf_addv(newb
, "ssffs;",
2199 gensym("#X"), gensym("obj"),
2200 atom_getfloatarg(3, natom
, nextmess
),
2201 atom_getfloatarg(4, natom
, nextmess
),
2202 atom_getsymbolarg(2, natom
, nextmess
));
2205 else if (!strcmp(second
, "connect")||
2206 !strcmp(second
, "fasten"))
2208 binbuf_addv(newb
, "ssffff;",
2209 gensym("#X"), gensym("connect"),
2210 nobj
- atom_getfloatarg(2, natom
, nextmess
) - 1,
2211 atom_getfloatarg(3, natom
, nextmess
),
2212 nobj
- atom_getfloatarg(4, natom
, nextmess
) - 1,
2213 atom_getfloatarg(5, natom
, nextmess
));
2217 else /* Pd to Max */
2219 if (!strcmp(first
, "#N"))
2221 if (!strcmp(second
, "canvas"))
2223 if (stackdepth
>= MAXSTACK
)
2225 post("too many embedded patches");
2228 stack
[stackdepth
] = nobj
;
2231 binbuf_addv(newb
, "ssffff;",
2232 gensym("#N"), gensym("vpatcher"),
2233 atom_getfloatarg(2, natom
, nextmess
),
2234 atom_getfloatarg(3, natom
, nextmess
),
2235 atom_getfloatarg(4, natom
, nextmess
),
2236 atom_getfloatarg(5, natom
, nextmess
));
2239 if (!strcmp(first
, "#X"))
2241 if (natom
>= 5 && !strcmp(second
, "restore")
2242 && (ISSYMBOL (&nextmess
[4], "pd")))
2244 binbuf_addv(newb
, "ss;", gensym("#P"), gensym("pop"));
2245 binbuf_addv(newb
, "ssffffss;",
2246 gensym("#P"), gensym("newobj"),
2247 atom_getfloatarg(2, natom
, nextmess
),
2248 atom_getfloatarg(3, natom
, nextmess
), 50., 1.,
2250 atom_getsymbolarg(5, natom
, nextmess
));
2251 if (stackdepth
) stackdepth
--;
2252 nobj
= stack
[stackdepth
];
2255 else if (!strcmp(second
, "obj"))
2257 t_symbol
*classname
=
2258 atom_getsymbolarg(4, natom
, nextmess
);
2259 if (classname
== gensym("inlet"))
2260 binbuf_addv(newb
, "ssfff;", gensym("#P"),
2262 atom_getfloatarg(2, natom
, nextmess
),
2263 atom_getfloatarg(3, natom
, nextmess
),
2265 else if (classname
== gensym("inlet~"))
2266 binbuf_addv(newb
, "ssffff;", gensym("#P"),
2268 atom_getfloatarg(2, natom
, nextmess
),
2269 atom_getfloatarg(3, natom
, nextmess
),
2271 else if (classname
== gensym("outlet"))
2272 binbuf_addv(newb
, "ssfff;", gensym("#P"),
2274 atom_getfloatarg(2, natom
, nextmess
),
2275 atom_getfloatarg(3, natom
, nextmess
),
2277 else if (classname
== gensym("outlet~"))
2278 binbuf_addv(newb
, "ssffff;", gensym("#P"),
2280 atom_getfloatarg(2, natom
, nextmess
),
2281 atom_getfloatarg(3, natom
, nextmess
),
2283 else if (classname
== gensym("bng"))
2284 binbuf_addv(newb
, "ssffff;", gensym("#P"),
2286 atom_getfloatarg(2, natom
, nextmess
),
2287 atom_getfloatarg(3, natom
, nextmess
),
2288 atom_getfloatarg(5, natom
, nextmess
), 0.);
2289 else if (classname
== gensym("tgl"))
2290 binbuf_addv(newb
, "ssffff;", gensym("#P"),
2292 atom_getfloatarg(2, natom
, nextmess
),
2293 atom_getfloatarg(3, natom
, nextmess
),
2294 atom_getfloatarg(5, natom
, nextmess
), 0.);
2295 else if (classname
== gensym("vsl"))
2296 binbuf_addv(newb
, "ssffffff;", gensym("#P"),
2298 atom_getfloatarg(2, natom
, nextmess
),
2299 atom_getfloatarg(3, natom
, nextmess
),
2300 atom_getfloatarg(5, natom
, nextmess
),
2301 atom_getfloatarg(6, natom
, nextmess
),
2302 (atom_getfloatarg(8, natom
, nextmess
) -
2303 atom_getfloatarg(7, natom
, nextmess
)) /
2304 (atom_getfloatarg(6, natom
, nextmess
) == 1? 1 :
2305 atom_getfloatarg(6, natom
, nextmess
) - 1),
2306 atom_getfloatarg(7, natom
, nextmess
));
2309 SETSYMBOL(outmess
, gensym("#P"));
2310 SETSYMBOL(outmess
+ 1, gensym("newex"));
2311 outmess
[2] = nextmess
[2];
2312 outmess
[3] = nextmess
[3];
2313 SETFLOAT(outmess
+ 4, 50);
2314 SETFLOAT(outmess
+ 5, 1);
2315 for (i
= 4; i
< natom
; i
++)
2316 outmess
[i
+2] = nextmess
[i
];
2317 SETSEMI(outmess
+ natom
+ 2);
2318 binbuf_add(newb
, natom
+ 3, outmess
);
2323 else if (!strcmp(second
, "msg") ||
2324 !strcmp(second
, "text"))
2326 SETSYMBOL(outmess
, gensym("#P"));
2327 SETSYMBOL(outmess
+ 1, gensym(
2328 (strcmp(second
, "msg") ? "comment" : "message")));
2329 outmess
[2] = nextmess
[2];
2330 outmess
[3] = nextmess
[3];
2331 SETFLOAT(outmess
+ 4, 50);
2332 SETFLOAT(outmess
+ 5, 1);
2333 for (i
= 4; i
< natom
; i
++)
2334 outmess
[i
+2] = nextmess
[i
];
2335 SETSEMI(outmess
+ natom
+ 2);
2336 binbuf_add(newb
, natom
+ 3, outmess
);
2339 else if (!strcmp(second
, "floatatom"))
2341 binbuf_addv(newb
, "ssfff;",
2342 gensym("#P"), gensym("flonum"),
2343 atom_getfloatarg(2, natom
, nextmess
),
2344 atom_getfloatarg(3, natom
, nextmess
), 35);
2347 else if (!strcmp(second
, "connect"))
2349 binbuf_addv(newb
, "ssffff;",
2350 gensym("#P"), gensym("connect"),
2351 nobj
- atom_getfloatarg(2, natom
, nextmess
) - 1,
2352 atom_getfloatarg(3, natom
, nextmess
),
2353 nobj
- atom_getfloatarg(4, natom
, nextmess
) - 1,
2354 atom_getfloatarg(5, natom
, nextmess
));
2358 nextindex
= endmess
+ 1;
2361 binbuf_addv(newb
, "ss;", gensym("#P"), gensym("pop"));
2363 binbuf_write(newb
, "import-result.pd", "/tmp", 0);
2368 /* function to support searching */
2369 int binbuf_match(t_binbuf
*inbuf
, t_binbuf
*searchbuf
)
2371 int indexin
, nmatched
;
2372 for (indexin
= 0; indexin
<= inbuf
->b_n
- searchbuf
->b_n
; indexin
++)
2374 for (nmatched
= 0; nmatched
< searchbuf
->b_n
; nmatched
++)
2376 t_atom
*a1
= &inbuf
->b_vec
[indexin
+ nmatched
],
2377 *a2
= &searchbuf
->b_vec
[nmatched
];
2378 if (a1
->a_type
!= a2
->a_type
||
2379 a1
->a_type
== A_SYMBOL
&& a1
->a_w
.w_symbol
!= a2
->a_w
.w_symbol
2381 a1
->a_type
== A_FLOAT
&& a1
->a_w
.w_float
!= a2
->a_w
.w_float
2383 a1
->a_type
== A_DOLLAR
&& a1
->a_w
.w_index
!= a2
->a_w
.w_index
2385 a1
->a_type
== A_DOLLSYM
&& a1
->a_w
.w_symbol
!= a2
->a_w
.w_symbol
)
2394 void pd_doloadbang(void);
2396 /* LATER make this evaluate the file on-the-fly. */
2397 /* LATER figure out how to log errors */
2398 void binbuf_evalfile(t_symbol
*name
, t_symbol
*dir
)
2400 t_binbuf
*b
= binbuf_new();
2401 int import
= !strcmp(name
->s_name
+ strlen(name
->s_name
) - 4, ".pat");
2402 /* set filename so that new canvases can pick them up */
2403 int dspstate
= canvas_suspend_dsp();
2404 glob_setfilename(0, name
, dir
);
2405 if (binbuf_read(b
, name
->s_name
, dir
->s_name
, 0))
2407 perror(name
->s_name
);
2413 t_binbuf
*newb
= binbuf_convert(b
, 1);
2417 binbuf_eval(b
, 0, 0, 0);
2419 glob_setfilename(0, &s_
, &s_
); /* bug fix by Krzysztof Czaja */
2421 canvas_resume_dsp(dspstate
);
2424 void glob_evalfile(t_pd
*ignore
, t_symbol
*name
, t_symbol
*dir
)
2427 /* even though binbuf_evalfile appears to take care of dspstate,
2428 we have to do it again here, because canvas_startdsp() assumes
2429 that all toplevel canvases are visible. LATER check if this
2430 is still necessary -- probably not. */
2432 int dspstate
= canvas_suspend_dsp();
2433 binbuf_evalfile(name
, dir
);
2434 while ((x
!= s__X
.s_thing
) && (x
= s__X
.s_thing
))
2435 vmess(x
, gensym("pop"), "i", 1);
2437 canvas_resume_dsp(dspstate
);