From fc3d3c0a4f110a23335398c327ac0a4fc949d5cb Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 17 Jun 2002 10:13:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r12, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/ggee/; revision=13 --- signal/streamout~.c | 323 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100755 signal/streamout~.c (limited to 'signal/streamout~.c') diff --git a/signal/streamout~.c b/signal/streamout~.c new file mode 100755 index 0000000..6e76b36 --- /dev/null +++ b/signal/streamout~.c @@ -0,0 +1,323 @@ + +/* (C) Guenter Geiger */ + +#include +#include "stream.h" + +#include +#include +#include +#ifdef unix +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#else +#include +#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); /* shutdown() ?? */ +#endif +#ifdef NT + closesocket(fd); +#endif +} + + +/* ------------------------ streamout~ ----------------------------- */ + + +static t_class *streamout_class; + +typedef struct _streamout +{ + t_object x_obj; + int x_fd; + int x_protocol; + t_tag x_tag; + t_symbol* hostname; + int portno; + short* cbuf; + int nsamples; + int tbufsize; +} t_streamout; + + + +static void streamout_tempbuf(t_streamout *x,int size) { + + if (x->cbuf && x->tbufsize) freebytes(x->cbuf,x->tbufsize); + x->tbufsize=size; + if (!x->cbuf) + x->cbuf = getbytes(size*sizeof(short)); + else + x->cbuf = resizebytes(x->cbuf,x->nsamples*sizeof(short),size*sizeof(short)); + x->nsamples = size; +} + + + +static void streamout_disconnect(t_streamout *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 streamout_connect(t_streamout *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; + x->x_tag.count = 0; + + + if (x->x_fd >= 0) + { + post("streamout~: already connected"); + return; + } + + /* create a socket */ + + sockfd = socket(AF_INET, x->x_protocol, 0); + if (sockfd < 0) + { + post("streamout: 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(x->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 t_int *streamout_perform(t_int *w) +{ + t_streamout* x = (t_streamout*) (w[1]); + t_float *in = (t_float *)(w[2]); + char* bp; + int n = (int)(w[3]); + int length = n*SF_SIZEOF(x->x_tag.format); + int sent = 0; + + if (n != x->nsamples) + streamout_tempbuf(x,n); + + x->x_tag.framesize=length; + x->x_tag.count++; + /* format the buffer */ + bp = (char*)in; + switch (x->x_tag.format) { + case SF_16BIT: { + short* cibuf =(short*) x->cbuf; + bp = (char*) x->cbuf; + while (n--) + *cibuf++ = (short) 32767.0 * *in++; + break; + } + case SF_8BIT: { + unsigned char* cbuf = (char*) x->cbuf; + bp = (char*) x->cbuf; + while (n--) + *cbuf++ = (unsigned char)(128. * (1.0 + *in++)); + break; + } + default: + break; + } + + if (x->x_fd > 0) { + /* send the format tag */ + +#ifdef unix + if (send(x->x_fd,(char*)&x->x_tag,sizeof(t_tag),/*MSG_DONTWAIT|*/MSG_NOSIGNAL) < 0) +#else + if (send(x->x_fd,(char*)&x->x_tag,sizeof(t_tag),0) < 0) +#endif + { + sys_sockerror("streamout"); + streamout_disconnect(x); + return (w+4); + } + + /* send the buffer */ + + for (sent = 0; sent < length;) { + int res = 0; +#ifdef unix + res = send(x->x_fd, bp, length-sent, /*MSG_DONTWAIT|*/MSG_NOSIGNAL); +#else + res = send(x->x_fd, bp, length-sent, 0); +#endif + if (res <= 0) + { + sys_sockerror("streamout"); + streamout_disconnect(x); + break; + } + else + { + sent += res; + bp += res; + } + } + } + return (w+4); +} + + + +static void streamout_dsp(t_streamout *x, t_signal **sp) +{ + dsp_add(streamout_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + + + +static void streamout_format(t_streamout *x,t_symbol* form) +{ + if (!strncmp(form->s_name,"float",5)) + x->x_tag.format = (int) SF_FLOAT; + + if (!strncmp(form->s_name,"16bit",5)) + x->x_tag.format = (int) SF_16BIT; + + if (!strncmp(form->s_name,"8bit",4)) + x->x_tag.format = (int) SF_8BIT; + + + post ("format set to %s", form->s_name); +} + + + +static void streamout_host(t_streamout *x,t_symbol* host) +{ + if (host != &s_) + x->hostname = host; + + if (x->x_fd >= 0) { + streamout_connect(x,x->hostname,(float) x->portno); + } +} + + + + +static void streamout_float(t_streamout* x,t_float arg) +{ + if (arg == 0.0) + streamout_disconnect(x); + else + streamout_connect(x,x->hostname,(float) x->portno); +} + + + +static void *streamout_new(t_symbol* prot) +{ + t_streamout *x = (t_streamout *)pd_new(streamout_class); + outlet_new(&x->x_obj, &s_float); + + x->hostname = gensym("localhost"); + x->portno = 3000; + x->x_fd = -1; + x->x_protocol = SOCK_STREAM; + + if (prot != &s_) + if (!strncmp(prot->s_name,"udp",3)) + x->x_protocol = SOCK_DGRAM; + + x->x_tag.format = SF_FLOAT; + x->x_tag.channels = 1; + x->x_tag.version = 1; + x->cbuf = NULL; + streamout_tempbuf(x,64); + return (x); +} + + + +static void streamout_free(t_streamout* x) +{ + if (x->cbuf && x->tbufsize) freebytes(x->cbuf,x->tbufsize); +} + + + +void streamout_tilde_setup(void) +{ + streamout_class = class_new(gensym("streamout~"), (t_newmethod) streamout_new, (t_method) streamout_free, + sizeof(t_streamout), 0, A_DEFSYM, 0); + class_addmethod(streamout_class, (t_method) streamout_connect, + gensym("connect"), A_SYMBOL, A_DEFFLOAT, 0); + class_addmethod(streamout_class, (t_method) streamout_disconnect, + gensym("disconnect"), 0); + class_addfloat(streamout_class,streamout_float); + class_addmethod(streamout_class, nullfn, gensym("signal"), 0); + class_addmethod(streamout_class, (t_method) streamout_dsp, gensym("dsp"), 0); + class_addmethod(streamout_class, (t_method)streamout_format,gensym("format"),A_SYMBOL,0); + class_addmethod(streamout_class, (t_method)streamout_host,gensym("host"),A_DEFSYM,0); + +} -- cgit v1.2.1