forked from len0rd/rockbox
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29871 a1c6a512-1295-4272-9138-f99709370657
1333 lines
34 KiB
C
1333 lines
34 KiB
C
/* Copyright (c) 1997-1999 Miller Puckette.
|
|
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
|
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
|
|
|
|
|
|
/* IOhannes :
|
|
* changed the canvas_restore in "g_canvas.c", so that it might accept $args as well (like "pd $0_test")
|
|
* so you can make multiple & distinguishable templates
|
|
* 1511:forum::für::umläute:2001
|
|
* change marked with IOhannes
|
|
*/
|
|
|
|
#ifdef ROCKBOX
|
|
#include "plugin.h"
|
|
#include "../../pdbox.h"
|
|
#ifdef SIMULATOR
|
|
int printf(const char *fmt, ...);
|
|
void perror(const char*);
|
|
#endif
|
|
#else /* ROCKBOX */
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#ifdef UNIX
|
|
#include <unistd.h>
|
|
#endif
|
|
#ifdef MSW
|
|
#include <io.h>
|
|
#endif
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#endif /* ROCKBOX */
|
|
|
|
#include "m_pd.h"
|
|
#include "s_stuff.h"
|
|
|
|
struct _binbuf
|
|
{
|
|
int b_n;
|
|
t_atom *b_vec;
|
|
};
|
|
|
|
t_binbuf *binbuf_new(void)
|
|
{
|
|
t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
|
|
x->b_n = 0;
|
|
x->b_vec = t_getbytes(0);
|
|
return (x);
|
|
}
|
|
|
|
void binbuf_free(t_binbuf *x)
|
|
{
|
|
t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
|
|
t_freebytes(x, sizeof(*x));
|
|
}
|
|
|
|
t_binbuf *binbuf_duplicate(t_binbuf *y)
|
|
{
|
|
t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
|
|
x->b_n = y->b_n;
|
|
x->b_vec = t_getbytes(x->b_n * sizeof(*x->b_vec));
|
|
memcpy(x->b_vec, y->b_vec, x->b_n * sizeof(*x->b_vec));
|
|
return (x);
|
|
}
|
|
|
|
void binbuf_clear(t_binbuf *x)
|
|
{
|
|
x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0);
|
|
x->b_n = 0;
|
|
}
|
|
|
|
/* convert text to a binbuf */
|
|
void binbuf_text(t_binbuf *x, char *text, size_t size)
|
|
{
|
|
char buf[MAXPDSTRING+1], *bufp, *ebuf = buf+MAXPDSTRING;
|
|
const char *textp = text, *etext = text+size;
|
|
t_atom *ap;
|
|
int nalloc = 16, natom = 0;
|
|
t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
|
|
x->b_vec = t_getbytes(nalloc * sizeof(*x->b_vec));
|
|
ap = x->b_vec;
|
|
x->b_n = 0;
|
|
while (1)
|
|
{
|
|
#ifndef ROCKBOX
|
|
int type;
|
|
#endif
|
|
/* skip leading space */
|
|
while ((textp != etext) && (*textp == ' ' || *textp == '\n'
|
|
|| *textp == '\r' || *textp == '\t')) textp++;
|
|
if (textp == etext) break;
|
|
if (*textp == ';') SETSEMI(ap), textp++;
|
|
else if (*textp == ',') SETCOMMA(ap), textp++;
|
|
else
|
|
{
|
|
/* it's an atom other than a comma or semi */
|
|
char c;
|
|
int floatstate = 0, slash = 0, /* lastslash = 0, */
|
|
firstslash = (*textp == '\\');
|
|
bufp = buf;
|
|
do
|
|
{
|
|
c = *bufp = *textp++;
|
|
/* lastslash = slash; */
|
|
slash = (c == '\\');
|
|
|
|
if (floatstate >= 0)
|
|
{
|
|
int digit = (c >= '0' && c <= '9'),
|
|
dot = (c == '.'), minus = (c == '-'),
|
|
plusminus = (minus || (c == '+')),
|
|
expon = (c == 'e' || c == 'E');
|
|
if (floatstate == 0) /* beginning */
|
|
{
|
|
if (minus) floatstate = 1;
|
|
else if (digit) floatstate = 2;
|
|
else if (dot) floatstate = 3;
|
|
else floatstate = -1;
|
|
}
|
|
else if (floatstate == 1) /* got minus */
|
|
{
|
|
if (digit) floatstate = 2;
|
|
else if (dot) floatstate = 3;
|
|
else floatstate = -1;
|
|
}
|
|
else if (floatstate == 2) /* got digits */
|
|
{
|
|
if (dot) floatstate = 4;
|
|
else if (expon) floatstate = 6;
|
|
else if (!digit) floatstate = -1;
|
|
}
|
|
else if (floatstate == 3) /* got '.' without digits */
|
|
{
|
|
if (digit) floatstate = 5;
|
|
else floatstate = -1;
|
|
}
|
|
else if (floatstate == 4) /* got '.' after digits */
|
|
{
|
|
if (digit) floatstate = 5;
|
|
else if (expon) floatstate = 6;
|
|
else floatstate = -1;
|
|
}
|
|
else if (floatstate == 5) /* got digits after . */
|
|
{
|
|
if (expon) floatstate = 6;
|
|
else if (!digit) floatstate = -1;
|
|
}
|
|
else if (floatstate == 6) /* got 'e' */
|
|
{
|
|
if (plusminus) floatstate = 7;
|
|
else if (digit) floatstate = 8;
|
|
else floatstate = -1;
|
|
}
|
|
else if (floatstate == 7) /* got plus or minus */
|
|
{
|
|
if (digit) floatstate = 8;
|
|
else floatstate = -1;
|
|
}
|
|
else if (floatstate == 8) /* got digits */
|
|
{
|
|
if (!digit) floatstate = -1;
|
|
}
|
|
}
|
|
if (!slash) bufp++;
|
|
}
|
|
while (textp != etext && bufp != ebuf &&
|
|
(slash || (*textp != ' ' && *textp != '\n' && *textp != '\r'
|
|
&& *textp != '\t' &&*textp != ',' && *textp != ';')));
|
|
*bufp = 0;
|
|
#if 0
|
|
post("buf %s", buf);
|
|
#endif
|
|
|
|
if (*buf == '$' && buf[1] >= '0' && buf[1] <= '9' && !firstslash)
|
|
{
|
|
for (bufp = buf+2; *bufp; bufp++)
|
|
if (*bufp < '0' || *bufp > '9')
|
|
{
|
|
SETDOLLSYM(ap, gensym(buf+1));
|
|
goto didit;
|
|
}
|
|
SETDOLLAR(ap, atoi(buf+1));
|
|
didit: ;
|
|
}
|
|
else
|
|
{
|
|
if (floatstate == 2 || floatstate == 4 || floatstate == 5 ||
|
|
floatstate == 8)
|
|
SETFLOAT(ap, atof(buf));
|
|
else SETSYMBOL(ap, gensym(buf));
|
|
}
|
|
}
|
|
ap++;
|
|
natom++;
|
|
if (natom == nalloc)
|
|
{
|
|
x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
|
|
nalloc * (2*sizeof(*x->b_vec)));
|
|
nalloc = nalloc * 2;
|
|
ap = x->b_vec + natom;
|
|
}
|
|
if (textp == etext) break;
|
|
}
|
|
/* reallocate the vector to exactly the right size */
|
|
x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
|
|
natom * sizeof(*x->b_vec));
|
|
x->b_n = natom;
|
|
}
|
|
|
|
/* convert a binbuf to text; no null termination. */
|
|
void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp)
|
|
{
|
|
char *buf = getbytes(0), *newbuf;
|
|
int length = 0;
|
|
char string[MAXPDSTRING];
|
|
t_atom *ap;
|
|
int indx;
|
|
|
|
for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
|
|
{
|
|
int newlength;
|
|
if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
|
|
length && buf[length-1] == ' ') length--;
|
|
atom_string(ap, string, MAXPDSTRING);
|
|
newlength = length + strlen(string) + 1;
|
|
if (!(newbuf = resizebytes(buf, length, newlength))) break;
|
|
buf = newbuf;
|
|
strcpy(buf + length, string);
|
|
length = newlength;
|
|
if (ap->a_type == A_SEMI) buf[length-1] = '\n';
|
|
else buf[length-1] = ' ';
|
|
}
|
|
if (length && buf[length-1] == ' ')
|
|
{
|
|
if((newbuf = t_resizebytes(buf, length, length-1)))
|
|
{
|
|
buf = newbuf;
|
|
length--;
|
|
}
|
|
}
|
|
*bufp = buf;
|
|
*lengthp = length;
|
|
}
|
|
|
|
/* LATER improve the out-of-space behavior below. Also fix this so that
|
|
writing to file doesn't buffer everything together. */
|
|
|
|
void binbuf_add(t_binbuf *x, int argc, t_atom *argv)
|
|
{
|
|
int newsize = x->b_n + argc, i;
|
|
t_atom *ap;
|
|
if((ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
|
|
newsize * sizeof(*x->b_vec))))
|
|
x->b_vec = ap;
|
|
else
|
|
{
|
|
error("binbuf_addmessage: out of space");
|
|
return;
|
|
}
|
|
#if 0
|
|
startpost("binbuf_add: ");
|
|
postatom(argc, argv);
|
|
endpost();
|
|
#endif
|
|
for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
|
|
*ap = *(argv++);
|
|
x->b_n = newsize;
|
|
}
|
|
|
|
#define MAXADDMESSV 100
|
|
void binbuf_addv(t_binbuf *x, char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
t_atom arg[MAXADDMESSV], *at =arg;
|
|
int nargs = 0;
|
|
char *fp = fmt;
|
|
|
|
va_start(ap, fmt);
|
|
while (1)
|
|
{
|
|
if (nargs >= MAXADDMESSV)
|
|
{
|
|
error("binbuf_addmessv: only %d allowed", MAXADDMESSV);
|
|
break;
|
|
}
|
|
switch(*fp++)
|
|
{
|
|
case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
|
|
case 'f': SETFLOAT(at, va_arg(ap, double)); break;
|
|
case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
|
|
case ';': SETSEMI(at); break;
|
|
case ',': SETCOMMA(at); break;
|
|
default: goto done;
|
|
}
|
|
at++;
|
|
nargs++;
|
|
}
|
|
done:
|
|
va_end(ap);
|
|
binbuf_add(x, nargs, arg);
|
|
}
|
|
|
|
/* add a binbuf to another one for saving. Semicolons and commas go to
|
|
symbols ";", "'",; the symbol ";" goes to "\;", etc. */
|
|
|
|
void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y)
|
|
{
|
|
t_binbuf *z = binbuf_new();
|
|
int i;
|
|
t_atom *ap;
|
|
binbuf_add(z, y->b_n, y->b_vec);
|
|
for (i = 0, ap = z->b_vec; i < z->b_n; i++, ap++)
|
|
{
|
|
char tbuf[MAXPDSTRING];
|
|
switch (ap->a_type)
|
|
{
|
|
case A_FLOAT:
|
|
break;
|
|
case A_SEMI:
|
|
SETSYMBOL(ap, gensym(";"));
|
|
break;
|
|
case A_COMMA:
|
|
SETSYMBOL(ap, gensym(","));
|
|
break;
|
|
case A_DOLLAR:
|
|
#ifdef ROCKBOX
|
|
snprintf(tbuf, sizeof(tbuf), "$%d", ap->a_w.w_index);
|
|
#else /* ROCKBOX */
|
|
sprintf(tbuf, "$%d", ap->a_w.w_index);
|
|
#endif /* ROCKBOX */
|
|
SETSYMBOL(ap, gensym(tbuf));
|
|
break;
|
|
case A_DOLLSYM:
|
|
#ifdef ROCKBOX
|
|
snprintf(tbuf, sizeof(tbuf), "$%s", ap->a_w.w_symbol->s_name);
|
|
#else /* ROCKBOX */
|
|
sprintf(tbuf, "$%s", ap->a_w.w_symbol->s_name);
|
|
#endif /* ROCKBOX */
|
|
SETSYMBOL(ap, gensym(tbuf));
|
|
break;
|
|
case A_SYMBOL:
|
|
/* FIXME make this general */
|
|
if (!strcmp(ap->a_w.w_symbol->s_name, ";"))
|
|
SETSYMBOL(ap, gensym(";"));
|
|
else if (!strcmp(ap->a_w.w_symbol->s_name, ","))
|
|
SETSYMBOL(ap, gensym(","));
|
|
break;
|
|
default:
|
|
bug("binbuf_addbinbuf");
|
|
}
|
|
}
|
|
|
|
binbuf_add(x, z->b_n, z->b_vec);
|
|
}
|
|
|
|
void binbuf_addsemi(t_binbuf *x)
|
|
{
|
|
t_atom a;
|
|
SETSEMI(&a);
|
|
binbuf_add(x, 1, &a);
|
|
}
|
|
|
|
/* Supply atoms to a binbuf from a message, making the opposite changes
|
|
from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
|
|
|
|
void binbuf_restore(t_binbuf *x, int argc, t_atom *argv)
|
|
{
|
|
int newsize = x->b_n + argc, i;
|
|
t_atom *ap;
|
|
if((ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
|
|
newsize * sizeof(*x->b_vec))))
|
|
x->b_vec = ap;
|
|
else
|
|
{
|
|
error("binbuf_addmessage: out of space");
|
|
return;
|
|
}
|
|
|
|
for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
|
|
{
|
|
if (argv->a_type == A_SYMBOL)
|
|
{
|
|
char *str = argv->a_w.w_symbol->s_name;
|
|
if (!strcmp(str, ";")) SETSEMI(ap);
|
|
else if (!strcmp(str, ",")) SETCOMMA(ap);
|
|
else if (str[0] == '$' && str[1] >= '0' && str[1] <= '9')
|
|
{
|
|
int dollsym = 0;
|
|
char *str2;
|
|
for (str2 = str + 2; *str2; str2++)
|
|
if (*str2 < '0' || *str2 > '9')
|
|
dollsym = 1;
|
|
if (dollsym)
|
|
SETDOLLSYM(ap, gensym(str + 1));
|
|
else
|
|
{
|
|
int dollar = 0;
|
|
#ifdef ROCKBOX
|
|
dollar = atoi(argv->a_w.w_symbol->s_name + 1);
|
|
#else
|
|
sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar);
|
|
#endif
|
|
SETDOLLAR(ap, dollar);
|
|
}
|
|
}
|
|
else *ap = *argv;
|
|
argv++;
|
|
}
|
|
else *ap = *(argv++);
|
|
}
|
|
x->b_n = newsize;
|
|
}
|
|
|
|
|
|
#define MSTACKSIZE 2048
|
|
|
|
void binbuf_print(t_binbuf *x)
|
|
{
|
|
int i, startedpost = 0, newline = 1;
|
|
for (i = 0; i < x->b_n; i++)
|
|
{
|
|
if (newline)
|
|
{
|
|
if (startedpost) endpost();
|
|
startpost("");
|
|
startedpost = 1;
|
|
}
|
|
postatom(1, x->b_vec + i);
|
|
if (x->b_vec[i].a_type == A_SEMI)
|
|
newline = 1;
|
|
else newline = 0;
|
|
}
|
|
if (startedpost) endpost();
|
|
}
|
|
|
|
int binbuf_getnatom(t_binbuf *x)
|
|
{
|
|
return (x->b_n);
|
|
}
|
|
|
|
t_atom *binbuf_getvec(t_binbuf *x)
|
|
{
|
|
return (x->b_vec);
|
|
}
|
|
|
|
int canvas_getdollarzero( void);
|
|
|
|
t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
|
|
{
|
|
int argno = atol(s->s_name), lastnum;
|
|
char buf[MAXPDSTRING], c, *sp;
|
|
for (lastnum = 0, sp = s->s_name; ((c = *sp) && c >= '0' && c <= '9');
|
|
sp++, lastnum++)
|
|
if (!c || argno < 0 || argno > ac)
|
|
{
|
|
if (!tonew)
|
|
return (0);
|
|
#ifdef ROCKBOX
|
|
else snprintf(buf, sizeof(buf), "$%d", argno);
|
|
#else /* ROCKBOX */
|
|
else sprintf(buf, "$%d", argno);
|
|
#endif /* ROCKBOX */
|
|
}
|
|
else if (argno == 0)
|
|
#ifdef ROCKBOX
|
|
snprintf(buf, sizeof(buf), "%d", canvas_getdollarzero());
|
|
#else /* ROCKBOX */
|
|
sprintf(buf, "%d", canvas_getdollarzero());
|
|
#endif /* ROCKBOX */
|
|
else
|
|
atom_string(av+(argno-1), buf, MAXPDSTRING/2-1);
|
|
strncat(buf, sp, MAXPDSTRING/2-1);
|
|
return (gensym(buf));
|
|
}
|
|
|
|
void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
|
|
{
|
|
static t_atom mstack[MSTACKSIZE], *msp = mstack, *ems = mstack+MSTACKSIZE;
|
|
t_atom *stackwas = msp;
|
|
t_atom *at = x->b_vec;
|
|
int ac = x->b_n;
|
|
int nargs;
|
|
while (1)
|
|
{
|
|
t_pd *nexttarget;
|
|
/* get a target. */
|
|
while (!target)
|
|
{
|
|
t_symbol *s;
|
|
while (ac && (at->a_type == A_SEMI || at->a_type == A_COMMA))
|
|
ac--, at++;
|
|
if (!ac) break;
|
|
if (at->a_type == A_DOLLAR)
|
|
{
|
|
if (at->a_w.w_index <= 0 || at->a_w.w_index > argc)
|
|
{
|
|
error("$%d: not enough arguments supplied",
|
|
at->a_w.w_index);
|
|
goto cleanup;
|
|
}
|
|
else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL)
|
|
{
|
|
error("$%d: symbol needed as message destination",
|
|
at->a_w.w_index);
|
|
goto cleanup;
|
|
}
|
|
else s = argv[at->a_w.w_index-1].a_w.w_symbol;
|
|
}
|
|
else if (at->a_type == A_DOLLSYM)
|
|
{
|
|
if (!(s = binbuf_realizedollsym(at->a_w.w_symbol,
|
|
argc, argv, 0)))
|
|
{
|
|
error("$%s: not enough arguments supplied",
|
|
at->a_w.w_symbol->s_name);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else s = atom_getsymbol(at);
|
|
if (!(target = s->s_thing))
|
|
{
|
|
error("%s: no such object", s->s_name);
|
|
cleanup:
|
|
do at++, ac--;
|
|
while (ac && at->a_type != A_SEMI);
|
|
/* LATER eat args until semicolon and continue */
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
at++, ac--;
|
|
break;
|
|
}
|
|
}
|
|
if (!ac) break;
|
|
nargs = 0;
|
|
nexttarget = target;
|
|
while (1)
|
|
{
|
|
t_symbol *s9;
|
|
if (!ac) goto gotmess;
|
|
if (msp >= ems)
|
|
{
|
|
error("message stack overflow");
|
|
goto broken;
|
|
}
|
|
switch (at->a_type)
|
|
{
|
|
case A_SEMI:
|
|
/* semis and commas in new message just get bashed to
|
|
a symbol. This is needed so you can pass them to "expr." */
|
|
if (target == &pd_objectmaker)
|
|
{
|
|
SETSYMBOL(msp, gensym(";"));
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
nexttarget = 0;
|
|
goto gotmess;
|
|
}
|
|
case A_COMMA:
|
|
if (target == &pd_objectmaker)
|
|
{
|
|
SETSYMBOL(msp, gensym(","));
|
|
break;
|
|
}
|
|
else goto gotmess;
|
|
case A_FLOAT:
|
|
case A_SYMBOL:
|
|
*msp = *at;
|
|
break;
|
|
case A_DOLLAR:
|
|
if (at->a_w.w_index > 0 && at->a_w.w_index <= argc)
|
|
*msp = argv[at->a_w.w_index-1];
|
|
else if (at->a_w.w_index == 0)
|
|
SETFLOAT(msp, canvas_getdollarzero());
|
|
else
|
|
{
|
|
if (target == &pd_objectmaker)
|
|
SETFLOAT(msp, 0);
|
|
else
|
|
{
|
|
error("$%d: argument number out of range",
|
|
at->a_w.w_index);
|
|
SETFLOAT(msp, 0);
|
|
}
|
|
}
|
|
break;
|
|
case A_DOLLSYM:
|
|
s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv,
|
|
target == &pd_objectmaker);
|
|
if (!s9)
|
|
goto broken;
|
|
SETSYMBOL(msp, s9);
|
|
break;
|
|
default:
|
|
bug("bad item in binbuf");
|
|
goto broken;
|
|
}
|
|
msp++;
|
|
ac--;
|
|
at++;
|
|
nargs++;
|
|
}
|
|
gotmess:
|
|
if (nargs)
|
|
{
|
|
switch (stackwas->a_type)
|
|
{
|
|
case A_SYMBOL:
|
|
typedmess(target, stackwas->a_w.w_symbol, nargs-1, stackwas+1);
|
|
break;
|
|
case A_FLOAT:
|
|
if (nargs == 1) pd_float(target, stackwas->a_w.w_float);
|
|
else pd_list(target, 0, nargs, stackwas);
|
|
break;
|
|
#ifdef ROCKBOX
|
|
default:
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
msp = stackwas;
|
|
if (!ac) break;
|
|
target = nexttarget;
|
|
at++;
|
|
ac--;
|
|
}
|
|
|
|
return;
|
|
broken:
|
|
msp = stackwas;
|
|
}
|
|
|
|
static int binbuf_doopen(char *s, int mode)
|
|
{
|
|
char namebuf[MAXPDSTRING];
|
|
#ifdef MSW
|
|
mode |= O_BINARY;
|
|
#endif
|
|
sys_bashfilename(s, namebuf);
|
|
return (open(namebuf, mode, 0666));
|
|
}
|
|
|
|
#ifndef ROCKBOX
|
|
static FILE *binbuf_dofopen(char *s, char *mode)
|
|
{
|
|
char namebuf[MAXPDSTRING];
|
|
sys_bashfilename(s, namebuf);
|
|
return (fopen(namebuf, mode));
|
|
}
|
|
#endif
|
|
|
|
int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag)
|
|
{
|
|
long length;
|
|
int fd;
|
|
int readret;
|
|
char *buf;
|
|
char namebuf[MAXPDSTRING];
|
|
|
|
namebuf[0] = 0;
|
|
if (*dirname)
|
|
strcat(namebuf, dirname), strcat(namebuf, "/");
|
|
strcat(namebuf, filename);
|
|
|
|
if ((fd = binbuf_doopen(namebuf, 0)) < 0)
|
|
{
|
|
#ifdef ROCKBOX
|
|
#ifdef SIMULATOR
|
|
printf("open: ");
|
|
perror(namebuf);
|
|
#endif /* SIMULATOR */
|
|
#else /* ROCKBOX */
|
|
fprintf(stderr, "open: ");
|
|
perror(namebuf);
|
|
#endif /* ROCKBOX */
|
|
return (1);
|
|
}
|
|
if ((length = lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0
|
|
|| !(buf = t_getbytes(length)))
|
|
{
|
|
#ifdef ROCKBOX
|
|
#ifdef SIMULATOR
|
|
printf("lseek: ");
|
|
perror(namebuf);
|
|
#endif /* SIMULATOR */
|
|
#else /* ROCKBOX */
|
|
fprintf(stderr, "lseek: ");
|
|
perror(namebuf);
|
|
#endif /* ROCKBOX */
|
|
close(fd);
|
|
return(1);
|
|
}
|
|
if ((readret = read(fd, buf, length)) < length)
|
|
{
|
|
#ifdef ROCKBOX
|
|
#ifdef SIMULATOR
|
|
printf("read (%d %ld) -> %d\n", fd, length, readret);
|
|
perror(namebuf);
|
|
#endif /* SIMULATOR */
|
|
#else /* ROCKBOX */
|
|
fprintf(stderr, "read (%d %ld) -> %d\n", fd, length, readret);
|
|
perror(namebuf);
|
|
#endif /* ROCKBOX */
|
|
close(fd);
|
|
t_freebytes(buf, length);
|
|
return(1);
|
|
}
|
|
/* optionally map carriage return to semicolon */
|
|
if (crflag)
|
|
{
|
|
int i;
|
|
for (i = 0; i < length; i++)
|
|
if (buf[i] == '\n')
|
|
buf[i] = ';';
|
|
}
|
|
binbuf_text(b, buf, length);
|
|
|
|
#if 0
|
|
startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost();
|
|
#endif
|
|
|
|
t_freebytes(buf, length);
|
|
close(fd);
|
|
return (0);
|
|
}
|
|
|
|
int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
|
|
int crflag)
|
|
{
|
|
int filedesc;
|
|
char buf[MAXPDSTRING], *bufptr;
|
|
if ((filedesc = open_via_path(
|
|
dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0)
|
|
{
|
|
error("%s: can't open", filename);
|
|
return (1);
|
|
}
|
|
else close (filedesc);
|
|
if (binbuf_read(b, bufptr, buf, crflag))
|
|
return (1);
|
|
else return (0);
|
|
}
|
|
|
|
#define WBUFSIZE 4096
|
|
static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd);
|
|
|
|
/* write a binbuf to a text file. If "crflag" is set we suppress
|
|
semicolons. */
|
|
int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
|
|
{
|
|
#ifdef ROCKBOX
|
|
int f = 0;
|
|
ssize_t bp_size;
|
|
#else /* ROCKBOX */
|
|
FILE *f = 0;
|
|
#endif /* ROCKBOX */
|
|
char sbuf[WBUFSIZE], fbuf[MAXPDSTRING], *bp = sbuf, *ep = sbuf + WBUFSIZE;
|
|
t_atom *ap;
|
|
int indx, deleteit = 0;
|
|
int ncolumn = 0;
|
|
|
|
fbuf[0] = 0;
|
|
if (*dir)
|
|
strcat(fbuf, dir), strcat(fbuf, "/");
|
|
strcat(fbuf, filename);
|
|
if (!strcmp(filename + strlen(filename) - 4, ".pat"))
|
|
{
|
|
x = binbuf_convert(x, 0);
|
|
deleteit = 1;
|
|
}
|
|
|
|
#ifdef ROCKBOX
|
|
if(!(f = binbuf_doopen(fbuf, O_WRONLY|O_CREAT|O_TRUNC)))
|
|
#else /* ROCKBOX */
|
|
if (!(f = binbuf_dofopen(fbuf, "w")))
|
|
#endif /* ROCKBOX */
|
|
{
|
|
#ifdef ROCKBOX
|
|
#ifdef SIMULATOR
|
|
printf("open: ");
|
|
#endif /* SIMULATOR */
|
|
#else /* ROCKBOX */
|
|
fprintf(stderr, "open: ");
|
|
#endif /* ROCKBOX */
|
|
sys_unixerror(fbuf);
|
|
goto fail;
|
|
}
|
|
for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
|
|
{
|
|
int length;
|
|
/* estimate how many characters will be needed. Printing out
|
|
symbols may need extra characters for inserting backslashes. */
|
|
if (ap->a_type == A_SYMBOL || ap->a_type == A_DOLLSYM)
|
|
length = 80 + strlen(ap->a_w.w_symbol->s_name);
|
|
else length = 40;
|
|
if (ep - bp < length)
|
|
{
|
|
#ifdef ROCKBOX
|
|
bp_size = bp - sbuf;
|
|
if(write(f, sbuf, bp_size) < bp_size)
|
|
#else /* ROCKBOX */
|
|
if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
|
|
#endif /* ROCKBOX */
|
|
{
|
|
sys_unixerror(fbuf);
|
|
goto fail;
|
|
}
|
|
bp = sbuf;
|
|
}
|
|
if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
|
|
bp > sbuf && bp[-1] == ' ') bp--;
|
|
if (!crflag || ap->a_type != A_SEMI)
|
|
{
|
|
atom_string(ap, bp, (ep-bp)-2);
|
|
length = strlen(bp);
|
|
bp += length;
|
|
ncolumn += length;
|
|
}
|
|
if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65))
|
|
{
|
|
*bp++ = '\n';
|
|
ncolumn = 0;
|
|
}
|
|
else
|
|
{
|
|
*bp++ = ' ';
|
|
ncolumn++;
|
|
}
|
|
}
|
|
#ifdef ROCKBOX
|
|
bp_size = bp - sbuf;
|
|
if(write(f, sbuf, bp_size) < bp_size)
|
|
#else /* ROCKBOX */
|
|
if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
|
|
#endif /* ROCKBOX */
|
|
{
|
|
sys_unixerror(fbuf);
|
|
goto fail;
|
|
}
|
|
if (deleteit)
|
|
binbuf_free(x);
|
|
#ifdef ROCKBOX
|
|
close(f);
|
|
#else /* ROCKBOX */
|
|
fclose(f);
|
|
#endif /* ROCKBOX */
|
|
return (0);
|
|
fail:
|
|
if (deleteit)
|
|
binbuf_free(x);
|
|
if (f)
|
|
#ifdef ROCKBOX
|
|
close(f);
|
|
#else /* ROCKBOX */
|
|
fclose(f);
|
|
#endif /* ROCKBOX */
|
|
return (1);
|
|
}
|
|
|
|
/* The following routine attempts to convert from max to pd or back. The
|
|
max to pd direction is working OK but you will need to make lots of
|
|
abstractions for objects like "gate" which don't exist in Pd. conversion
|
|
from Pd to Max hasn't been tested for patches with subpatches yet! */
|
|
|
|
#define MAXSTACK 1000
|
|
|
|
#define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \
|
|
!strcmp((a)->a_w.w_symbol->s_name, (b)))
|
|
|
|
static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
|
|
{
|
|
t_binbuf *newb = binbuf_new();
|
|
t_atom *vec = oldb->b_vec;
|
|
t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK],
|
|
nobj = 0, i;
|
|
t_atom outmess[MAXSTACK], *nextmess;
|
|
if (!maxtopd)
|
|
binbuf_addv(newb, "ss;", gensym("max"), gensym("v2"));
|
|
for (nextindex = 0; nextindex < n; )
|
|
{
|
|
int endmess, natom;
|
|
char *first, *second;
|
|
for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI;
|
|
endmess++)
|
|
;
|
|
if (endmess == n) break;
|
|
if (endmess == nextindex || endmess == nextindex + 1
|
|
|| vec[nextindex].a_type != A_SYMBOL ||
|
|
vec[nextindex+1].a_type != A_SYMBOL)
|
|
{
|
|
nextindex = endmess + 1;
|
|
continue;
|
|
}
|
|
natom = endmess - nextindex;
|
|
if (natom > MAXSTACK-10) natom = MAXSTACK-10;
|
|
nextmess = vec + nextindex;
|
|
first = nextmess->a_w.w_symbol->s_name;
|
|
second = (nextmess+1)->a_w.w_symbol->s_name;
|
|
if (maxtopd)
|
|
{
|
|
/* case 1: importing a ".pat" file into Pd. */
|
|
|
|
/* dollar signs in file translate to symbols */
|
|
for (i = 0; i < natom; i++)
|
|
{
|
|
if (nextmess[i].a_type == A_DOLLAR)
|
|
{
|
|
char buf[100];
|
|
#ifdef ROCKBOX
|
|
snprintf(buf, sizeof(buf), "$%d", nextmess[i].a_w.w_index);
|
|
#else /* ROCKBOX */
|
|
sprintf(buf, "$%d", nextmess[i].a_w.w_index);
|
|
#endif /* ROCKBOX */
|
|
SETSYMBOL(nextmess+i, gensym(buf));
|
|
}
|
|
else if (nextmess[i].a_type == A_DOLLSYM)
|
|
{
|
|
char buf[100];
|
|
#ifdef ROCKBOX
|
|
snprintf(buf, sizeof(buf), "$%s", nextmess[i].a_w.w_symbol->s_name);
|
|
#else /* ROCKBOX */
|
|
sprintf(buf, "$%s", nextmess[i].a_w.w_symbol->s_name);
|
|
#endif /* ROCKBOX */
|
|
SETSYMBOL(nextmess+i, gensym(buf));
|
|
}
|
|
}
|
|
if (!strcmp(first, "#N"))
|
|
{
|
|
if (!strcmp(second, "vpatcher"))
|
|
{
|
|
if (stackdepth >= MAXSTACK)
|
|
{
|
|
post("too many embedded patches");
|
|
return (newb);
|
|
}
|
|
stack[stackdepth] = nobj;
|
|
stackdepth++;
|
|
nobj = 0;
|
|
binbuf_addv(newb, "ssfffff;",
|
|
gensym("#N"), gensym("canvas"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
atom_getfloatarg(4, natom, nextmess) -
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(5, natom, nextmess) -
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
#ifdef ROCKBOX
|
|
10.0);
|
|
#else
|
|
(float)sys_defaultfont);
|
|
#endif
|
|
}
|
|
}
|
|
if (!strcmp(first, "#P"))
|
|
{
|
|
/* drop initial "hidden" flag */
|
|
if (!strcmp(second, "hidden"))
|
|
{
|
|
nextmess++;
|
|
natom--;
|
|
second = (nextmess+1)->a_w.w_symbol->s_name;
|
|
}
|
|
if (natom >= 7 && !strcmp(second, "newobj")
|
|
&& (ISSYMBOL(&nextmess[6], "patcher") ||
|
|
ISSYMBOL(&nextmess[6], "p")))
|
|
{
|
|
binbuf_addv(newb, "ssffss;",
|
|
gensym("#X"), gensym("restore"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
gensym("pd"), atom_getsymbolarg(7, natom, nextmess));
|
|
if (stackdepth) stackdepth--;
|
|
nobj = stack[stackdepth];
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "newex") || !strcmp(second, "newobj"))
|
|
{
|
|
t_symbol *classname =
|
|
atom_getsymbolarg(6, natom, nextmess);
|
|
if (classname == gensym("trigger") ||
|
|
classname == gensym("t"))
|
|
{
|
|
for (i = 7; i < natom; i++)
|
|
if (nextmess[i].a_type == A_SYMBOL &&
|
|
nextmess[i].a_w.w_symbol == gensym("i"))
|
|
nextmess[i].a_w.w_symbol = gensym("f");
|
|
}
|
|
if (classname == gensym("table"))
|
|
classname = gensym("TABLE");
|
|
SETSYMBOL(outmess, gensym("#X"));
|
|
SETSYMBOL(outmess + 1, gensym("obj"));
|
|
outmess[2] = nextmess[2];
|
|
outmess[3] = nextmess[3];
|
|
SETSYMBOL(outmess+4, classname);
|
|
for (i = 7; i < natom; i++)
|
|
outmess[i-2] = nextmess[i];
|
|
SETSEMI(outmess + natom - 2);
|
|
binbuf_add(newb, natom - 1, outmess);
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "message") ||
|
|
!strcmp(second, "comment"))
|
|
{
|
|
SETSYMBOL(outmess, gensym("#X"));
|
|
SETSYMBOL(outmess + 1, gensym(
|
|
(strcmp(second, "message") ? "text" : "msg")));
|
|
outmess[2] = nextmess[2];
|
|
outmess[3] = nextmess[3];
|
|
for (i = 6; i < natom; i++)
|
|
outmess[i-2] = nextmess[i];
|
|
SETSEMI(outmess + natom - 2);
|
|
binbuf_add(newb, natom - 1, outmess);
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "button"))
|
|
{
|
|
binbuf_addv(newb, "ssffs;",
|
|
gensym("#X"), gensym("obj"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
gensym("bng"));
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "number") || !strcmp(second, "flonum"))
|
|
{
|
|
binbuf_addv(newb, "ssff;",
|
|
gensym("#X"), gensym("floatatom"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess));
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "slider"))
|
|
{
|
|
float inc = atom_getfloatarg(7, natom, nextmess);
|
|
if (inc <= 0)
|
|
inc = 1;
|
|
binbuf_addv(newb, "ssffsffffffsssfffffffff;",
|
|
gensym("#X"), gensym("obj"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
gensym("vsl"),
|
|
atom_getfloatarg(4, natom, nextmess),
|
|
atom_getfloatarg(5, natom, nextmess),
|
|
atom_getfloatarg(6, natom, nextmess),
|
|
atom_getfloatarg(6, natom, nextmess)
|
|
+ (atom_getfloatarg(5, natom, nextmess) - 1) * inc,
|
|
0., 0.,
|
|
gensym("empty"), gensym("empty"), gensym("empty"),
|
|
0., -8., 0., 8., -262144., -1., -1., 0., 1.);
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "toggle"))
|
|
{
|
|
binbuf_addv(newb, "ssffs;",
|
|
gensym("#X"), gensym("obj"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
gensym("tgl"));
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "inlet"))
|
|
{
|
|
binbuf_addv(newb, "ssffs;",
|
|
gensym("#X"), gensym("obj"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
gensym((natom > 5 ? "inlet~" : "inlet")));
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "outlet"))
|
|
{
|
|
binbuf_addv(newb, "ssffs;",
|
|
gensym("#X"), gensym("obj"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
gensym((natom > 5 ? "outlet~" : "outlet")));
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "user"))
|
|
{
|
|
binbuf_addv(newb, "ssffs;",
|
|
gensym("#X"), gensym("obj"),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
atom_getfloatarg(4, natom, nextmess),
|
|
atom_getsymbolarg(2, natom, nextmess));
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "connect")||
|
|
!strcmp(second, "fasten"))
|
|
{
|
|
binbuf_addv(newb, "ssffff;",
|
|
gensym("#X"), gensym("connect"),
|
|
nobj - atom_getfloatarg(2, natom, nextmess) - 1,
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
nobj - atom_getfloatarg(4, natom, nextmess) - 1,
|
|
atom_getfloatarg(5, natom, nextmess));
|
|
}
|
|
}
|
|
}
|
|
else /* Pd to Max */
|
|
{
|
|
if (!strcmp(first, "#N"))
|
|
{
|
|
if (!strcmp(second, "canvas"))
|
|
{
|
|
if (stackdepth >= MAXSTACK)
|
|
{
|
|
post("too many embedded patches");
|
|
return (newb);
|
|
}
|
|
stack[stackdepth] = nobj;
|
|
stackdepth++;
|
|
nobj = 0;
|
|
binbuf_addv(newb, "ssffff;",
|
|
gensym("#N"), gensym("vpatcher"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
atom_getfloatarg(4, natom, nextmess),
|
|
atom_getfloatarg(5, natom, nextmess));
|
|
}
|
|
}
|
|
if (!strcmp(first, "#X"))
|
|
{
|
|
if (natom >= 5 && !strcmp(second, "restore")
|
|
&& (ISSYMBOL (&nextmess[4], "pd")))
|
|
{
|
|
binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
|
|
binbuf_addv(newb, "ssffffss;",
|
|
gensym("#P"), gensym("newobj"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess), 50., 1.,
|
|
gensym("patcher"),
|
|
atom_getsymbolarg(5, natom, nextmess));
|
|
if (stackdepth) stackdepth--;
|
|
nobj = stack[stackdepth];
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "obj"))
|
|
{
|
|
t_symbol *classname =
|
|
atom_getsymbolarg(4, natom, nextmess);
|
|
if (classname == gensym("inlet"))
|
|
binbuf_addv(newb, "ssfff;", gensym("#P"),
|
|
gensym("inlet"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
15.);
|
|
else if (classname == gensym("inlet~"))
|
|
binbuf_addv(newb, "ssffff;", gensym("#P"),
|
|
gensym("inlet"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
15., 1.);
|
|
else if (classname == gensym("outlet"))
|
|
binbuf_addv(newb, "ssfff;", gensym("#P"),
|
|
gensym("outlet"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
15.);
|
|
else if (classname == gensym("outlet~"))
|
|
binbuf_addv(newb, "ssffff;", gensym("#P"),
|
|
gensym("outlet"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
15., 1.);
|
|
else if (classname == gensym("bng"))
|
|
binbuf_addv(newb, "ssffff;", gensym("#P"),
|
|
gensym("button"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
atom_getfloatarg(5, natom, nextmess), 0.);
|
|
else if (classname == gensym("tgl"))
|
|
binbuf_addv(newb, "ssffff;", gensym("#P"),
|
|
gensym("toggle"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
atom_getfloatarg(5, natom, nextmess), 0.);
|
|
else if (classname == gensym("vsl"))
|
|
binbuf_addv(newb, "ssffffff;", gensym("#P"),
|
|
gensym("slider"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
atom_getfloatarg(5, natom, nextmess),
|
|
atom_getfloatarg(6, natom, nextmess),
|
|
(atom_getfloatarg(8, natom, nextmess) -
|
|
atom_getfloatarg(7, natom, nextmess)) /
|
|
(atom_getfloatarg(6, natom, nextmess) == 1? 1 :
|
|
atom_getfloatarg(6, natom, nextmess) - 1),
|
|
atom_getfloatarg(7, natom, nextmess));
|
|
else
|
|
{
|
|
SETSYMBOL(outmess, gensym("#P"));
|
|
SETSYMBOL(outmess + 1, gensym("newex"));
|
|
outmess[2] = nextmess[2];
|
|
outmess[3] = nextmess[3];
|
|
SETFLOAT(outmess + 4, 50);
|
|
SETFLOAT(outmess + 5, 1);
|
|
for (i = 4; i < natom; i++)
|
|
outmess[i+2] = nextmess[i];
|
|
SETSEMI(outmess + natom + 2);
|
|
binbuf_add(newb, natom + 3, outmess);
|
|
}
|
|
nobj++;
|
|
|
|
}
|
|
else if (!strcmp(second, "msg") ||
|
|
!strcmp(second, "text"))
|
|
{
|
|
SETSYMBOL(outmess, gensym("#P"));
|
|
SETSYMBOL(outmess + 1, gensym(
|
|
(strcmp(second, "msg") ? "comment" : "message")));
|
|
outmess[2] = nextmess[2];
|
|
outmess[3] = nextmess[3];
|
|
SETFLOAT(outmess + 4, 50);
|
|
SETFLOAT(outmess + 5, 1);
|
|
for (i = 4; i < natom; i++)
|
|
outmess[i+2] = nextmess[i];
|
|
SETSEMI(outmess + natom + 2);
|
|
binbuf_add(newb, natom + 3, outmess);
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "floatatom"))
|
|
{
|
|
binbuf_addv(newb, "ssfff;",
|
|
gensym("#P"), gensym("flonum"),
|
|
atom_getfloatarg(2, natom, nextmess),
|
|
atom_getfloatarg(3, natom, nextmess), 35);
|
|
nobj++;
|
|
}
|
|
else if (!strcmp(second, "connect"))
|
|
{
|
|
binbuf_addv(newb, "ssffff;",
|
|
gensym("#P"), gensym("connect"),
|
|
nobj - atom_getfloatarg(2, natom, nextmess) - 1,
|
|
atom_getfloatarg(3, natom, nextmess),
|
|
nobj - atom_getfloatarg(4, natom, nextmess) - 1,
|
|
atom_getfloatarg(5, natom, nextmess));
|
|
}
|
|
}
|
|
}
|
|
nextindex = endmess + 1;
|
|
}
|
|
if (!maxtopd)
|
|
binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
|
|
#if 0
|
|
binbuf_write(newb, "import-result.pd", "/tmp", 0);
|
|
#endif
|
|
return (newb);
|
|
}
|
|
|
|
/* function to support searching */
|
|
int binbuf_match(t_binbuf *inbuf, t_binbuf *searchbuf)
|
|
{
|
|
int indexin, nmatched;
|
|
for (indexin = 0; indexin <= inbuf->b_n - searchbuf->b_n; indexin++)
|
|
{
|
|
for (nmatched = 0; nmatched < searchbuf->b_n; nmatched++)
|
|
{
|
|
t_atom *a1 = &inbuf->b_vec[indexin + nmatched],
|
|
*a2 = &searchbuf->b_vec[nmatched];
|
|
if (a1->a_type != a2->a_type ||
|
|
(a1->a_type == A_SYMBOL && a1->a_w.w_symbol != a2->a_w.w_symbol)
|
|
||
|
|
(a1->a_type == A_FLOAT && a1->a_w.w_float != a2->a_w.w_float)
|
|
||
|
|
(a1->a_type == A_DOLLAR && a1->a_w.w_index != a2->a_w.w_index)
|
|
||
|
|
(a1->a_type == A_DOLLSYM && a1->a_w.w_symbol != a2->a_w.w_symbol))
|
|
goto nomatch;
|
|
}
|
|
return (1);
|
|
nomatch: ;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
void pd_doloadbang(void);
|
|
|
|
/* LATER make this evaluate the file on-the-fly. */
|
|
/* LATER figure out how to log errors */
|
|
void binbuf_evalfile(t_symbol *name, t_symbol *dir)
|
|
{
|
|
t_binbuf *b = binbuf_new();
|
|
int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat");
|
|
/* set filename so that new canvases can pick them up */
|
|
int dspstate = canvas_suspend_dsp();
|
|
glob_setfilename(0, name, dir);
|
|
|
|
if (binbuf_read(b, name->s_name, dir->s_name, 0))
|
|
{
|
|
#if !defined(ROCKBOX) || (defined(ROCKBOX) && defined(SIMULATOR))
|
|
perror(name->s_name);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if (import)
|
|
{
|
|
t_binbuf *newb = binbuf_convert(b, 1);
|
|
binbuf_free(b);
|
|
b = newb;
|
|
}
|
|
binbuf_eval(b, 0, 0, 0);
|
|
}
|
|
glob_setfilename(0, &s_, &s_); /* bug fix by Krzysztof Czaja */
|
|
binbuf_free(b);
|
|
canvas_resume_dsp(dspstate);
|
|
}
|
|
|
|
void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
|
|
{
|
|
t_pd *x = 0;
|
|
|
|
#ifdef ROCKBOX
|
|
(void) ignore;
|
|
#endif
|
|
/* even though binbuf_evalfile appears to take care of dspstate,
|
|
we have to do it again here, because canvas_startdsp() assumes
|
|
that all toplevel canvases are visible. LATER check if this
|
|
is still necessary -- probably not. */
|
|
|
|
int dspstate = canvas_suspend_dsp();
|
|
binbuf_evalfile(name, dir);
|
|
while ((x != s__X.s_thing) && (x = s__X.s_thing))
|
|
vmess(x, gensym("pop"), "i", 1);
|
|
pd_doloadbang();
|
|
canvas_resume_dsp(dspstate);
|
|
}
|
|
|