yes, I am using netsend/receive, but the program on the other end, piping the pdreceive into the program and forwarding the output via pdsend back to PD, needs to be started. If this were possible from shell, or otherwise from inside PD, then I could have small units that started the piping chain within the PD patch rather than having to start it myself from the command line.
i've made a little test script ( here attached ) that does the lauching of pdreceive and then communicates with pd.
it DOES stay alive and the problem is rather that the process is not destroyed when i destroy the shell object, that's why <defunct> processes appear ( the father ( shell object ) is dead and the script is still alive ).
then you cannot launch a new instance of your script if the former one holds an exclusive ressource ( like a port number ).
in my example, this luckily works but this is surely unclean...
cheers,
yves
6 lines of codes were added to shell.c to remove all these zombies.
about some definitions :
a zombie is a process that wants to terminate but cannot warn its dead father, so it is kept in system tables endlessly.
to clean up properly, the father's got to wait the ending of its child before exiting.
cheers,
yves:
Yves Degoyon wrote:
yes, I am using netsend/receive, but the program on the other end, piping the pdreceive into the program and forwarding the output via pdsend back to PD, needs to be started. If this were possible from shell, or otherwise from inside PD, then I could have small units that started the piping chain within the PD patch rather than having to start it myself from the command line.
i've made a little test script ( here attached ) that does the lauching of pdreceive and then communicates with pd.
it DOES stay alive and the problem is rather that the process is not destroyed when i destroy the shell object, that's why <defunct> processes appear ( the father ( shell object ) is dead and the script is still alive ).
then you cannot launch a new instance of your script if the former one holds an exclusive ressource ( like a port number ).
in my example, this luckily works but this is surely unclean...
cheers,
yves
/* (C) Guenter Geiger geiger@epy.co.at */
#include <m_pd.h> #ifdef NT #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif
#include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <signal.h>
/* ------------------------ shell ----------------------------- */
#define INBUFSIZE 1024
static t_class *shell_class;
typedef struct _shell { t_object x_obj; int x_echo; char *sr_inbuf; int sr_inhead; int sr_intail; void* x_binbuf; int fdpipe[2]; int pid; } t_shell;
void shell_bang(t_shell *x) { post("shell : bang"); }
#if 1 static void shell_doit(void *z, t_binbuf *b) { t_atom messbuf[1024]; t_shell *x = (t_shell *)z; int msg, natom = binbuf_getnatom(b); t_atom *at = binbuf_getvec(b);
for (msg = 0; msg < natom;)
{
int emsg;
for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
&& at[emsg].a_type != A_SEMI; emsg++)
;
if (emsg > msg)
{
int i;
for (i = msg; i < emsg; i++)
if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
{
pd_error(x, "netreceive: got dollar sign in message");
goto nodice;
}
if (at[msg].a_type == A_FLOAT)
{
if (emsg > msg + 1)
outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
}
else if (at[msg].a_type == A_SYMBOL)
outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
emsg-msg-1, at + msg + 1);
}
nodice:
msg = emsg + 1;
}
}
void shell_read(t_shell *x, int fd) { char buf[INBUFSIZE]; t_binbuf* bbuf = binbuf_new(); int i; int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); int ret;
ret = read(fd, buf,INBUFSIZE);
buf[ret] = '\0';
for (i=0;i<ret;i++)
if (buf[i] == '\n') buf[i] = ';';
if (ret < 0)
{
error("shell: pipe read error");
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else if (ret == 0)
{
post("EOF on socket %d\n", fd);
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else
{
int natom;
t_atom *at;
binbuf_text(bbuf, buf, strlen(buf));
natom = binbuf_getnatom(bbuf);
at = binbuf_getvec(bbuf);
shell_doit(x,bbuf);
}
binbuf_free(bbuf);
}
#endif
static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at) { int i; char* argv[20];
argv[0] = s->s_name;
if (x->fdpipe[0] != -1) {
close(x->fdpipe[0]);
close(x->fdpipe[1]);
sys_rmpollfn(x->fdpipe[0]);
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
kill(x->pid,SIGKILL);
}
for (i=1;i<=ac;i++) {
argv[i] = atom_getsymbolarg(i-1,ac,at)->s_name;
/* post("argument %s",argv[i]);*/
}
argv[i] = 0;
if (pipe(x->fdpipe) < 0)
error("unable to create pipe");
sys_addpollfn(x->fdpipe[0],shell_read,x);
if (!(x->pid = fork())) {
/* reassign stdout */
dup2(x->fdpipe[1],1);
execvp(s->s_name,argv);
exit(0);
}
if (x->x_echo)
outlet_anything(x->x_obj.ob_outlet, s, ac, at);
}
static void shell_free(t_shell* x) { t_int status;
post( "shell : cleaning up...( pid=%d )", x->pid );
if ( kill ( x->pid, SIGKILL ) == -1 )
{
post( "shell : couldn't not kill child on exit. some zombies ????" );
perror( "kill" );
}
if ( waitpid( x->pid, &status, 0 ) == -1 )
{
post( "shell : abnormal terminsation" );
perror( "waitpid" );
}
binbuf_free(x->x_binbuf);
post( "shell : done." );
}
static void *shell_new(void) { t_shell *x = (t_shell *)pd_new(shell_class);
x->x_echo = 0;
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
x->sr_inhead = x->sr_intail = 0;
if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
x->x_binbuf = binbuf_new();
outlet_new(&x->x_obj, &s_list);
return (x);
}
void shell_setup(void) { shell_class = class_new(gensym("shell"), (t_newmethod)shell_new, (t_method)shell_free, sizeof(t_shell), 0, 0); class_addbang(shell_class,shell_bang); class_addanything(shell_class, shell_anything); }
yeah, me again, fixed another problem in shell :
it could not take float arguments ( like a port number ) and i needed it.
yves
Yves Degoyon wrote:
6 lines of codes were added to shell.c to remove all these zombies.
about some definitions :
a zombie is a process that wants to terminate but cannot warn its dead father, so it is kept in system tables endlessly.
to clean up properly, the father's got to wait the ending of its child before exiting.
cheers,
yves:
/* (C) Guenter Geiger geiger@epy.co.at */
#include <m_pd.h> #ifdef NT #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif
#include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <signal.h>
/* ------------------------ shell ----------------------------- */
#define INBUFSIZE 1024
static t_class *shell_class;
typedef struct _shell { t_object x_obj; int x_echo; char *sr_inbuf; int sr_inhead; int sr_intail; void* x_binbuf; int fdpipe[2]; int pid; } t_shell;
void shell_bang(t_shell *x) { post("shell : bang"); }
#if 1 static void shell_doit(void *z, t_binbuf *b) { t_atom messbuf[1024]; t_shell *x = (t_shell *)z; int msg, natom = binbuf_getnatom(b); t_atom *at = binbuf_getvec(b);
for (msg = 0; msg < natom;)
{
int emsg;
for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
&& at[emsg].a_type != A_SEMI; emsg++)
;
if (emsg > msg)
{
int i;
for (i = msg; i < emsg; i++)
if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
{
pd_error(x, "netreceive: got dollar sign in message");
goto nodice;
}
if (at[msg].a_type == A_FLOAT)
{
if (emsg > msg + 1)
outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
}
else if (at[msg].a_type == A_SYMBOL)
outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
emsg-msg-1, at + msg + 1);
}
nodice:
msg = emsg + 1;
}
}
void shell_read(t_shell *x, int fd) { char buf[INBUFSIZE]; t_binbuf* bbuf = binbuf_new(); int i; int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); int ret;
ret = read(fd, buf,INBUFSIZE);
buf[ret] = '\0';
for (i=0;i<ret;i++)
if (buf[i] == '\n') buf[i] = ';';
if (ret < 0)
{
error("shell: pipe read error");
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else if (ret == 0)
{
post("EOF on socket %d\n", fd);
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else
{
int natom;
t_atom *at;
binbuf_text(bbuf, buf, strlen(buf));
natom = binbuf_getnatom(bbuf);
at = binbuf_getvec(bbuf);
shell_doit(x,bbuf);
}
binbuf_free(bbuf);
}
#endif
static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at) { int i; char* argv[20];
argv[0] = s->s_name;
if (x->fdpipe[0] != -1) {
close(x->fdpipe[0]);
close(x->fdpipe[1]);
sys_rmpollfn(x->fdpipe[0]);
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
kill(x->pid,SIGTERM);
}
for (i=1;i<=ac;i++) {
switch ( at[i-1].a_type )
{
case A_SYMBOL :
argv[i] = at[i-1].a_w.w_symbol;
break;
case A_FLOAT :
argv[i] = (char*)getbytes( 128 );
if ( at[i-1].a_w.w_float == (int) at[i-1].a_w.w_float )
{
sprintf( argv[i], "%d", (int)at[i-1].a_w.w_float );
}
else
{
sprintf( argv[i], "%f", (int)at[i-1].a_w.w_float );
}
break;
default :
post( "shell : unknown argument type : %d...lost", at[i-1].a_type );
break;
}
post("argument %s",argv[i]);
}
argv[i] = 0;
if (pipe(x->fdpipe) < 0)
error("unable to create pipe");
sys_addpollfn(x->fdpipe[0],shell_read,x);
if (!(x->pid = fork())) {
/* reassign stdout */
dup2(x->fdpipe[1],1);
execvp(s->s_name,argv);
exit(0);
}
if (x->x_echo)
outlet_anything(x->x_obj.ob_outlet, s, ac, at);
}
static void shell_free(t_shell* x) { t_int status;
post( "shell : cleaning up...( pid=%d )", x->pid );
if ( kill ( x->pid, SIGKILL ) == -1 )
{
post( "shell : couldn't not kill child on exit. some zombies ????" );
perror( "kill" );
}
usleep( 1000000 );
if ( waitpid( x->pid, &status, 0 ) == -1 )
{
post( "shell : abnormal termination" );
perror( "waitpid" );
}
binbuf_free(x->x_binbuf);
post( "shell : done." );
}
static void *shell_new(void) { t_shell *x = (t_shell *)pd_new(shell_class);
x->x_echo = 0;
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
x->sr_inhead = x->sr_intail = 0;
if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
x->x_binbuf = binbuf_new();
outlet_new(&x->x_obj, &s_list);
return (x);
}
void shell_setup(void) { shell_class = class_new(gensym("shell"), (t_newmethod)shell_new, (t_method)shell_free, sizeof(t_shell), 0, 0); class_addbang(shell_class,shell_bang); class_addanything(shell_class, shell_anything); }
Hi Yves,
this is great, thank you for the patch, I had the zombie thing fixed some days ago, but I think the patch didnt make it to the list and I haven't put a new version of ggee on the web.
Didn't realize the float problem though, ....
There were other things I wanted to add to shell, in order to use it as a general script interpreter within pd, ... like starting a perl script etc. for this it needs communication through shell inlet and the stdio of the scripting process.
Greetings,
Guenter
this is great, thank you for the patch, I had the zombie thing fixed some days ago, but I think the patch didnt make it to the list and I haven't put a new version of ggee on the web.
the "no zombie" version was sent to the dev-list here it is again
lg
e.
/* (C) Guenter Geiger geiger@epy.co.at */
#include <m_pd.h>
#ifdef NT
#pragma warning( disable : 4244 )
#pragma warning( disable : 4305 )
#endif
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
/* ------------------------ shell ----------------------------- */
#define INBUFSIZE 1024
static t_class *shell_class;
typedef struct _shell
{
t_object x_obj;
int x_echo;
char *sr_inbuf;
int sr_inhead;
int sr_intail;
void* x_binbuf;
int fdpipe[2];
int pid;
} t_shell;
static int shell_pid;
void child_handler(int n)
{
int ret;
waitpid(-1,&ret,WNOHANG);
}
void shell_bang(t_shell *x)
{
post("bang");
}
#if 1
static void shell_doit(void *z, t_binbuf *b)
{
t_atom messbuf[1024];
t_shell *x = (t_shell *)z;
int msg, natom = binbuf_getnatom(b);
t_atom *at = binbuf_getvec(b);
for (msg = 0; msg < natom;)
{
int emsg;
for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
&& at[emsg].a_type != A_SEMI; emsg++)
;
if (emsg > msg)
{
int i;
for (i = msg; i < emsg; i++)
if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
{
pd_error(x, "netreceive: got dollar sign in message");
goto nodice;
}
if (at[msg].a_type == A_FLOAT)
{
if (emsg > msg + 1)
outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
}
else if (at[msg].a_type == A_SYMBOL)
outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
emsg-msg-1, at + msg + 1);
}
nodice:
msg = emsg + 1;
}
}
void shell_read(t_shell *x, int fd)
{
char buf[INBUFSIZE];
t_binbuf* bbuf = binbuf_new();
int i;
int readto =
(x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
int ret;
ret = read(fd, buf,INBUFSIZE);
buf[ret] = '\0';
for (i=0;i<ret;i++)
if (buf[i] == '\n') buf[i] = ';';
if (ret < 0)
{
error("shell: pipe read error");
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else if (ret == 0)
{
post("EOF on socket %d\n", fd);
sys_rmpollfn(fd);
x->fdpipe[0] = -1;
close(fd);
return;
}
else
{
int natom;
t_atom *at;
binbuf_text(bbuf, buf, strlen(buf));
natom = binbuf_getnatom(bbuf);
at = binbuf_getvec(bbuf);
shell_doit(x,bbuf);
}
binbuf_free(bbuf);
}
#endif
static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
{
int i;
char* argv[20];
argv[0] = s->s_name;
if (x->fdpipe[0] != -1) {
close(x->fdpipe[0]);
close(x->fdpipe[1]);
sys_rmpollfn(x->fdpipe[0]);
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
kill(x->pid,SIGKILL);
}
for (i=1;i<=ac;i++) {
argv[i] = atom_getsymbolarg(i-1,ac,at)->s_name;
/* post("argument %s",argv[i]);*/
}
argv[i] = 0;
if (pipe(x->fdpipe) < 0)
error("unable to create pipe");
sys_addpollfn(x->fdpipe[0],shell_read,x);
if (!(x->pid = fork())) {
/* reassign stdout */
dup2(x->fdpipe[1],1);
execvp(s->s_name,argv);
exit(0);
}
if (x->x_echo)
outlet_anything(x->x_obj.ob_outlet, s, ac, at);
}
void shell_free(t_shell* x)
{
binbuf_free(x->x_binbuf);
}
static void *shell_new()
{
t_shell *x = (t_shell *)pd_new(shell_class);
x->x_echo = 0;
x->fdpipe[0] = -1;
x->fdpipe[1] = -1;
x->sr_inhead = x->sr_intail = 0;
if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
x->x_binbuf = binbuf_new();
outlet_new(&x->x_obj, &s_list);
return (x);
}
void shell_setup(void)
{
shell_class = class_new(gensym("shell"), (t_newmethod)shell_new,
(t_method)shell_free,sizeof(t_shell), 0,0);
class_addbang(shell_class,shell_bang);
class_addanything(shell_class, shell_anything);
signal(SIGCHLD, child_handler);
}
hi all,
what is dev-list?
pd-devel@iem.kug.ac.at
http://www.iem.at/mailinglists/pd-list/
it was split up a month or two ago or so ...
lg
e
Krzysztof
rat@telecoma.net wrote: ...
the "no zombie" version was sent to the dev-list
hi all! it seems i also missed the split. tried to subscribe to the dev-list & announce-list yesterday, but gut no response :-( d13b
hi all,
what is dev-list?
pd-devel@iem.kug.ac.at
http://www.iem.at/mailinglists/pd-list/
it was split up a month or two ago or so ...
lg
e
Krzysztof
rat@telecoma.net wrote: ...
the "no zombie" version was sent to the dev-list
i also read the msg about splitting as a proposal and not as a fact..
is there anyone posting on dev-list (except erich).
martin
On Mon, 27 May 2002, d wrote:
hi all! it seems i also missed the split. tried to subscribe to the dev-list & announce-list yesterday, but gut no response :-( d13b
hi all,
what is dev-list?
pd-devel@iem.kug.ac.at
http://www.iem.at/mailinglists/pd-list/
it was split up a month or two ago or so ...
lg
e
Krzysztof
rat@telecoma.net wrote: ...
the "no zombie" version was sent to the dev-list
martin pi attacksyour.net/pi
johann strauss gasse 32 | 7 1040 vienna ++43 699 10 44 37 42
sil.at
i also read the msg about splitting as a proposal and not as a fact..
is there anyone posting on dev-list (except erich).
haha :-) , no i m not posting to the dev-list but guenther was posting his shell.c there .
i tried to subscribe some weeks ago but the "list" told me i was already subscribed (i did not do it), so maybe we are all there and thats why we did not notice it (sounds like P.K Dick paranoia :-)
i m sure iohannes can clear this somehow ...
cheers
erich
rat@telecoma.net wrote:
i also read the msg about splitting as a proposal and not as a fact..
is there anyone posting on dev-list (except erich)
haha :-) , no i m not posting to the dev-list but guenther was posting his shell.c there .
i tried to subscribe some weeks ago but the "list" told me i was already subscribed (i did not do it), so maybe we are all there and thats why we did not notice it (sounds like P.K Dick paranoia :-)
i m sure iohannes can clear this somehow ...
ok, i hope i have fixed all the problems now yes ALL pd-list subscribers are allready subscribed to the pd-dev@iem.kug.ac.at and pd-announce@iem.kug.ac.at
however, the lists were sort of down, because i had misconfigured the MTA. should be up now...
mfg.cdsadr IOhannes
cheers
erich
On Mon, 27 May 2002 rat@telecoma.net wrote:
i also read the msg about splitting as a proposal and not as a fact..
is there anyone posting on dev-list (except erich).
haha :-) , no i m not posting to the dev-list but guenther was posting his shell.c there .
yeah, this was kind of a test of the new lists, I realized that it didn't show up in my mailbox, but it was in the list archive or so, then I thought it might be a problem with my mailer --> postponed the problem --> forgot the problem :) (one of my favourite problem solving algorithms ...)
Guenter
geiger@xdv.org wrote:
yeah, this was kind of a test of the new lists, I realized that it didn't show up in my mailbox, but it was in the list archive or so, then I thought it might be a problem with my mailer --> postponed the problem --> forgot the problem :) (one of my favourite problem solving algorithms ...)
Is it open source?
mik
and I tried to subscribe right now, and got "already subscribed"... sme.
----- Original Message ----- From: "d" dieb13@klingt.org To: pd-list@iem.kug.ac.at Sent: Monday, May 27, 2002 10:21 AM Subject: Re: dev-list (was Re: [pd] shell and ongoing processes)
hi all! it seems i also missed the split. tried to subscribe to the dev-list & announce-list yesterday, but gut no response :-( d13b
and I tried to subscribe right now, and got "already subscribed"... sme.
maybe we are on dev-list and do not know ????? :-)
martin
----- Original Message ----- From: "d" dieb13@klingt.org To: pd-list@iem.kug.ac.at Sent: Monday, May 27, 2002 10:21 AM Subject: Re: dev-list (was Re: [pd] shell and ongoing processes)
hi all! it seems i also missed the split. tried to subscribe to the dev-list & announce-list yesterday, but gut no response :-( d13b
martin pi attacksyour.net/pi
johann strauss gasse 32 | 7 1040 vienna ++43 699 10 44 37 42
sil.at
Hi, sme hat gesagt: // sme wrote:
and I tried to subscribe right now, and got "already subscribed"... sme.
I'm as well, without knowing. Of course I want to be on such a list, but I didn't know, that it already started... So what now?
Frank Barknecht _ ______footils.org__
Hi all, i don't really know whether this already exists in some library... it's a Max-like prepend object (not exactly the same but compatible).
Grab it at http://www.parasitaere-kapazitaeten.net/Pd/ext/prepend If you can't find it, wait another day and/or reload your browser cache... the server's IP has been changed.
greetings, Thomas
PS: If you need some help, use the following:
#N canvas 252 279 610 313 12; #X obj 75 62 prepend set; #X msg 76 28 1 2 3; #X msg 221 28 1 2 3; #X obj 223 69 prepend one two; #X msg 284 26 set three four; #X msg 22 182 1 2 3; #X obj 30 228 prepend one two; #X obj 249 230 prepend one two; #X msg 323 188 three four; #X msg 247 189 one; #X text 322 146 same as with set; #X text 322 164 into left inlet; #X text 285 47 set prepend atoms; #X msg 86 183 set 3 4; #X obj 75 103 print; #X obj 223 110 print; #X obj 30 269 print; #X obj 249 271 print; #X msg 20 29 help; #X connect 0 0 14 0; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 15 0; #X connect 4 0 3 0; #X connect 5 0 6 0; #X connect 6 0 16 0; #X connect 7 0 17 0; #X connect 8 0 7 1; #X connect 9 0 7 0; #X connect 13 0 6 0; #X connect 18 0 0 0;
hi Thomas,
thanks, but since it depends on flext, I am not sure it could be included in cyclone (also gpl does not help). Anyway, I think I would like to see yet, if I could limit memory allocation overhead just a bit...
Krzysztof
btw, prepend is part of ggee.
Thomas Grill wrote: ...
i don't really know whether this already exists in some library... it's a Max-like prepend object (not exactly the same but compatible).
thanks, but since it depends on flext, I am not sure it could be included in cyclone (also gpl does not help).
flext is also under the gpl, so that shouldn't be a problem. Anyway....
btw, prepend is part of ggee.
Shame on me, i thought i (some time ago) did a search on pdb without a result?!
Well, go on and use Thomas Musil's since it's smaller for use and possibly better tested.
greetings, Thomas
I read:
flext is also under the gpl, so that shouldn't be a problem.
but from what I gathered the GPL is the problem since pd is licensed under less restricitive terms (kind of BSDish) and cyclone uses the same license.
regards,
x
Hi Krzsysztof,
the thing about prepend brought me to a more general question about cyclone:
How do you deal with objects/features that are not optimally solved in MaxMSP and/or implemented differently in their (equally named) pd counterparts?
For example, the prepend object in Max/MSP can be sent a [set preatom( message, which then makes the object prepend "preatom" to every incoming message. Therefore you can't prepend to a message beginning with "set". In the iemlib2 this is solved in a way that the prepend object is static and can't be changed. In my prepend there's a second inlet to change the prepended atoms (and i cancel the [set preatom( feature for the future).
Therefore, the pd objects do not exactly mimic the Max behavior and patches are not fully portable.. and even worse.. differences may be hard to find.
greetings, Thomas
hi Thomas,
Thomas Grill wrote: ...
How do you deal with objects/features that are not optimally solved in MaxMSP and/or implemented differently in their (equally named) pd counterparts?
the most important thing is to ease the pain of `recycling' (although it will never be painless) -- porting existing max/msp patches to Pd and creating Pd patches ready to be ported to max -- and not to ease the pain of making new patches.
The somewhat less important thing is that there are, indeed, quite useful classes in max/msp, which could be made even more useful by implementing some additional features. If such additional feature does not break max->Pd compatibility, I would be willing to implement it, but then, if someone uses it in a Pd patch, a warning should be printed out about breaking ``backwards compatibility'' (Pd->max).
Speaking of name clashes with Pd counterparts -- this was the subject of a small voting proposed some time ago on pd-list. The poll's results were, basically (but not necessarily accurately), that internal Pd classes need to remain as they are, but it is better for externals to conform, or change the name.
...
For example, the prepend object in Max/MSP can be sent a [set preatom( message, which then makes the object prepend "preatom" to every incoming message. Therefore you can't prepend to a message beginning with "set".
one can always [route]...
...
Well, go on and use Thomas Musil's since it's smaller for use and possibly better tested.
but not fully compatible. Otoh gg's seems to be unfinished -- but I suspect it uses similar memory scheme as max does (stack instead of a heap). I may be wrong, though...
Krzysztof