#include "m_pd.h" #include "stream13.h" #include #include #ifdef _WIN32 #include #else #include #include #include #include #include #define SOCKET_ERROR -1 #endif #ifdef __APPLE__ #include #endif /* these pragmas are only used for MSVC, not MinGW or Cygwin */ #ifdef _MSC_VER #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif /* Utility functions */ static void sys_sockerror(char *s) { #ifdef _WIN32 int err = WSAGetLastError(); if (err == 10054) return; #else int err = errno; #endif post("%s: %s (%d)\n", s, strerror(err), err); } static void sys_closesocket(int fd) { #ifdef _WIN32 closesocket(fd); #else close(fd); #endif } /* ------------------------ streamout13~ ----------------------------- */ /* #define A1 (4 * (3.14159265/2)) #define A3 (64 * (2.5 - 3.14159265)) #define A5 (1024 * ((3.14159265/2) - 1.5)) */ static t_class *streamout13_class; typedef struct _streamout13 { t_object x_obj; int x_fd; int x_protocol; int x_format; int x_realformat; t_symbol* hostname; int portno; int x_n; short* cbuf; int nsamples; int blockspersend; int blockssincesend; int newblockspersend; } t_streamout13; static void streamout13_connect(t_streamout13 *x, t_symbol *hostname, t_floatarg fportno) { struct sockaddr_in server; struct hostent *hp; int sockfd; int portno = fportno; x->hostname = hostname; x->portno = (int) fportno; if (x->x_fd >= 0) { error("streamout13_connect: already connected - reconnecting"); sys_closesocket(x->x_fd); x->x_fd = -1; outlet_float(x->x_obj.ob_outlet, 0); } /* create a socket */ sockfd = socket(AF_INET, x->x_protocol, 0); if (sockfd < 0) { post("streamout13: Connection to %s on port %d failed",hostname->s_name,portno); sys_sockerror("socket"); return; } /* connect socket using hostname provided in command line */ server.sin_family = AF_INET; hp = gethostbyname(hostname->s_name); if (hp == 0) { post("bad host?\n"); return; } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); /* assign client port number */ server.sin_port = htons((u_short)portno); /* try to connect. LATER make a separate thread to do this because it might block */ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { sys_sockerror("connecting stream socket"); sys_closesocket(sockfd); return; } post("connected host %s on port %d",hostname->s_name, portno); x->x_fd = sockfd; outlet_float(x->x_obj.ob_outlet, 1); } static void streamout13_disconnect(t_streamout13 *x) { if (x->x_fd >= 0) { sys_closesocket(x->x_fd); x->x_fd = -1; outlet_float(x->x_obj.ob_outlet, 0); } } static void streamout13_tempbuf(t_streamout13 *x,int size) { int fullsize = size * x->x_n; if (!x->cbuf) x->cbuf = getbytes(fullsize*sizeof(t_float)*x->blockspersend+4); else x->cbuf = resizebytes(x->cbuf,x->nsamples*sizeof(short),fullsize*sizeof(t_float)*x->blockspersend+4); x->nsamples = size; x->blockssincesend=0; } static t_int *streamout13_perform(t_int *w) { t_streamout13* x = (t_streamout13*) (w[1]); int n = (int)(w[2]); int i,j,res = 0; int offset = 3; int sent = 0; int length ; char* buf = (char *)(w[2]); short* cibuf; char* bp; #ifndef _WIN32 t_float *in[x->x_n]; #else t_float** in = (t_float**) malloc(x->x_n * sizeof(t_float*)); #endif for (i=0;i < x->x_n;i++) { in[i] = (t_float *)(w[offset+i]); } if (x->x_fd > 0){ if (n != x->nsamples) streamout13_tempbuf(x,n); /* format the buffer */ /* cibuf = x->cbuf + x->blockssincesend * n * x->x_n + 2; while (n--){ for (j=0;jx_n;j++){ *cibuf++ = (short) 32767.0 * *(in[j]++); } } */ switch (x->x_format) { case SF_FLOAT:{ t_float* fbuf = (t_float*) x->cbuf + x->blockssincesend * n * x->x_n + 1; while (n--){ for (j=0;jx_n;j++){ *fbuf++ = *(in[j]++); } } break; } case SF_16BIT: { short* sbuf =(short*) x->cbuf + x->blockssincesend * n * x->x_n + 2; /*2 extra bytes for format & grain */ while (n--){ for (j=0;jx_n;j++){ *sbuf++ = (short) 32767.0 * *(in[j]++); } } break; } case SF_8BIT: { // signed char* cbuf = (signed char*) ibuf; signed char* cbuf = (signed char*) x->cbuf + x->blockssincesend * n * x->x_n + 4; while (n--) for (j=0;jx_n;j++){ *cbuf++ = (127.0 * *in[j]++); } } break; default: break; } if (!(x->blockssincesend < x->blockspersend - 1)){ x->blockssincesend=0; if (x->x_realformat !=x->x_format){ x->x_realformat = x->x_format; x->blockspersend = (int) (x->blockspersend * 4 / SF_SIZEOF(x->x_format)) ; x->nsamples=0; // post ("formatchange:%d",x->x_format); } if (x->blockspersend != (int) (x->newblockspersend * 4 / SF_SIZEOF(x->x_realformat)) ){ x->blockspersend = (int) (x->newblockspersend * 4 / SF_SIZEOF(x->x_realformat) ) ; x->nsamples=0; // post ("grainchange:%d",x->blockspersend); } cibuf=x->cbuf; *cibuf=(short)x->x_realformat; // *x->cbuf=(short)x->x_realformat; cibuf=x->cbuf + 1; *cibuf=x->blockspersend; // post ("out:cibuf:%d",*cibuf); /* send the buffer */ length = x->nsamples * x->x_n * x->blockspersend * SF_SIZEOF(x->x_realformat) + 4; // outlet_float(x->x_out2,length); // post ("out - length:%d",length); for (bp = buf, sent = 0; sent < length;) { res = send(x->x_fd, (char*) x->cbuf, length - sent , 0); if (res <= 0) { sys_sockerror("streamout13~-error"); streamout13_disconnect(x); break; } else { sent += res; bp += res; } } }else{ x->blockssincesend++; } } // post ("b-s-s:%d, length:%d, last:%d, prev:%d",x->blockssincesend,length,*cibuf,prev); #ifdef _WIN32 free(in); #endif return (w + 2 + i * 2); } static void streamout13_dsp(t_streamout13 *x, t_signal **sp) { /* dsp_add(streamout13_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); */ int i; t_int** myvec = getbytes(sizeof(t_int)*(x->x_n + 3)); myvec[0] = (t_int*)x; myvec[1] = (t_int*)sp[0]->s_n; for (i=0;i < x->x_n/*+1*/;i++) myvec[2 + i] = (t_int*)sp[i]->s_vec; dsp_addv(streamout13_perform, x->x_n + 3, (t_int*)myvec); freebytes(myvec,sizeof(t_int)*(x->x_n + 3)); } static void streamout13_grain(t_streamout13 *x,t_floatarg grain) { if ((grain > 0) && (grain < 24)){ x->newblockspersend=(int) grain; post ("streamout13~:grainsize set to %d blocks",(int) grain); } } static void streamout13_format(t_streamout13 *x,t_symbol* form) { if (!strncmp(form->s_name,"float",5)) x->x_format = (int) SF_FLOAT; if (!strncmp(form->s_name,"16bit",5)) x->x_format = (int) SF_16BIT; if (!strncmp(form->s_name,"8bit",4)) x->x_format = (int) SF_8BIT; post ("streamout13~:format set to %s", form->s_name); } static void streamout13_host(t_streamout13 *x,t_symbol* host) { if (host != &s_){ x->hostname = host; if (x->x_fd >= 0) { streamout13_disconnect(x); streamout13_connect(x,x->hostname,(float) x->portno); } } } static void streamout13_float(t_streamout13* x,t_float arg) { if (arg == 0.0) streamout13_disconnect(x); else streamout13_connect(x,x->hostname,(float) x->portno); } static void *streamout13_new(t_symbol* hostname,t_floatarg portno,t_floatarg xn) { int i; t_streamout13 *x = (t_streamout13 *)pd_new(streamout13_class); outlet_new(&x->x_obj, &s_float); // x->x_out2 = outlet_new(&x->x_obj, &s_float); if (hostname == &s_) x->hostname = gensym("localhost"); else x->hostname = hostname; if (portno == 0.0) x->portno = 3000; else x->portno = portno; if (xn < 1) x->x_n = 1; else x->x_n = xn; for (i = 0 ;i < x->x_n - 1;i++){ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); /* post("creating ~input nr:%d",i);*/ } x->x_fd = -1; x->x_protocol = SOCK_DGRAM; x->x_format = SF_16BIT; x->x_realformat = SF_16BIT; x->cbuf = NULL; x->blockspersend=16; x->newblockspersend=8; x->blockssincesend=0; streamout13_tempbuf(x,64); return (x); } void streamout13_setup(void) { streamout13_class = class_new(gensym("streamout13~"), (t_newmethod) streamout13_new, 0, sizeof(t_streamout13), 0, A_DEFSYM, A_DEFFLOAT,A_DEFFLOAT, 0); class_addmethod(streamout13_class, (t_method) streamout13_connect,gensym("connect"), A_SYMBOL, A_DEFFLOAT, 0); class_addmethod(streamout13_class, (t_method) streamout13_disconnect, gensym("disconnect"), 0); class_addfloat(streamout13_class,streamout13_float); class_addmethod(streamout13_class, nullfn, gensym("signal"), 0); class_addmethod(streamout13_class, (t_method)streamout13_format,gensym("format"),A_SYMBOL,0); class_addmethod(streamout13_class, (t_method)streamout13_grain,gensym("grain"),A_DEFFLOAT,0); class_addmethod(streamout13_class, (t_method) streamout13_dsp, gensym("dsp"), 0); class_addmethod(streamout13_class, (t_method)streamout13_host,gensym("host"),A_DEFSYM,0); } void streamout13_tilde_setup() { streamout13_setup(); }