aboutsummaryrefslogtreecommitdiff
path: root/popen.c
diff options
context:
space:
mode:
Diffstat (limited to 'popen.c')
-rw-r--r--popen.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/popen.c b/popen.c
new file mode 100644
index 0000000..c97a17c
--- /dev/null
+++ b/popen.c
@@ -0,0 +1,211 @@
+/*
+Copyright (C) 2002 Antoine Rousseau
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "m_pd.h"
+#include "s_stuff.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#define BUFSIZE 4096
+
+typedef struct popen
+{
+ t_object x_obj;
+ FILE *x_file;
+ char x_data[BUFSIZE];
+ int x_count;
+ int x_ropened;
+ t_outlet *x_msgout;
+} t_popen;
+
+t_class *popen_class;
+static t_binbuf *inbinbuf;
+
+
+static void *popen_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_popen *x;
+
+ x = (t_popen *)pd_new(popen_class);
+
+ x->x_file = NULL;
+ x->x_count=0;
+ x->x_msgout = outlet_new(&x->x_obj, &s_anything);
+ x->x_ropened=0;
+ return (x);
+}
+
+static void popen_close(t_popen *x)
+{
+ if(x->x_ropened) {
+ sys_rmpollfn(fileno(x->x_file));
+ //fflush(x->x_file);
+ }
+ if(x->x_file) pclose(x->x_file);
+ x->x_file=0;
+ x->x_ropened=0;
+}
+
+static void popen_ff(t_popen *x)
+{
+
+}
+
+static void popen_open(t_popen *x, t_symbol *s,int argc, t_atom *argv)
+{
+ char cmd[512],*text;
+ int cmd_len;
+
+ t_binbuf *bb=binbuf_new();
+
+ popen_close(x);
+
+ //post("argc=%d",argc);
+ //post("argv[0]=%s",atom_getsymbol(&argv[0])->s_name);
+
+ binbuf_add(bb,argc,argv);
+ binbuf_gettext(bb, &text,&cmd_len);
+ binbuf_free(bb);
+
+ strncpy(cmd,text,cmd_len);
+ cmd[cmd_len]=0;
+ //post("cmd=%s",cmd);
+
+ x->x_file=popen(cmd,"w");
+
+}
+
+static void popen_list(t_popen *x, t_symbol *s,
+ int argc, t_atom *argv)
+{
+ t_binbuf *bb;
+ char *buf;
+ int l;
+
+ if(!x->x_file) return;
+
+ bb=binbuf_new();
+ binbuf_add(bb,argc,argv);
+ //binbuf_print(bb);
+ binbuf_gettext(bb, &buf,&l);
+ buf[l]=0;
+
+ //printf("popen list: %s\n",buf);
+ fprintf(x->x_file,"%s\n",buf);fflush(x->x_file);
+
+ freebytes(buf,l);
+ binbuf_free(bb);
+}
+
+static void popen_out(t_popen *x, t_binbuf *b)
+{
+ t_atom messbuf[1024];
+ 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, "popen: got dollar sign in message");
+ goto nodice;
+ }
+ if (at[msg].a_type == A_FLOAT)
+ {
+ if (emsg > msg + 1)
+ outlet_list(x->x_msgout, 0, emsg-msg, at + msg);
+ else outlet_float(x->x_msgout, at[msg].a_w.w_float);
+ }
+ else if (at[msg].a_type == A_SYMBOL)
+ outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
+ emsg-msg-1, at + msg + 1);
+ }
+ nodice:
+ msg = emsg + 1;
+ }
+}
+
+static void popen_read(t_popen *x,int fd)
+{
+ int len,i=0;
+ unsigned char b;
+ unsigned char buffer[BUFSIZE];
+
+ if((len=read(fd,buffer,BUFSIZE))> 0){
+
+ for(i=0;i<len;i++){
+ if(x->x_count>=BUFSIZE) x->x_count=0;
+ x->x_data[x->x_count++]=buffer[i];
+ if(buffer[i]==';') {
+ binbuf_text(inbinbuf, x->x_data, x->x_count);
+ x->x_count=0;
+ popen_out(x,inbinbuf);
+ }
+ }
+ }
+}
+
+static void popen_ropen(t_popen *x, t_symbol *s,int argc, t_atom *argv)
+{
+ char cmd[512],*text;
+ int cmd_len;
+
+ t_binbuf *bb=binbuf_new();
+
+ popen_close(x);
+
+ //post("argc=%d",argc);
+ //post("argv[0]=%s",atom_getsymbol(&argv[0])->s_name);
+
+ binbuf_add(bb,argc,argv);
+ binbuf_gettext(bb, &text,&cmd_len);
+ binbuf_free(bb);
+
+ strncpy(cmd,text,cmd_len);
+ cmd[cmd_len]=0;
+ //post("cmd=%s",cmd);
+
+ x->x_file=popen(cmd,"r");
+ sys_addpollfn(fileno(x->x_file),(t_fdpollfn)popen_read,(void*)x);
+ x->x_ropened=1;
+}
+
+void popen_setup(void )
+{
+ inbinbuf = binbuf_new();
+ popen_class = class_new(gensym("popen"), (t_newmethod)popen_new,
+ (t_method)popen_close,sizeof(t_popen), 0, A_GIMME, 0);
+ class_addmethod(popen_class, (t_method)popen_close,
+ gensym("close"), 0);
+ class_addmethod(popen_class, (t_method)popen_open,
+ gensym("open"), A_GIMME, 0);
+ class_addmethod(popen_class, (t_method)popen_ropen,
+ gensym("ropen"), A_GIMME, 0);
+ class_addlist(popen_class, popen_list);
+
+}
+