From b0d0df6b50bf3fc62958e32bd3560661dfbc03ba Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Wed, 8 Nov 2017 21:19:55 -0500 Subject: [PATCH] update stdout to Vanilla's eed18dd4b57000d0ebfe9d75b76b0c94609d45de so that it works with pd~ Fix bug in which stdout didn't catch on that it should send to parent pd~ in binary; this was caused by different startup order when pd~ was started with or without GUI (it failed when non-GUI, binary mode). --- pd/extra/stdout/GNUmakefile.am | 34 +++++++--- pd/extra/stdout/stdout-help.pd | 29 ++++++-- pd/extra/stdout/stdout.c | 118 ++++++++++++++++++++++++++++++++- 3 files changed, 162 insertions(+), 19 deletions(-) diff --git a/pd/extra/stdout/GNUmakefile.am b/pd/extra/stdout/GNUmakefile.am index cc2a517f0..72c585ff7 100644 --- a/pd/extra/stdout/GNUmakefile.am +++ b/pd/extra/stdout/GNUmakefile.am @@ -1,28 +1,40 @@ -## Makefile.am -- Process this file with automake to produce Makefile.in +######################################### +##### Defaults & Paths ##### NAME=stdout external_LTLIBRARIES = stdout.la -SOURCES = stdout.c -PATCHES = stdout-help.pd +SOURCES = stdout.c +PATCHES = stdout-help.pd OTHERDATA = -############################### +EXTRA_DIST = makefile + +######################################### +##### 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@ diff --git a/pd/extra/stdout/stdout-help.pd b/pd/extra/stdout/stdout-help.pd index 91edbc417..4d7f3ebb4 100644 --- a/pd/extra/stdout/stdout-help.pd +++ b/pd/extra/stdout/stdout-help.pd @@ -1,19 +1,38 @@ -#N canvas 121 60 488 321 12; +#N canvas 124 51 758 493 12; #X msg 126 203 walk the dog; #X msg 117 156 1; #X obj 117 240 stdout; -#X text 269 287 updated for Pd version 0.42; #X obj 14 13 stdout; #X text 67 14 - write messages to standard output; #X msg 122 179 1 2; -#X obj 119 291 pd~; -#X text 44 291 see also:; +#X obj 119 431 pd~; +#X text 44 431 see also:; #X text 34 39 Sends messages to Pd's standard output. This is useful in conjunction with the pd~ object \, which starts a pd sub-process. Messages sent to the sub-process standard output appear on the output of the pd~ object in the owning process. This might also be useful in other situations. Note that there's no corresponding "stdin" object - there seems to be no one canonical way such a thing should act.; +#X msg 256 203 walk the dog; +#X msg 247 156 1; +#X msg 252 179 1 2; +#X text 269 427 updated for Pd version 0.48; +#X obj 247 240 stdout -cr; +#X msg 383 178 100 111 117 98 108 101 32 32 115 112 97 99 101 44 32 +80 100 10, f 32; +#X obj 383 240 stdout -b; +#X text 45 307 special flags:; +#X text 76 332 -cr: omit trailing semicolon in output (like [print]) +; +#X text 79 352 -b \, -binary: binary mode; +#X text 79 392 -nf \, -noflush: do not fflush the output after each +message; +#X text 79 372 -f \, -flush: fflush the output after each message (default +on W32), f 65; #X connect 0 0 2 0; #X connect 1 0 2 0; -#X connect 6 0 2 0; +#X connect 5 0 2 0; +#X connect 9 0 13 0; +#X connect 10 0 13 0; +#X connect 11 0 13 0; +#X connect 14 0 15 0; diff --git a/pd/extra/stdout/stdout.c b/pd/extra/stdout/stdout.c index 5cd52f25c..3798aa44f 100644 --- a/pd/extra/stdout/stdout.c +++ b/pd/extra/stdout/stdout.c @@ -9,20 +9,124 @@ #include <string.h> static t_class *stdout_class; +#define MODE_DEFAULT 0 /* default, FUDI style */ +#define MODE_CR 1 /* newline-terminate messages and omit semicolons */ +#define MODE_BIN 2 /* binary messages supplied bytewise from patch */ +#define MODE_PDTILDE 3 /* binary atoms for subprocess of pd~ object */ + typedef struct _stdout { t_object x_obj; + int x_mode; /* 0=FUDI; 1=printf (no terminating semicolon); -1=binary */ + int x_flush; /* fflush() stdout after each message */ } t_stdout; -static void *stdout_new(t_float fnonrepeat) +static void *stdout_new(t_symbol*s, int argc, t_atom*argv) { t_stdout *x = (t_stdout *)pd_new(stdout_class); + /* for some reason in MS windows we have to flush standard out here - + otherwise these outputs get out of order from the ones from pdsched.c + over in ../pd~. I'm guessing mingw (with its different C runtime + support) will handle this correctly and so am only ifdeffing this on + Microsoft C compiler. It's an efficiency hit, possibly a serious + one. */ +#ifdef _MSC_VER + x->x_flush = 1; +#endif + + while(argc--) + { + s = atom_getsymbol(argv++); + if (gensym("-cr") == s) + { + /* No-semicolon mode */ + x->x_mode = MODE_CR; + } + else if ((gensym("-b") == s) || (gensym("-binary") == s)) + { + /* Binary mode: + no extra characters (semicolons, CR,...) is appended + */ + x->x_mode = MODE_BIN; + } + else if ((gensym("-f") == s) || (gensym("-flush") == s)) + { + x->x_flush = 1; + } + else if ((gensym("-nf") == s) || (gensym("-noflush") == s)) + { + x->x_flush = 0; + } + else if (gensym("") != s) + { + /* unknown mode; ignore it */ + } + } + if (gensym("#pd_binary_stdio")->s_thing) + x->x_mode = MODE_PDTILDE; return (x); } +static void stdout_binary(t_stdout *x, int argc, t_atom *argv) +{ +#define BUFSIZE 65535 + char buf[BUFSIZE]; + int i; + if (argc>BUFSIZE) + argc = BUFSIZE; + for (i=0; i<argc; i++) + ((unsigned char *)buf)[i] = atom_getfloatarg(i, argc, argv); + buf[i>BUFSIZE?BUFSIZE:i] = 0; + fwrite(buf, 1, argc, stdout); + + if (x->x_flush || !argc) + fflush(stdout); +} + +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 void stdout_anything(t_stdout *x, t_symbol *s, int argc, t_atom *argv) { char msgbuf[MAXPDSTRING], *sp, *ep = msgbuf+MAXPDSTRING; + if (x->x_mode == MODE_BIN) + { + if ((gensym("list") == s) || (gensym("float") == s) || + (gensym("bang") == s)) + stdout_binary(x, argc, argv); + else + pd_error(x, + "stdout: only 'list' messages allowed in binary mode (got '%s')", + s->s_name); + return; + } + else if (x->x_mode == MODE_PDTILDE) + { + pd_tilde_putsymbol(s, stdout); + for (; argc--; argv++) + { + if (argv->a_type == A_FLOAT) + pd_tilde_putfloat(argv->a_w.w_float, stdout); + else if (argv->a_type == A_SYMBOL) + pd_tilde_putsymbol(argv->a_w.w_symbol, stdout); + } + putc(A_SEMI, stdout); + if (x->x_flush) + fflush(stdout); + return; + } msgbuf[0] = 0; strncpy(msgbuf, s->s_name, MAXPDSTRING); msgbuf[MAXPDSTRING-1] = 0; @@ -34,7 +138,15 @@ static void stdout_anything(t_stdout *x, t_symbol *s, int argc, t_atom *argv) atom_string(argv++, sp, ep-sp); sp += strlen(sp); } - printf("%s;\n", msgbuf); + switch(x->x_mode) { + case MODE_CR: + printf("%s\n", msgbuf); + break; + default: + printf("%s;\n", msgbuf); + } + if (x->x_flush) + fflush(stdout); } static void stdout_free(t_stdout *x) @@ -45,6 +157,6 @@ static void stdout_free(t_stdout *x) void stdout_setup(void) { stdout_class = class_new(gensym("stdout"), (t_newmethod)stdout_new, - (t_method)stdout_free, sizeof(t_stdout), 0, 0); + (t_method)stdout_free, sizeof(t_stdout), 0, A_GIMME, 0); class_addanything(stdout_class, stdout_anything); } -- GitLab