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
......
This diff is collapsed.
......@@ -31,14 +31,19 @@ function have_args() {
}
function set_vars(win) {
var port_no, font_engine_sanity, pd_engine_id;
var port_no, font_engine_sanity, pd_engine_id, argv_offset;
// If the GUI was started by Pd, our port number is going to be
// the first argument. If the GUI is supposed to start Pd, we won't
// have any arguments and need to set it here.
if (have_args() && gui.App.argv.length > 1) {
port_no = gui.App.argv[0]; // fed to us by the Pd process
// Unfortunately there's a bug in nw.js where the argument that
// specifies the package.json path doesn't get included in the
// argv array. This happens under Windows and Linux but apparently
// not under OSX. That means we need an offset hack
argv_offset = process.platform === "darwin" ? 1 : 0;
port_no = gui.App.argv[1 + argv_offset]; // fed to us by the Pd process
// address unique to the pd_engine
pd_engine_id = gui.App.argv[4];
pd_engine_id = gui.App.argv[5 + argv_offset];
} else {
// If we're starting Pd, this is the first port number to try. (We'll
// increment it if that port happens to be taken.)
......
......@@ -224,7 +224,7 @@ pd.res: pd.rc
# for making objects included with Pd, [expr] is whacky, so its built
# separately, and pd~ doesn't build on Windows yet
EXTERNALS_SRC := $(wildcard $(pd_src)/extra/[a-df-oq-z]*/*.c)
EXTERNALS_SRC := $(wildcard $(pd_src)/extra/[a-z]*/*.c)
#EXPR_SRC = vexp.c vexp_fun.c vexp_if.c
#EXPR_OBJ = $(patsubst %.c, $(pd_src)/extra/expr~/%.o, $(EXPR_SRC))
#expr_src = $(pd_src)/extra/expr~
......
......@@ -1135,6 +1135,57 @@ static int defaultfontshit[MAXFONTS] = {
24, 15, 28};
#define NDEFAULTFONT (sizeof(defaultfontshit)/sizeof(*defaultfontshit))
extern t_symbol *pd_getplatform(void);
extern void sys_expandpath(const char *from, char *to);
/* set the datadir for nwjs. We use the published nw.js
defaults if there's only one instance of the GUI set to
run. Otherwise, we append the port number so that
nw.js will spawn a new instance for us.
Currently, users can give a command line arg to force Pd
to start with a new GUI instance. A new GUI must also get
created when a user turns on audio and there is a [pd~] object
on the canvas. The latter would actually be more usable within
a single GUI instance, but that would require some way to
visually distinguish patches that are associated with different Pd
engine processes.
*/
static void set_datadir(char *buf, int new_gui_instance, int portno)
{
char dir[FILENAME_MAX];
t_symbol *platform = pd_getplatform();
strcpy(buf, "--user-data-dir=");
/* Let's go ahead and quote the string to handle spaces in
paths, etc. */
strcat(buf, "\"");
if (platform == gensym("darwin"))
sys_expandpath("~/Library/Application Support/", dir);
else if (platform != gensym("win32"))/* bsd and linux */
sys_expandpath("~/.config/", dir);
#ifdef _WIN32
/* win32 has a more robust API for getting the
value of %LOCALAPPDATA%, but this works on
Windows 7 and is straightforward... */
char *env = getenv("LOCALAPPDATA");
strcpy(dir, env);
strcat(dir, "\\");
#endif
strcat(dir, "purr-data");
if (new_gui_instance)
{
char portbuf[10];
sprintf(portbuf, "-%d", portno);
strcat(dir, portbuf);
}
strcat(buf, dir);
/* Finally, close quote... */
strcat(buf, "\"");
}
extern int sys_unique;
int sys_startgui(const char *guidir)
{
pid_t childpid;
......@@ -1146,13 +1197,12 @@ int sys_startgui(const char *guidir)
int xsock = -1;
stderr_isatty = isatty(2);
#ifdef MSW
if (GetCurrentDirectory(FILENAME_MAX, cwd) == 0)
strcpy(cwd, ".");
if (GetCurrentDirectory(FILENAME_MAX, cwd) == 0)
strcpy(cwd, ".");
#endif
#ifdef HAVE_UNISTD_H
if (!getcwd(cwd, FILENAME_MAX))
strcpy(cwd, ".");
if (!getcwd(cwd, FILENAME_MAX))
strcpy(cwd, ".");
#endif
#ifdef MSW
short version = MAKEWORD(2, 0);
......@@ -1272,7 +1322,6 @@ int sys_startgui(const char *guidir)
/* assign server port number */
server.sin_port = htons((unsigned short)portno);
/* name the socket */
while (bind(xsock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
......@@ -1325,7 +1374,8 @@ int sys_startgui(const char *guidir)
/* this glob is needed so the Wish executable can have the same
* filename as the Pd.app, i.e. 'Pd-0.42-3.app' should have a Wish
* executable called 'Pd-0.42-3.app/Contents/MacOS/Pd-0.42-3' */
sprintf(embed_glob, "%s/../../MacOS/Pd*", guidir);
// sprintf(embed_glob, "%s/../../MacOS/Pd*", guidir);
sprintf(embed_glob, "%s/../../MacOS/nwjs", guidir);
glob_buffer.gl_matchc = 1; /* we only need one match */
glob(embed_glob, GLOB_LIMIT, NULL, &glob_buffer);
if (glob_buffer.gl_pathc > 0) {
......@@ -1342,37 +1392,74 @@ int sys_startgui(const char *guidir)
break;
}
sprintf(cmdbuf,"\"%s\" %s/pd.tk %d\n",wish_paths[i],guidir,portno);
char data_dir_flag[MAXPDSTRING];
set_datadir(data_dir_flag, sys_unique, portno);
/* Make a copy in case the user wants to change to the repo
dir while developing... */
char guidir2[MAXPDSTRING];
/* Let's go ahead and quote the path in case there are spaces
in it. This won't happen on a sane Linux/BSD setup. But it
will happen under Windows, so we quote here, too, for
the sake of consistency. */
strcpy(guidir2, "\"");
strcat(guidir2, guidir);
strcat(guidir2, "\"");
/* Uncomment the following line if you want to
use the nw binary and GUI code from your local
copy of the Purr Data repo. (Make sure to run
tar_em_up.sh first to fetch the nw binary.) */
//strcpy(guidir2, "\"/home/grieg/purr-data/pd/nw\"");
sprintf(cmdbuf,
"\"%s\" %s %s "
"%d localhost %s %s " X_SPECIFIER,
wish_paths[i],
data_dir_flag,
guidir2,
portno,
(sys_k12_mode ? "pd-l2ork-k12" : "pd-l2ork"),
guidir2,