aboutsummaryrefslogtreecommitdiff
path: root/streamout13~.c
diff options
context:
space:
mode:
Diffstat (limited to 'streamout13~.c')
-rw-r--r--streamout13~.c382
1 files changed, 382 insertions, 0 deletions
diff --git a/streamout13~.c b/streamout13~.c
new file mode 100644
index 0000000..97eb986
--- /dev/null
+++ b/streamout13~.c
@@ -0,0 +1,382 @@
+#include "m_pd.h"
+#include "stream13.h"
+
+#include <sys/types.h>
+#include <string.h>
+#ifdef unix
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define SOCKET_ERROR -1
+#else
+#include <winsock.h>
+#endif
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+
+/* Utility functions */
+
+static void sys_sockerror(char *s)
+{
+#ifdef unix
+ int err = errno;
+#else
+ int err = WSAGetLastError();
+ if (err == 10054) return;
+#endif
+ post("%s: %s (%d)\n", s, strerror(err), err);
+}
+
+
+
+static void sys_closesocket(int fd)
+{
+#ifdef UNIX
+ close(fd);
+#endif
+#ifdef NT
+ closesocket(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]);
+ t_float *in[x->x_n];
+ int i,j,res = 0;
+ int offset = 3;
+ int sent = 0;
+ int length ;
+ char* buf = (char *)(w[2]);
+ short* cibuf;
+ char* bp;
+
+
+
+ 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;j<x->x_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;j<x->x_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;j<x->x_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;j<x->x_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);
+ 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_sethelpsymbol(streamout13_class, gensym("streamio13~"));
+ 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);
+
+}