aboutsummaryrefslogtreecommitdiff
path: root/signal/pipewrite~.c
diff options
context:
space:
mode:
authorGuenter Geiger <ggeiger@users.sourceforge.net>2002-06-17 10:13:57 +0000
committerGuenter Geiger <ggeiger@users.sourceforge.net>2002-06-17 10:13:57 +0000
commitfc3d3c0a4f110a23335398c327ac0a4fc949d5cb (patch)
tree1849d6afbe34cee9cec97bdb2295401f5126870b /signal/pipewrite~.c
This commit was generated by cvs2svn to compensate for changes in r12,svn2git-root
which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/ggee/; revision=13
Diffstat (limited to 'signal/pipewrite~.c')
-rwxr-xr-xsignal/pipewrite~.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/signal/pipewrite~.c b/signal/pipewrite~.c
new file mode 100755
index 0000000..fe332f8
--- /dev/null
+++ b/signal/pipewrite~.c
@@ -0,0 +1,216 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+#include "m_imp.h"
+//#include <m_pd.h>
+#include "g_canvas.h"
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+/*
+ * -------------------------- pipewrite~ -------------------------------
+ */
+
+#define MAX_CHANS 4
+#define BLOCKTIME 0.001
+#define uint32 unsigned int
+#define uint16 unsigned short
+
+static t_class *pipewrite_class;
+
+typedef struct _pipewrite
+{
+ t_object x_obj;
+ t_symbol* filename;
+ int x_file;
+ t_int x_channels;
+ t_int size;
+ t_glist * x_glist;
+ t_int x_blocked;
+ t_int x_blockwarn;
+ short maxval;
+} t_pipewrite;
+
+static void pipewrite_close(t_pipewrite *x)
+{
+ if (x->x_file > 0) {
+ close(x->x_file);
+ }
+ x->x_file = -1;
+ x->size=0;
+}
+
+
+static void pipewrite_open(t_pipewrite *x,t_symbol *filename)
+{
+ char fname[MAXPDSTRING];
+
+ if (filename == &s_) {
+ post("pipewrite: open without filename");
+ return;
+ }
+
+ canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
+ fname, MAXPDSTRING);
+ x->x_blocked = 0;
+ x->filename = filename;
+ x->maxval=0;
+ x->size=0;
+ post("pipewrite: filename = %s",x->filename->s_name);
+
+ pipewrite_close(x);
+
+ if ((x->x_file = open(fname,O_WRONLY | O_NONBLOCK)) < 0)
+ {
+
+ error("can't open pipe %s: ",fname);
+ perror("system says");
+ return;
+ }
+}
+
+static void pipewrite_block(t_pipewrite *x, t_floatarg f)
+{
+ x->x_blockwarn = f;
+}
+
+
+static short out[4*64];
+
+static t_int *pipewrite_perform(t_int *w)
+{
+ t_pipewrite* x = (t_pipewrite*)(w[1]);
+ t_float * in[4];
+ int c = x->x_channels;
+ int i,num,n;
+ short* tout = out;
+ int ret;
+ double timebefore,timeafter;
+ double late;
+ struct sigaction action;
+ struct sigaction oldaction;
+
+
+ if (x->x_file < 0) {
+ pipewrite_open(x,x->filename);
+ }
+
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, &oldaction);
+
+ for (i=0;i < c;i++) {
+ in[i] = (t_float *)(w[2+i]);
+ }
+
+ n = num = (int)(w[2+c]);
+
+ /* loop */
+
+ if (x->x_file >= 0) {
+
+ while (n--) {
+ for (i=0;i<c;i++) {
+ if (*(in[i]) > 1. ) { *(in[i]) = 1. ; }
+ if (*(in[i]) < -1. ) { *(in[i]) = -1. ; }
+ *tout++ = (*(in[i])++ * 32768.);
+ }
+ }
+
+ timebefore = sys_getrealtime();
+ if ((ret = write(x->x_file,out,sizeof(short)*num*c)) < sizeof(short)*num*c) {
+ post("pipewrite: short write %d",ret);
+
+ }
+
+ timeafter = sys_getrealtime();
+ late = timeafter - timebefore;
+ x->size +=ret;
+ /* OK, we let only 10 ms block here */
+ if (late > BLOCKTIME && x->x_blockwarn) {
+ x->x_blocked++;
+ if (x->x_blocked > x->x_blockwarn) {
+ x->x_blocked=0;
+/* post("maximum blockcount %d reached",x->x_blockwarn); */
+ }
+ }
+ }
+
+ sigaction(SIGPIPE, &oldaction, NULL);
+
+ return (w+3+c);
+}
+
+
+
+static void pipewrite_dsp(t_pipewrite *x, t_signal **sp)
+{
+ switch (x->x_channels) {
+ case 1:
+ dsp_add(pipewrite_perform, 3, x, sp[0]->s_vec,
+ sp[0]->s_n);
+ break;
+ case 2:
+ dsp_add(pipewrite_perform, 4, x, sp[0]->s_vec,
+ sp[1]->s_vec, sp[0]->s_n);
+ break;
+ case 4:
+ dsp_add(pipewrite_perform, 6, x, sp[0]->s_vec,
+ sp[1]->s_vec,
+ sp[2]->s_vec,
+ sp[3]->s_vec,
+ sp[0]->s_n);
+ break;
+ }
+}
+
+static void pipewrite_free(t_pipewrite* x)
+{
+ pipewrite_close(x);
+}
+
+
+static void *pipewrite_new(t_symbol* name,t_floatarg chan)
+{
+ t_pipewrite *x = (t_pipewrite *)pd_new(pipewrite_class);
+ t_int c = chan;
+
+ if (c<1 || c > MAX_CHANS) c = 1;
+
+ x->x_glist = (t_glist*) canvas_getcurrent();
+ x->x_channels = c--;
+ post("channels:%d",x->x_channels);
+ x->x_file=0;
+ x->x_blocked = 0;
+ x->x_blockwarn = 10;
+ while (c--) {
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ }
+
+ if (name && name != &s_) { /* start the pipe */
+ pipewrite_open(x,name);
+ }
+
+ return (x);
+}
+
+void pipewrite_tilde_setup(void)
+{
+ pipewrite_class = class_new(gensym("pipewrite~"), (t_newmethod)pipewrite_new, (t_method)pipewrite_free,
+ sizeof(t_pipewrite), 0,A_DEFSYM,A_DEFFLOAT,A_NULL);
+ class_addmethod(pipewrite_class,nullfn,gensym("signal"), 0);
+ class_addmethod(pipewrite_class, (t_method) pipewrite_dsp, gensym("dsp"), 0);
+ class_addmethod(pipewrite_class, (t_method) pipewrite_open, gensym("open"), A_SYMBOL,A_NULL);
+ class_addmethod(pipewrite_class, (t_method) pipewrite_close, gensym("close"), 0);
+ class_addmethod(pipewrite_class, (t_method)pipewrite_block,gensym("block"),A_DEFFLOAT,0);
+
+}