Commit cb9dd051 authored by Jonathan Wilkes's avatar Jonathan Wilkes
Browse files

Merge branch 'fix-unique-flag-revised'

parents aaf525e0 a147dfbb
## Makefile.am -- Process this file with automake to produce Makefile.in
#########################################
##### Defaults & Paths #####
NAME=pd~
PATCHES = pd~-help.pd pd~-subprocess.pd
external_LTLIBRARIES = pd~.la pdsched.la
PATCHES = pd~-help.pd pd~-subprocess.pd
OTHERDATA =
pd__la_SOURCES = pd~.c
pdsched_la_SOURCES = pdsched.c
external_LTLIBRARIES = pd~.la pdsched.la
dist_external_DATA = $(PATCHES) $(OTHERDATA)
EXTRA_DIST = makefile notes.txt binarymsg.c
#########################################
##### Files, Binaries, & Libs #####
# you shouldn't need to add anything below here
dist_external_DATA = $(PATCHES) $(OTHERDATA)
AUTOMAKE_OPTIONS = foreign
AM_CPPFLAGS = -I$(top_srcdir)/src -DPD
AM_CFLAGS = @ARCH_CFLAGS@
AM_CFLAGS = @EXTERNAL_CFLAGS@
AM_CPPFLAGS += -I$(top_srcdir)/src -DPD
AM_LIBS = $(LIBM)
AM_LDFLAGS = -module -avoid-version -shared @ARCH_LDFLAGS@ -shrext .@EXTERNAL_EXTENSION@ -L$(top_srcdir)/src
AM_LDFLAGS = -module -avoid-version -shared @EXTERNAL_LDFLAGS@ \
-shrext .@EXTERNAL_EXTENSION@ -L$(top_builddir)/src
externaldir = $(pkglibdir)/extra/$(NAME)
if MINGW
AM_LIBS += -lpd
endif
#########################################
##### Targets #####
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
# create convenience link for running locally
all-local:
rm -f *.@EXTERNAL_EXTENSION@
-$(LN_S) $(wildcard .libs/*.@EXTERNAL_EXTENSION@) ./
clean-local:
rm -f *.@EXTERNAL_EXTENSION@
#include <stdio.h>
#include "m_pd.h"
static void pd_tilde_putfloat(float f, FILE *fd)
{
putc(A_FLOAT, fd);
fwrite(&f, sizeof(f), 1, fd);
}
static void pd_tilde_putsymbol(t_symbol *s, FILE *fd)
{
char *sp = s->s_name;
putc(A_SYMBOL, fd);
do
putc(*sp, fd);
while (*sp++);
}
static int pd_tilde_getatom(t_atom *ap, FILE *fd)
{
char buf[MAXPDSTRING];
while (1)
{
int type = getc(fd), fill;
float f;
switch (type)
{
case EOF:
return (0);
case A_SEMI:
SETSEMI(ap);
return (1);
case A_FLOAT:
if (fread(&f, sizeof(f), 1, fd) >= 1)
{
SETFLOAT(ap, f);
return (1);
}
else return (0);
case A_SYMBOL:
for (fill = 0; fill < MAXPDSTRING; fill++)
{
int c = getc(fd);
if (c == EOF)
return (0);
else buf[fill] = c;
if (!c)
{
SETSYMBOL(ap, gensym(buf));
return (1);
}
}
return (0);
}
}
}
......@@ -4,6 +4,7 @@ CSYM=pd_tilde
include ../makefile.subdir
pd_linux: pdsched.pd_linux
pd_nt: pdsched.dll
d_fat: pdsched.d_fat
d_ppc: pdsched.d_ppc
......@@ -12,3 +13,8 @@ pdsched.pd_linux: pdsched.c
$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
$(CC) -shared -o $*.pd_linux $*.o -lc -lm
rm -f $*.o
pdsched.dll: pdsched.c
$(MSCC) $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
$(MSLN) /nologo /dll /export:pd_extern_sched $*.obj $(PDNTLIB)
rm -f $*.obj
......@@ -12,19 +12,25 @@ outputs audio and messages. */
*/
#include "m_pd.h"
#include "s_stuff.h"
#include "m_imp.h"
#include <stdio.h>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif
#define BUFSIZE 65536
static char inbuf[BUFSIZE];
#include "binarymsg.c"
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)\
|| defined(__GNU__)
void glob_watchdog(t_pd *dummy);
static void pollwatchdog( void)
{
static int sched_diddsp, sched_nextpingtime;
sched_diddsp++;
if (sys_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0))
if (sys_nogui && sys_hipriority &&
(sched_diddsp - sched_nextpingtime > 0))
{
glob_watchdog(0);
/* ping every 2 seconds */
......@@ -34,11 +40,53 @@ static void pollwatchdog( void)
}
#endif
static t_class *pd_ambinary_class;
#define BUFSIZE 65536
static char *ascii_inbuf;
static int readasciimessage(t_binbuf *b)
{
int fill = 0, c;
binbuf_clear(b);
while ((c = getchar()) != EOF)
{
if (c == ';')
{
binbuf_text(b, ascii_inbuf, fill);
return (1);
}
else if (fill < BUFSIZE)
ascii_inbuf[fill++] = c;
else if (fill == BUFSIZE)
fprintf(stderr, "pd-extern: input buffer overflow\n");
}
return (0);
}
static int readbinmessage(t_binbuf *b)
{
binbuf_clear(b);
while (1)
{
t_atom at;
if (!pd_tilde_getatom(&at, stdin))
{
fprintf(stderr, "pd-extern: EOF on input\n");
return (0);
}
else if (at.a_type == A_SEMI)
return (1);
else binbuf_add(b, 1, &at);
}
}
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, blocksize;
int i, j, rate, advance, callback, chin, chout, fill = 0, c, blocksize,
useascii = 0;
t_binbuf *b = binbuf_new();
sys_get_audio_params(&naudioindev, audioindev, chindev,
......@@ -47,60 +95,76 @@ int pd_extern_sched(char *flags)
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);
if (!flags || flags[0] != 'a')
{
/* signal to stdout object to do binary by attaching an object
to an obscure symbol name */
pd_ambinary_class = class_new(gensym("pd~"), 0, 0, sizeof(t_pd),
CLASS_PD, 0);
pd_bind(&pd_ambinary_class, gensym("#pd_binary_stdio"));
/* On Windows, set stdin and out to "binary" mode */
#ifdef _WIN32
setmode(fileno(stdout),O_BINARY);
setmode(fileno(stdin),O_BINARY);
#endif
}
else
{
if (!(ascii_inbuf = getbytes(BUFSIZE)))
return (1);
useascii = 1;
}
/* 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)
while (useascii ? readasciimessage(b) : readbinmessage(b) )
{
if (c == ';')
t_atom *ap = binbuf_getvec(b);
int n = binbuf_getnatom(b);
if (n > 0 && ap[0].a_type == A_FLOAT)
{
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_pollgui();
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
pollwatchdog();
/* 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_pollgui();
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)\
|| defined(__GNU__)
pollwatchdog();
#endif
if (useascii)
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)
else putchar(A_SEMI);
for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--;
fp++)
{
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);
if (useascii)
printf("%g\n", *fp);
else pd_tilde_putfloat(*fp, stdout);
*fp = 0;
}
if (useascii)
printf(";\n");
else putchar(A_SEMI);
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");
}
binbuf_free(b);
return (0);
}
#N canvas 12 0 566 872 12;
#N canvas 113 52 638 844 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 obj 114 614 env~ 8192;
#X floatatom 114 663 5 0 0 0 - - -, f 5;
#X msg 535 750 \; 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 114 639 i;
#X obj 228 612 env~ 8192;
#X floatatom 228 662 5 0 0 0 - - -, f 5;
#X obj 228 638 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 obj 535 724 loadbang;
#X obj 12 643 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
#X text 27 52 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
#X text 24 246 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.
......@@ -34,23 +34,23 @@ 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
#X text 302 469 Creation args:;
#X text 286 486 -insig <n> sets input audio channels;
#X text 287 504 -outsig <n> sets output channels;
#X text 290 538 -fifo <n> sets round-trip delay in blocks;
#X text 293 555 -pddir <s> sets Pd directory \, e.g. \,;
#X text 320 570 .../Pd-0.42.app/Contents/Resources;
#X text 293 586 -scheddir <s> sets scheduler dir \, e.g. \,;
#X text 318 603 .../.../Resources/extra/pd~;
#X text 288 520 -sr <n> sets sample rate;
#X text 28 699 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
#X text 21 756 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.
#X text 393 802 Updated for Pd version 0.42.;
#X text 24 132 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
......
#N canvas 577 21 563 559 12;
#N canvas 600 66 646 598 12;
#X obj 202 395 r foo;
#X obj 202 423 print foo;
#X obj 87 174 adc~;
......@@ -6,12 +6,12 @@
#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 floatatom 87 250 5 0 0 0 - - -, f 5;
#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
#X obj 297 220 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
#X obj 332 186 osc~ 440;
#X obj 332 220 *~;
......@@ -20,7 +20,7 @@
#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 floatatom 160 250 5 0 0 0 - - -, f 5;
#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
......@@ -29,7 +29,7 @@ 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
adc~ here is the first inlet of the pd~ object \, and the first channel
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
......
......@@ -5,19 +5,30 @@
BSD license; see README.txt in this distribution for details.
*/
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <windows.h>
typedef int socklen_t;
#define EADDRINUSE WSAEADDRINUSE
#else
#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>
#include <fcntl.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _MSC_VER
#pragma warning (disable: 4305 4244)
#define snprintf sprintf_s
#define stat _stat
#endif
#ifdef MSP
......@@ -33,7 +44,7 @@ typedef double t_floatarg;
#define A_SYMBOL A_SYM
#define getbytes t_getbytes
#define freebytes t_freebytes
#define ERROR error(
#define PDERROR error(
void *pd_tilde_class;
#define MAXPDSTRING 4096
#define DEFDACBLKSIZE 64
......@@ -43,8 +54,7 @@ void *pd_tilde_class;
#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,
#define PDERROR pd_error(x,
#endif
......@@ -65,6 +75,9 @@ static char pd_tilde_dllextent[] = ".d_fat",
static char pd_tilde_dllextent[] = ".m_i386", pd_tilde_dllextent2[] = ".dll";
#endif
#define FOOFOO
#include "binarymsg.c"
/* ------------------------ pd_tilde~ ----------------------------- */
#define MSGBUFSIZE 65536
......@@ -84,14 +97,13 @@ typedef struct _pd_tilde
#endif /* MSP */
FILE *x_infd;
FILE *x_outfd;
char *x_msgbuf;
int x_msgbufsize;
int x_infill;
t_binbuf *x_binbuf;
int x_childpid;
int x_ninsig;
int x_noutsig;
int x_fifo;
float x_sr;
int x_binary;
t_float x_sr;
t_symbol *x_pddir;
t_symbol *x_schedlibdir;
t_sample **x_insig;
......@@ -114,169 +126,311 @@ char *strcpy(char *s1, const char *s2);
static void pd_tilde_tick(t_pd_tilde *x);
static void pd_tilde_close(t_pd_tilde *x)
{
#ifdef _WIN32
int termstat;
#endif
if (x->x_outfd)
fclose(x->x_outfd);
if (x->x_infd)
fclose(x->x_infd);
if (x->x_childpid > 0)
#ifdef _WIN32
_cwait(&termstat, x->x_childpid, WAIT_CHILD);
#else
waitpid(x->x_childpid, 0, 0);
if (x->x_msgbuf)
free(x->x_msgbuf);
#endif
binbuf_clear(x->x_binbuf);
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)
t_atom at;
binbuf_clear(x->x_binbuf);
if (x->x_binary)
{
int c = getc(infd);
if (c == EOF)
int nonempty = 0;
while (1)
{
ERROR "pd~: %s", strerror(errno));
pd_tilde_close(x);
break;
pd_tilde_getatom(&at, x->x_infd);
if (!nonempty && at.a_type == A_SEMI)
break;
nonempty = (at.a_type != A_SEMI);
binbuf_add(x->x_binbuf, 1, &at);
}
if (x->x_infill >= x->x_msgbufsize)
}
else /* ASCII */
{
t_binbuf *tmpb = binbuf_new();
while (1)
{
char *z = realloc(x->x_msgbuf, x->x_msgbufsize+MSGBUFSIZE);
if (!z)
char msgbuf[MAXPDSTRING];
int c, infill = 0, n;
t_atom *vec;
while (isspace((c = getc(x->x_infd))) && c != EOF)
;
if (c == EOF)
return;
do
msgbuf[infill++] = c;
while (!isspace((c = getc(x->x_infd))) && c != ';' && c != EOF) ;
binbuf_text(tmpb, msgbuf, infill);
n = binbuf_getnatom(tmpb);
vec = binbuf_getvec(tmpb);
binbuf_add(x->x_binbuf, n, vec);
if (!n)
{
ERROR "pd~: failed to grow input buffer");
pd_tilde_close(x);
break;
bug("pd~");
break; /* shouldn't happen */
}
x->x_msgbuf = z;
x->x_msgbufsize += MSGBUFSIZE;
}
x->x_msgbuf[x->x_infill++] = c;
if (c == ';')
{
if (!gotsomething)
if (vec[0].a_type == A_SEMI)
break;
gotsomething = 0;
}
else if (!isspace(c))
gotsomething = setclock = 1;
binbuf_free(tmpb);