diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2011-01-10 06:03:02 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2011-01-10 06:03:02 +0000 |
commit | 5af7081222ef801b23857fb904c78d0798f5d0df (patch) | |
tree | 68ac177c010b99c8eb837ea323c69cb541497148 /externals/extra/pd~ | |
parent | b77e38f5d194fb2ed72563d8ed20815d02a88efc (diff) |
build Pd's extra as a libdir
svn path=/trunk/; revision=14694
Diffstat (limited to 'externals/extra/pd~')
-rw-r--r-- | externals/extra/pd~/notes.txt | 8 | ||||
-rw-r--r-- | externals/extra/pd~/pdsched.c | 85 | ||||
-rw-r--r-- | externals/extra/pd~/pd~-help.pd | 75 | ||||
-rw-r--r-- | externals/extra/pd~/pd~-subprocess.pd | 60 | ||||
-rw-r--r-- | externals/extra/pd~/pd~.c | 765 | ||||
-rw-r--r-- | externals/extra/pd~/z.pd | 15 |
6 files changed, 1008 insertions, 0 deletions
diff --git a/externals/extra/pd~/notes.txt b/externals/extra/pd~/notes.txt new file mode 100644 index 00000000..59129d5a --- /dev/null +++ b/externals/extra/pd~/notes.txt @@ -0,0 +1,8 @@ +pd -schedlib `pwd`/pdsched + +dolist: +pd~ to delay starting subproc until asked +figure out about setting nchannels from command line +fix maximum nchannels in and out + + diff --git a/externals/extra/pd~/pdsched.c b/externals/extra/pd~/pdsched.c new file mode 100644 index 00000000..7efe49a9 --- /dev/null +++ b/externals/extra/pd~/pdsched.c @@ -0,0 +1,85 @@ +/* Copyright 2008 Miller Puckette. Berkeley license; see the +file LICENSE.txt in this distribution. */ + +/* A plug-in scheduler that turns Pd into a filter that inputs and +outputs audio and messages. */ + +/* todo: + fix schedlib code to use extent2 + figure out about if (sys_externalschedlib) { return; } in s_audio.c + make buffer size ynamically growable + +*/ +#include "m_pd.h" +#include "s_stuff.h" +#include <stdio.h> + +#define BUFSIZE 65536 +static char inbuf[BUFSIZE]; + +int pd_extern_sched(char *flags) +{ + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int i, j, rate, advance, callback, chin, chout, fill = 0, c; + t_binbuf *b = binbuf_new(); + + sys_get_audio_params(&naudioindev, audioindev, chindev, + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); + + chin = (naudioindev < 1 ? 0 : chindev[0]); + chout = (naudiooutdev < 1 ? 0 : choutdev[0]); + + fprintf(stderr, "Pd plug-in scheduler called, chans %d %d, sr %d\n", + chin, chout, (int)rate); + sys_setchsr(chin, chout, rate); + sys_audioapi = API_NONE; + while ((c = getchar()) != EOF) + { + if (c == ';') + { + int n; + t_atom *ap; + binbuf_text(b, inbuf, fill); + n = binbuf_getnatom(b); + ap = binbuf_getvec(b); + fill = 0; + if (n > 0 && ap[0].a_type == A_FLOAT) + { + /* a list -- take it as incoming signals. */ + int chan, nchan = n/DEFDACBLKSIZE; + t_sample *fp; + for (i = chan = 0, fp = sys_soundin; chan < nchan; chan++) + for (j = 0; j < DEFDACBLKSIZE; j++) + *fp++ = atom_getfloat(ap++); + for (; chan < chin; chan++) + for (j = 0; j < DEFDACBLKSIZE; j++) + *fp++ = 0; + sched_tick(sys_time+sys_time_per_dsp_tick); + sys_pollgui(); + printf(";\n"); + for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++) + { + printf("%g\n", *fp); + *fp = 0; + } + printf(";\n"); + fflush(stdout); + } + else if (n > 1 && ap[0].a_type == A_SYMBOL) + { + t_pd *whom = ap[0].a_w.w_symbol->s_thing; + if (!whom) + error("%s: no such object", ap[0].a_w.w_symbol->s_name); + else if (ap[1].a_type == A_SYMBOL) + typedmess(whom, ap[1].a_w.w_symbol, n-2, ap+2); + else pd_list(whom, 0, n-1, ap+1); + } + } + else if (fill < BUFSIZE) + inbuf[fill++] = c; + else if (fill == BUFSIZE) + fprintf(stderr, "pd-extern: input buffer overflow\n"); + } + return (0); +} diff --git a/externals/extra/pd~/pd~-help.pd b/externals/extra/pd~/pd~-help.pd new file mode 100644 index 00000000..8bc357e0 --- /dev/null +++ b/externals/extra/pd~/pd~-help.pd @@ -0,0 +1,75 @@ +#N canvas 12 0 566 872 12; +#X msg 31 406 foo bar baz; +#X obj 189 466 osc~ 440; +#X obj 127 645 env~ 8192; +#X floatatom 127 694 5 0 0 0 - - -; +#X msg 434 807 \; pd dsp 1; +#X msg 24 332 pd~ stop; +#X obj 127 670 i; +#X obj 241 643 env~ 8192; +#X floatatom 241 693 5 0 0 0 - - -; +#X obj 241 669 i; +#X obj 123 489 *~; +#X obj 158 490 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 189 490 *~; +#X obj 224 491 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 434 781 loadbang; +#X obj 14 691 print x; +#X msg 15 309 pd~ start pd~-subprocess.pd; +#X obj 14 532 pd~ -ninsig 2 -noutsig 2 -fifo 20; +#X obj 37 20 pd~; +#X text 69 22 - run a pd sub-process; +#X text 27 57 The pd~ object starts and manages a Pd sub-process that +can communicate with the super-process (this one) via audio channels +and/or Pd messages. In this way you can take advantage of multi-core +CPUs \, and/or use Pd features from within Max (if you're using the +Max version of pd~).; +#X text 24 251 Sending a new "start" message will stop the sub-process +and start a new one. If you just want to stop the sub-process \, send +"stop".; +#X text 33 353 Any message besides "pd~" is sent to the sub-process. +For instance \, the message below sends "bar baz" to any object in +the sub-process named "foo" \, such as a "receive" object.; +#X text 43 430 Audio signals appear in adc~ objects in the sub-process. +The sub-process doesn't open real audio devices.; +#X text 281 473 Creation args:; +#X text 265 490 -insig <n> sets input audio channels; +#X text 266 508 -outsig <n> sets output channels; +#X text 269 542 -fifo <n> sets round-trip delay in blocks; +#X text 272 559 -pddir <s> sets Pd directory \, e.g. \,; +#X text 299 574 .../Pd-0.42.app/Contents/Resources; +#X text 272 590 -scheddir <s> sets scheduler dir \, e.g. \,; +#X text 297 607 .../.../Resources/extra/pd~; +#X text 267 524 -sr <n> sets sample rate; +#X text 20 716 The first outlet reports messages the sub-process sends +us via "stdout" objects. Any other outlets are signals corresponding +to "dac~" objects in the sub-process.; +#X text 10 784 ATTENTION: DSP must be running in this process for the +sub-process to run. This is because its clock is slaved to audio I/O +it gets from us!; +#X text 359 849 Updated for Pd version 0.42.; +#X text 24 138 Messages with "pd~" selector control the sub-process. +"pd~ start" takes as arguments any startup arguments you wish to send +the sub-process. For example \, specify "-nogui" to stop the sub-process's +GUI from appearing. You don't have to specify the number of channels +in and out \, since that's set by creation arguments below. Audio config +arguments arguments (-audiobuf \, -audiodev \, etc.) are ignored.; +#X connect 0 0 17 0; +#X connect 1 0 10 0; +#X connect 1 0 12 0; +#X connect 2 0 6 0; +#X connect 5 0 17 0; +#X connect 6 0 3 0; +#X connect 7 0 9 0; +#X connect 9 0 8 0; +#X connect 10 0 17 0; +#X connect 11 0 10 1; +#X connect 12 0 17 1; +#X connect 13 0 12 1; +#X connect 14 0 4 0; +#X connect 16 0 17 0; +#X connect 17 0 15 0; +#X connect 17 1 2 0; +#X connect 17 2 7 0; diff --git a/externals/extra/pd~/pd~-subprocess.pd b/externals/extra/pd~/pd~-subprocess.pd new file mode 100644 index 00000000..1d883ab1 --- /dev/null +++ b/externals/extra/pd~/pd~-subprocess.pd @@ -0,0 +1,60 @@ +#N canvas 577 21 563 559 12; +#X obj 202 395 r foo; +#X obj 202 423 print foo; +#X obj 87 174 adc~; +#X obj 72 442 stdout; +#X msg 72 364 a b c; +#X msg 455 441 \; pd dsp 1; +#X obj 87 201 env~ 8192; +#X floatatom 87 250 5 0 0 0 - - -; +#X obj 87 226 i; +#X obj 263 253 dac~; +#X obj 262 185 osc~ 440; +#X obj 262 219 *~; +#X obj 297 220 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 332 186 osc~ 440; +#X obj 332 220 *~; +#X obj 367 221 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 86 411 bang; +#X obj 455 417 loadbang; +#X obj 160 201 env~ 8192; +#X floatatom 160 250 5 0 0 0 - - -; +#X obj 160 226 i; +#X msg 86 388 4; +#X text 62 8 This is a test patch to demonstrate the Pd~ object. It's +intended as the patch to run in the sub-process. The sub-process (which +is a separate instance of Pd) can be called from a Max or Pd super-process. +; +#X text 63 73 Audio inlets and outlets on the Pd~ object (in the super-process) +talk to adc~ and dac~ objects here - so \, for instance \, the first +adc~ here is the first inlet of the pd~ object \, and the first chanel +of dac~ goes to the second outlet of pd~ (because the first one is +for messages \, as shown further below.); +#X text 58 283 Any message sent to a stdout object in this sub-process +(below) appears on the first \, message outlet of the pd~ object in +the super-process. The super-process can send messages to any "receive" +object in this sub-process.; +#X text 137 478 We turn DSP on at load for convenience - control objects +in this patch will still work without it (unlike in the super-process +\, where DSP must be on for time to move forward in the sub-process.) +; +#X text 351 538 Updated for Pd version 0.42.; +#X connect 0 0 1 0; +#X connect 2 0 6 0; +#X connect 2 1 18 0; +#X connect 4 0 3 0; +#X connect 6 0 8 0; +#X connect 8 0 7 0; +#X connect 10 0 11 0; +#X connect 11 0 9 0; +#X connect 12 0 11 1; +#X connect 13 0 14 0; +#X connect 14 0 9 1; +#X connect 15 0 14 1; +#X connect 16 0 3 0; +#X connect 17 0 5 0; +#X connect 18 0 20 0; +#X connect 20 0 19 0; +#X connect 21 0 3 0; diff --git a/externals/extra/pd~/pd~.c b/externals/extra/pd~/pd~.c new file mode 100644 index 00000000..165065f8 --- /dev/null +++ b/externals/extra/pd~/pd~.c @@ -0,0 +1,765 @@ +/* + pd~.c - embed a Pd process within Pd or Max. + + Copyright 2008 Miller Puckette + BSD license; see README.txt in this distribution for details. +*/ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#ifdef NT +#pragma warning (disable: 4305 4244) +#endif + +#ifdef MSP +#include "ext.h" +#include "z_dsp.h" +#include "math.h" +#include "ext_support.h" +#include "ext_proto.h" +#include "ext_obex.h" + +typedef double t_floatarg; +#define w_symbol w_sym +#define A_SYMBOL A_SYM +#define getbytes t_getbytes +#define freebytes t_freebytes +#define ERROR error( +void *pd_tilde_class; +#define MAXPDSTRING 4096 +#define DEFDACBLKSIZE 64 +#endif /* MSP */ + +#ifdef PD +#include "m_pd.h" +#include "s_stuff.h" +static t_class *pd_tilde_class; +char *class_gethelpdir(t_class *c); +#define ERROR pd_error(x, + +#endif + +#ifdef __linux__ +#ifdef __x86_64__ +static char pd_tilde_dllextent[] = ".l_ia64", + pd_tilde_dllextent2[] = ".pd_linux"; +#else +static char pd_tilde_dllextent[] = ".l_i386", + pd_tilde_dllextent2[] = ".pd_linux"; +#endif +#endif +#ifdef __APPLE__ +static char pd_tilde_dllextent[] = ".d_fat", + pd_tilde_dllextent2[] = ".pd_darwin"; +#endif + +/* ------------------------ pd_tilde~ ----------------------------- */ + +#define MSGBUFSIZE 65536 + +typedef struct _pd_tilde +{ +#ifdef PD + t_object x_obj; + t_clock *x_clock; + t_outlet *x_outlet1; /* for messages back from subproc */ + t_canvas *x_canvas; +#endif /* PD */ +#ifdef MSP + t_pxobject x_obj; + void *x_outlet1; + void *x_clock; +#endif /* MSP */ + FILE *x_infd; + FILE *x_outfd; + char *x_msgbuf; + int x_msgbufsize; + int x_infill; + int x_childpid; + int x_ninsig; + int x_noutsig; + int x_fifo; + float x_sr; + t_symbol *x_pddir; + t_symbol *x_schedlibdir; + t_sample **x_insig; + t_sample **x_outsig; +} t_pd_tilde; + +#ifdef MSP +static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av); +static void pd_tilde_tick(t_pd_tilde *x); +static t_int *pd_tilde_perform(t_int *w); +static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp); +void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s); +static void pd_tilde_free(t_pd_tilde *x); +void pd_tilde_setup(void); +int main(); +void pd_tilde_minvel_set(t_pd_tilde *x, void *attr, long ac, t_atom *av); +char *strcpy(char *s1, const char *s2); +#endif + +static void pd_tilde_tick(t_pd_tilde *x); +static void pd_tilde_close(t_pd_tilde *x) +{ + if (x->x_outfd) + fclose(x->x_outfd); + if (x->x_infd) + fclose(x->x_infd); + if (x->x_childpid > 0) + waitpid(x->x_childpid, 0, 0); + if (x->x_msgbuf) + free(x->x_msgbuf); + x->x_infd = x->x_outfd = 0; + x->x_childpid = -1; + x->x_msgbuf = 0; + x->x_msgbufsize = 0; +} + +static void pd_tilde_readmessages(t_pd_tilde *x) +{ + int gotsomething = 0, setclock = 0, wasempty = (x->x_infill == 0); + FILE *infd = x->x_infd; + while (1) + { + int c = getc(infd); + if (c == EOF) + { + ERROR "pd~: %s", strerror(errno)); + pd_tilde_close(x); + break; + } + if (x->x_infill >= x->x_msgbufsize) + { + char *z = realloc(x->x_msgbuf, x->x_msgbufsize+MSGBUFSIZE); + if (!z) + { + ERROR "pd~: failed to grow input buffer"); + pd_tilde_close(x); + break; + } + x->x_msgbuf = z; + x->x_msgbufsize += MSGBUFSIZE; + } + x->x_msgbuf[x->x_infill++] = c; + if (c == ';') + { + if (!gotsomething) + break; + gotsomething = 0; + } + else if (!isspace(c)) + gotsomething = setclock = 1; + } + if (setclock) + clock_delay(x->x_clock, 0); + else if (wasempty) + x->x_infill = 0; +} + +static void pd_tilde_donew(t_pd_tilde *x, char *pddir, char *schedlibdir, + char *patchdir, char *pdargs, int ninsig, int noutsig, int fifo, + float samplerate) +{ + int i, pid, pipe1[2], pipe2[2]; + char cmdbuf[MAXPDSTRING], pdexecbuf[MAXPDSTRING], schedbuf[MAXPDSTRING]; + struct stat statbuf; + x->x_infd = x->x_outfd = 0; + x->x_childpid = -1; + snprintf(pdexecbuf, MAXPDSTRING, "%s/bin/pd", pddir); + if (stat(pdexecbuf, &statbuf) < 0) + { + snprintf(pdexecbuf, MAXPDSTRING, "%s/../../../bin/pd", pddir); + if (stat(pdexecbuf, &statbuf) < 0) + { + snprintf(pdexecbuf, MAXPDSTRING, "%s/pd", pddir); + if (stat(pdexecbuf, &statbuf) < 0) + { + ERROR "pd~: can't stat %s", pdexecbuf); + goto fail1; + } + } + } + snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, + pd_tilde_dllextent); + if (stat(schedbuf, &statbuf) < 0) + { + snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, + pd_tilde_dllextent2); + if (stat(schedbuf, &statbuf) < 0) + { + ERROR "pd~: can't stat %s", schedbuf); + goto fail1; + } + } + snprintf(cmdbuf, MAXPDSTRING, +"%s -schedlib %s/pdsched -path %s -inchannels %d -outchannels %d -r %g %s\n", + pdexecbuf, schedlibdir, patchdir, ninsig, noutsig, samplerate, pdargs); +#if 0 +#ifdef PD + fprintf(stderr, "%s", cmdbuf); +#endif + post("cmd: %s", cmdbuf); +#endif + if (pipe(pipe1) < 0) + { + ERROR "pd~: can't create pipe"); + goto fail1; + } + if (pipe(pipe2) < 0) + { + ERROR "pd~: can't create pipe"); + goto fail2; + } + if ((pid = fork()) < 0) + { + ERROR "pd~: can't fork"); + goto fail3; + } + else if (pid == 0) + { + /* child process */ + if (pipe2[1] == 0) + { + dup2(pipe2[1], 20); + close(pipe2[1]); + pipe2[1] = 20; + } + dup2(pipe1[0], 0); + dup2(pipe2[1], 1); + if (pipe1[0] >= 2) + close(pipe1[0]); + if (pipe1[1] >= 2) + close(pipe1[1]); + if (pipe2[0] >= 2) + close(pipe2[0]); + if (pipe2[1] >= 2) + close(pipe2[1]); + execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0); + _exit(1); + } + /* OK, we're parent */ + close(pipe1[0]); + close(pipe2[1]); + x->x_outfd = fdopen(pipe1[1], "w"); + x->x_infd = fdopen(pipe2[0], "r"); + x->x_childpid = pid; + for (i = 0; i < fifo; i++) + fprintf(x->x_outfd, "%s", ";\n0;\n"); + fflush(x->x_outfd); + if (!(x->x_msgbuf = calloc(MSGBUFSIZE, 1))) + { + ERROR "pd~: can't allocate message buffer"); + goto fail3; + } + x->x_msgbufsize = MSGBUFSIZE; + x->x_infill = 0; + /* fprintf(stderr, "read...\n"); */ + pd_tilde_readmessages(x); + /* fprintf(stderr, "... done.\n"); */ + return; +fail3: + close(pipe2[0]); + close(pipe2[1]); + if (x->x_childpid > 0) + waitpid(x->x_childpid, 0, 0); +fail2: + close(pipe1[0]); + close(pipe1[1]); +fail1: + x->x_infd = x->x_outfd = 0; + x->x_childpid = -1; + return; +} + +static t_int *pd_tilde_perform(t_int *w) +{ + t_pd_tilde *x = (t_pd_tilde *)(w[1]); + int n = (int)(w[2]), i, j, numbuffill = 0, c; + char numbuf[80]; + FILE *infd = x->x_infd; + if (!infd) + goto zeroit; + fprintf(x->x_outfd, ";\n"); + if (!x->x_ninsig) + fprintf(x->x_outfd, "0\n"); + else for (i = 0; i < x->x_ninsig; i++) + { + t_sample *fp = x->x_insig[i]; + for (j = 0; j < n; j++) + fprintf(x->x_outfd, "%g\n", *fp++); + for (; j < DEFDACBLKSIZE; j++) + fprintf(x->x_outfd, "0\n"); + } + fprintf(x->x_outfd, ";\n"); + fflush(x->x_outfd); + i = j = 0; + while (1) + { + while (1) + { + c = getc(infd); + if (c == EOF) + { + if (errno) + ERROR "pd~: %s", strerror(errno)); + else ERROR "pd~: subprocess exited"); + pd_tilde_close(x); + goto zeroit; + } + else if (!isspace(c) && c != ';') + { + if (numbuffill < (80-1)) + numbuf[numbuffill++] = c; + } + else + { + t_sample z; + if (numbuffill) + { + numbuf[numbuffill] = 0; + if (sscanf(numbuf, "%f", &z) < 1) + continue; + if (i < x->x_noutsig) + x->x_outsig[i][j] = z; + if (++j >= DEFDACBLKSIZE) + j = 0, i++; + } + numbuffill = 0; + break; + } + } + /* message terminated */ + if (c == ';') + break; + } + for (; i < x->x_noutsig; i++, j = 0) + { + for (; j < DEFDACBLKSIZE; j++) + x->x_outsig[i][j] = 0; + } + pd_tilde_readmessages(x); + return (w+3); +zeroit: + for (i = 0; i < x->x_noutsig; i++) + { + for (j = 0; j < DEFDACBLKSIZE; j++) + x->x_outsig[i][j] = 0; + } + return (w+3); +} + +static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp) +{ + int i, n = (x->x_ninsig || x->x_noutsig ? sp[0]->s_n : 1); + t_sample **g; + + for (i = 0, g = x->x_insig; i < x->x_ninsig; i++, g++) + *g = (*(sp++))->s_vec; + + for (i = 0, g = x->x_outsig; i < x->x_noutsig; i++, g++) + *g = (*(sp++))->s_vec; + + dsp_add(pd_tilde_perform, 2, x, n); +} + +static void pd_tilde_pdtilde(t_pd_tilde *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_symbol *sel = ((argc > 0 && argv->a_type == A_SYMBOL) ? + argv->a_w.w_symbol : gensym("?")), *schedlibdir; + char *patchdir; + if (sel == gensym("start")) + { + char pdargstring[MAXPDSTRING]; + if (x->x_infd) + pd_tilde_close(x); + pdargstring[0] = 0; + argc--; argv++; +#ifdef PD + while (argc--) + { + atom_string(argv++, pdargstring + strlen(pdargstring), + MAXPDSTRING - strlen(pdargstring)); + if (strlen(pdargstring) < MAXPDSTRING-1) + strcat(pdargstring, " "); + } + patchdir = canvas_getdir(x->x_canvas)->s_name; +#endif +#ifdef MSP + while (argc--) + { + /* because Mac pathnames sometimes have an evil preceeding + colon character, we test for and silently eat them */ + if (argv->a_type == A_SYM) + strncat(pdargstring, (*argv->a_w.w_sym->s_name == ':'? + argv->a_w.w_sym->s_name+1 : argv->a_w.w_sym->s_name), + MAXPDSTRING - strlen(pdargstring)-3); + else if (argv->a_type == A_LONG) + snprintf(pdargstring+strlen(pdargstring), + MAXPDSTRING - strlen(pdargstring)-3, "%ld", + argv->a_w.w_long); + else if (argv->a_type == A_FLOAT) + snprintf(pdargstring+strlen(pdargstring), + MAXPDSTRING - strlen(pdargstring)-3, "%f", + argv->a_w.w_float); + strcat(pdargstring, " "); + argv++; + } + patchdir = "."; +#endif + schedlibdir = x->x_schedlibdir; + if (schedlibdir == gensym(".") && x->x_pddir != gensym(".")) + { + char *pds = x->x_pddir->s_name, scheddirstring[MAXPDSTRING]; + int l = strlen(pds); + if (l >= 4 && (!strcmp(pds+l-3, "bin") || !strcmp(pds+l-4, "bin/"))) + snprintf(scheddirstring, MAXPDSTRING, "%s/../extra/pd~", pds); + else snprintf(scheddirstring, MAXPDSTRING, "%s/extra/pd~", pds); + schedlibdir = gensym(scheddirstring); + } + pd_tilde_donew(x, x->x_pddir->s_name, schedlibdir->s_name, + patchdir, pdargstring, x->x_ninsig, x->x_noutsig, x->x_fifo, + x->x_sr); + } + else if (sel == gensym("stop")) + { + if (x->x_infd) + pd_tilde_close(x); + } + else if (sel == gensym("pddir")) + { + if ((argc > 1) && argv[1].a_type == A_SYMBOL) + { + t_symbol *sym = argv[1].a_w.w_symbol; +#ifdef MSP + if (sym->s_name[0] == ':') + sym = gensym(s->s_name+1); +#endif + x->x_pddir = sym; + } + else ERROR "pd~ pddir: needs symbol argument"); + } + else ERROR "pd~: unknown control message: %s", sel->s_name); +} + +static void pd_tilde_free(t_pd_tilde *x) +{ +#ifdef MSP + dsp_free((t_pxobject *)x); +#endif + pd_tilde_close(x); + clock_free(x->x_clock); +} + +/* -------------------------- Pd glue ------------------------- */ +#ifdef PD + +static void pd_tilde_tick(t_pd_tilde *x) +{ + int messstart = 0, i, n; + t_atom *vec; + t_binbuf *b; + if (!x->x_msgbuf) + return; + b = binbuf_new(); + binbuf_text(b, x->x_msgbuf, x->x_infill); + /* binbuf_print(b); */ + n = binbuf_getnatom(b); + vec = binbuf_getvec(b); + for (i = 0; i < n; i++) + { + if (vec[i].a_type == A_SEMI) + { + if (i > messstart && vec[messstart].a_type == A_SYMBOL) + outlet_anything(x->x_outlet1, vec[messstart].a_w.w_symbol, + i-(messstart+1), vec+(messstart+1)); + else if (i > messstart) + outlet_list(x->x_outlet1, 0, i-messstart, vec+messstart); + messstart = i+1; + } + } + binbuf_free(b); + x->x_infill = 0; +} + +static void pd_tilde_anything(t_pd_tilde *x, t_symbol *s, + int argc, t_atom *argv) +{ + char msgbuf[MAXPDSTRING]; + if (!x->x_outfd) + return; + fprintf(x->x_outfd, "%s ", s->s_name); + while (argc--) + { + atom_string(argv++, msgbuf, MAXPDSTRING); + fprintf(x->x_outfd, "%s ", msgbuf); + } + fprintf(x->x_outfd, ";\n"); +} + +static void *pd_tilde_new(t_symbol *s, int argc, t_atom *argv) +{ + t_pd_tilde *x = (t_pd_tilde *)pd_new(pd_tilde_class); + int ninsig = 2, noutsig = 2, j, fifo = 5; + float sr = sys_getsr(); + t_sample **g; + t_symbol *pddir = sys_guidir, + *scheddir = gensym(class_gethelpdir(pd_tilde_class)); + /* fprintf(stderr, "pd %s, sched %s\n", pddir->s_name, scheddir->s_name); */ + while (argc > 0) + { + t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); + if (!strcmp(firstarg->s_name, "-sr") && argc > 1) + { + sr = atom_getfloatarg(1, argc, argv); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-ninsig") && argc > 1) + { + ninsig = atom_getfloatarg(1, argc, argv); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-noutsig") && argc > 1) + { + noutsig = atom_getfloatarg(1, argc, argv); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-fifo") && argc > 1) + { + fifo = atom_getfloatarg(1, argc, argv); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-pddir") && argc > 1) + { + pddir = atom_getsymbolarg(1, argc, argv); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-scheddir") && argc > 1) + { + scheddir = atom_getsymbolarg(1, argc, argv); + argc -= 2; argv += 2; + } + else break; + } + + if (argc) + { + pd_error(x, +"usage: pd~ [-sr #] [-ninsig #] [-noutsig #] [-fifo #] [-pddir <>]"); + post( +"... [-scheddir <>]"); + } + + x->x_clock = clock_new(x, (t_method)pd_tilde_tick); + x->x_insig = (t_sample **)getbytes(ninsig * sizeof(*x->x_insig)); + x->x_outsig = (t_sample **)getbytes(noutsig * sizeof(*x->x_outsig)); + x->x_ninsig = ninsig; + x->x_noutsig = noutsig; + x->x_fifo = fifo; + x->x_sr = sr; + x->x_pddir = pddir; + x->x_schedlibdir = scheddir; + x->x_infd = 0; + x->x_outfd = 0; + x->x_outfd = 0; + x->x_childpid = -1; + x->x_msgbuf = 0; + x->x_canvas = canvas_getcurrent(); + for (j = 1, g = x->x_insig; j < ninsig; j++, g++) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + x->x_outlet1 = outlet_new(&x->x_obj, 0); + for (j = 0, g = x->x_outsig; j < noutsig; j++, g++) + outlet_new(&x->x_obj, &s_signal); + signal(SIGPIPE, SIG_IGN); + + return (x); +} + +void pd_tilde_setup(void) +{ + pd_tilde_class = class_new(gensym("pd~"), (t_newmethod)pd_tilde_new, + (t_method)pd_tilde_free, sizeof(t_pd_tilde), 0, A_GIMME, 0); + class_addmethod(pd_tilde_class, nullfn, gensym("signal"), 0); + class_addmethod(pd_tilde_class, (t_method)pd_tilde_dsp, gensym("dsp"), 0); + class_addmethod(pd_tilde_class, (t_method)pd_tilde_pdtilde, gensym("pd~"), A_GIMME, 0); + class_addanything(pd_tilde_class, pd_tilde_anything); + post("pd~ version 0.2"); +} +#endif + +/* -------------------------- MSP glue ------------------------- */ +#ifdef MSP + +#define LOTS 10000 + +static void pd_tilde_tick(t_pd_tilde *x) +{ + int messstart = 0, i, n = 0; + t_atom vec[LOTS]; + long z1 = 0, z2 = 0; + void *b; + if (!x->x_msgbuf) + return; + b = binbuf_new(); + binbuf_text(b, &x->x_msgbuf, x->x_infill); + /* binbuf_print(b); */ + while (!binbuf_getatom(b, &z1, &z2, vec+n)) + if (++n >= LOTS) + break; + for (i = 0; i < n; i++) + { + if (vec[i].a_type == A_SEMI) + { + if (i > messstart + 1) + { + void *whom; + if (vec[messstart].a_type == A_SYM) + outlet_anything(x->x_outlet1, vec[messstart].a_w.w_sym, + i-messstart-1, vec+(messstart+1)); + else if (vec[messstart].a_type == A_FLOAT && i == messstart+1) + outlet_float(x->x_outlet1, vec[messstart].a_w.w_float); + else if (vec[messstart].a_type == A_LONG && i == messstart+1) + outlet_int(x->x_outlet1, vec[messstart].a_w.w_long); + else outlet_list(x->x_outlet1, gensym("list"), + i-messstart, vec+(messstart)); + } + messstart = i+1; + } + } + binbuf_free(b); + x->x_infill = 0; +} + +static void pd_tilde_anything(t_pd_tilde *x, t_symbol *s, + long ac, t_atom *av) +{ + char msgbuf[MAXPDSTRING], *sp, *ep = msgbuf+MAXPDSTRING; + if (!x->x_outfd) + return; + msgbuf[0] = 0; + strncpy(msgbuf, s->s_name, MAXPDSTRING); + msgbuf[MAXPDSTRING-1] = 0; + sp = msgbuf + strlen(msgbuf); + while (ac--) + { + if (sp < ep-1) + sp[0] = ' ', sp[1] = 0, sp++; + if (sp < ep - 80) + { + if (av->a_type == A_SYM && strlen(av->a_w.w_sym->s_name) < ep - sp-20) + strcpy(sp, av->a_w.w_sym->s_name); + else if (av->a_type == A_LONG) + sprintf(sp, "%ld" ,av->a_w.w_long); + else if (av->a_type == A_FLOAT) + sprintf(sp, "%g" ,av->a_w.w_float); + } + sp += strlen(sp); + av++; + } + fprintf(x->x_outfd, "%s;\n", msgbuf); +} + +int main() +{ + t_class *c; + + c = class_new("pd_tilde~", (method)pd_tilde_new, (method)pd_tilde_free, sizeof(t_pd_tilde), (method)0L, A_GIMME, 0); + + class_addmethod(c, (method)pd_tilde_dsp, "dsp", A_CANT, 0); + class_addmethod(c, (method)pd_tilde_assist, "assist", A_CANT, 0); + class_addmethod(c, (method)pd_tilde_pdtilde, "pd~", A_GIMME, 0); + class_addmethod(c, (method)pd_tilde_anything, "anything", A_GIMME, 0); + class_dspinit(c); + + class_register(CLASS_BOX, c); + pd_tilde_class = c; + post("pd~ version 0.2"); + return (0); +} + +static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av) +{ + int ninsig = 2, noutsig = 2, fifo = 5, j; + float sr = sys_getsr(); + t_symbol *pddir = gensym("."), *scheddir = gensym("."); + t_pd_tilde *x; + + if (x = (t_pd_tilde *)object_alloc(pd_tilde_class)) + { + while (ac > 0 && av[0].a_type == A_SYM) + { + char *flag = av[0].a_w.w_sym->s_name; + if (!strcmp(flag, "-sr") && ac > 1) + { + sr = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float : + (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0)); + ac -= 2; av += 2; + } + else if (!strcmp(flag, "-ninsig") && ac > 1) + { + ninsig = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float : + (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0)); + ac -= 2; av += 2; + } + else if (!strcmp(flag, "-noutsig") && ac > 1) + { + noutsig = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float : + (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0)); + ac -= 2; av += 2; + } + else if (!strcmp(flag, "-fifo") && ac > 1) + { + fifo = (av[1].a_type == A_FLOAT ? av[1].a_w.w_float : + (av[1].a_type == A_LONG ? av[1].a_w.w_long : 0)); + ac -= 2; av += 2; + } + else if (!strcmp(flag, "-pddir") && ac > 1) + { + pddir = (av[1].a_type == A_SYM ? av[1].a_w.w_sym : gensym(".")); + ac -= 2; av += 2; + } + else if (!strcmp(flag, "-scheddir") && ac > 1) + { + scheddir = (av[1].a_type == A_SYM ? av[1].a_w.w_sym : gensym(".")); + ac -= 2; av += 2; + } + else break; + } + if (ac) + post("pd~: warning: ignoring extra arguments"); + dsp_setup((t_pxobject *)x, ninsig); + x->x_outlet1 = outlet_new(&x->x_obj, 0); + for (j = 0; j < noutsig; j++) + outlet_new((t_pxobject *)x, "signal"); + x->x_clock = clock_new(x, (method)pd_tilde_tick); + x->x_insig = (t_sample **)getbytes(ninsig * sizeof(*x->x_insig)); + x->x_outsig = (t_sample **)getbytes(noutsig * sizeof(*x->x_outsig)); + x->x_ninsig = ninsig; + x->x_noutsig = noutsig; + x->x_fifo = fifo; + x->x_sr = sr; + x->x_pddir = pddir; + x->x_schedlibdir = scheddir; + x->x_infd = 0; + x->x_outfd = 0; + x->x_outfd = 0; + x->x_childpid = -1; + x->x_msgbuf = 0; + } + return (x); +} + +void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s) +{ +} + +#endif /* MSP */ diff --git a/externals/extra/pd~/z.pd b/externals/extra/pd~/z.pd new file mode 100644 index 00000000..373201da --- /dev/null +++ b/externals/extra/pd~/z.pd @@ -0,0 +1,15 @@ +#N canvas 686 241 450 300 10; +#X obj 65 58 r foo; +#X obj 62 100 print foo; +#X obj 244 59 adc~; +#X obj 238 102 env~ 8192; +#X floatatom 236 140 5 0 0 0 - - -; +#X obj 155 234 dac~; +#X obj 155 191 osc~ 440; +#X obj 287 204 stdout; +#X msg 307 153 a b c; +#X connect 0 0 1 0; +#X connect 2 0 3 0; +#X connect 3 0 4 0; +#X connect 6 0 5 0; +#X connect 8 0 7 0; |