aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2010-01-13 21:54:30 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2010-01-13 21:54:30 +0000
commit9bfd11451d5fa6512aec0619c3791d66b3b1fcb7 (patch)
tree52c32fbcb706cb0085018de245b8b9e13f177da0
parentfcd21c7b86fa4f48db3b8273465861bfa73a2d1f (diff)
Fixed header files for _WIN32
svn path=/trunk/externals/mrpeach/; revision=12985
-rw-r--r--net/udpreceive~.c1487
-rw-r--r--net/udpsend~.c1306
2 files changed, 1397 insertions, 1396 deletions
diff --git a/net/udpreceive~.c b/net/udpreceive~.c
index 353f1a6..85f9bf1 100644
--- a/net/udpreceive~.c
+++ b/net/udpreceive~.c
@@ -1,189 +1,190 @@
-/* udpreceive~ started 20100110 by Martin Peach based on netreceive~: */
-/* ------------------------ netreceive~ --------------------------------------- */
-/* */
-/* Tilde object to receive uncompressed audio data from netsend~. */
-/* Written by Olaf Matthes <olaf.matthes@gmx.de>. */
-/* Based on streamin~ by Guenter Geiger. */
-/* Get source at http://www.akustische-kunst.org/ */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* See file LICENSE for further informations on licensing terms. */
-/* */
-/* This program 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 General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/* */
-/* Based on PureData by Miller Puckette and others. */
-/* */
-/* This project was commissioned by the Society for Arts and Technology [SAT], */
-/* Montreal, Quebec, Canada, http://www.sat.qc.ca/. */
-/* */
-/* ---------------------------------------------------------------------------- */
-
-
-#include "m_pd.h"
-
-#include "udpsend~.h"
-
-#include <sys/types.h>
-#include <string.h>
-#if defined(UNIX) || defined(unix)
-#include <sys/socket.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#define SOCKET_ERROR -1
-#endif
-#ifdef _WIN32
-#include <winsock.h>
-#endif
-
-#ifndef SOL_IP
-#define SOL_IP IPPROTO_IP
-#endif
-
-#define DEFAULT_AUDIO_BUFFER_FRAMES 16 /* a small circ. buffer for 16 frames */
-#define DEFAULT_AVERAGE_NUMBER 10 /* number of values we store for average history */
-#define DEFAULT_NETWORK_POLLTIME 1 /* interval in ms for polling for input data (Max/MSP only) */
-#define DEFAULT_QUEUE_LENGTH 3 /* min. number of buffers that can be used reliably on your hardware */
-
-#if defined(UNIX) || defined(unix)
-#define CLOSESOCKET(fd) close(fd)
-#endif
-#ifdef _WIN32
-#define CLOSESOCKET(fd) closesocket(fd)
-#endif
-
-/* ------------------------ udpreceive~ ----------------------------- */
-
-typedef struct _udpreceive_tilde
-{
- t_object x_obj;
- t_outlet *x_outlet1;
- t_outlet *x_outlet2;
+/* udpreceive~ started 20100110 by Martin Peach based on netreceive~: */
+/* ------------------------ netreceive~ --------------------------------------- */
+/* */
+/* Tilde object to receive uncompressed audio data from netsend~. */
+/* Written by Olaf Matthes <olaf.matthes@gmx.de>. */
+/* Based on streamin~ by Guenter Geiger. */
+/* Get source at http://www.akustische-kunst.org/ */
+/* */
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* See file LICENSE for further informations on licensing terms. */
+/* */
+/* This program 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 General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/* Based on PureData by Miller Puckette and others. */
+/* */
+/* This project was commissioned by the Society for Arts and Technology [SAT], */
+/* Montreal, Quebec, Canada, http://www.sat.qc.ca/. */
+/* */
+/* ---------------------------------------------------------------------------- */
+
+
+#include "m_pd.h"
+
+#include "udpsend~.h"
+
+#include <sys/types.h>
+#include <string.h>
+#if defined(UNIX) || defined(unix)
+#include <sys/socket.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#define SOCKET_ERROR -1
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h> /* for socklen_t */
+#endif
+
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+
+#define DEFAULT_AUDIO_BUFFER_FRAMES 16 /* a small circ. buffer for 16 frames */
+#define DEFAULT_AVERAGE_NUMBER 10 /* number of values we store for average history */
+#define DEFAULT_NETWORK_POLLTIME 1 /* interval in ms for polling for input data (Max/MSP only) */
+#define DEFAULT_QUEUE_LENGTH 3 /* min. number of buffers that can be used reliably on your hardware */
+
+#if defined(UNIX) || defined(unix)
+#define CLOSESOCKET(fd) close(fd)
+#endif
+#ifdef _WIN32
+#define CLOSESOCKET(fd) closesocket(fd)
+#endif
+
+/* ------------------------ udpreceive~ ----------------------------- */
+
+typedef struct _udpreceive_tilde
+{
+ t_object x_obj;
+ t_outlet *x_outlet1;
+ t_outlet *x_outlet2;
t_outlet *x_addrout;
t_atom x_addrbytes[5];
- int x_socket;
- int x_connectsocket;
- int x_nconnections;
- int x_ndrops;
- int x_tcp;
- t_symbol *x_hostname;
-
- /* buffering */
- int x_framein;
- int x_frameout;
- t_frame x_frames[DEFAULT_AUDIO_BUFFER_FRAMES];
- int x_maxframes;
- long x_framecount;
- int x_blocksize;
- int x_blocksperrecv;
- int x_blockssincerecv;
-
- int x_nbytes;
- int x_counter;
- int x_average[DEFAULT_AVERAGE_NUMBER];
- int x_averagecur;
- int x_underflow;
- int x_overflow;
-
- long x_samplerate;
- int x_noutlets;
- int x_vecsize;
- t_int **x_myvec; /* vector we pass on to the DSP routine */
-} t_udpreceive_tilde;
-
-/* function prototypes */
-static void udpreceive_tilde_closesocket(t_udpreceive_tilde* x);
-static void udpreceive_tilde_reset(t_udpreceive_tilde* x, t_floatarg buffer);
-static void udpreceive_tilde_datapoll(t_udpreceive_tilde *x);
-static void udpreceive_tilde_connectpoll(t_udpreceive_tilde *x);
-static int udpreceive_tilde_createsocket(t_udpreceive_tilde* x, int portno);
-static t_int *udpreceive_tilde_perform(t_int *w);
-static void udpreceive_tilde_dsp(t_udpreceive_tilde *x, t_signal **sp);
-static void udpreceive_tilde_info(t_udpreceive_tilde *x);
-static void *udpreceive_tilde_new(t_floatarg fportno, t_floatarg outlets, t_floatarg blocksize);
-static void udpreceive_tilde_free(t_udpreceive_tilde *x);
-void udpreceive_tilde_setup(void);
-static int udpreceive_tilde_sockerror(char *s);
-static int udpreceive_tilde_setsocketoptions(int sockfd);
-/* these would require to include some headers that are different
- between pd 0.36 and later, so it's easier to do it like this! */
-EXTERN void sys_rmpollfn(int fd);
-EXTERN void sys_addpollfn(int fd, void* fn, void *ptr);
-
-static t_class *udpreceive_tilde_class;
-static t_symbol *ps_format, *ps_channels, *ps_framesize, *ps_overflow, *ps_underflow, *ps_packets,
- *ps_queuesize, *ps_average, *ps_sf_float, *ps_sf_16bit, *ps_sf_8bit,
- *ps_sf_mp3, *ps_sf_aac, *ps_sf_unknown, *ps_bitrate, *ps_hostname, *ps_nothing;
-
-/* remove all pollfunctions and close socket */
-static void udpreceive_tilde_closesocket(t_udpreceive_tilde* x)
-{
- sys_rmpollfn(x->x_socket);
- outlet_float(x->x_outlet1, 0);
- CLOSESOCKET(x->x_socket);
- x->x_socket = -1;
-}
-
-static void udpreceive_tilde_reset(t_udpreceive_tilde* x, t_floatarg buffer)
-{
- int i;
-
- x->x_counter = 0;
- x->x_nbytes = 0;
- x->x_framein = 0;
- x->x_frameout = 0;
- x->x_blockssincerecv = 0;
- x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
-
- for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
- x->x_average[i] = x->x_maxframes;
- x->x_averagecur = 0;
-
+ int x_socket;
+ int x_connectsocket;
+ int x_nconnections;
+ int x_ndrops;
+ int x_tcp;
+ t_symbol *x_hostname;
+
+ /* buffering */
+ int x_framein;
+ int x_frameout;
+ t_frame x_frames[DEFAULT_AUDIO_BUFFER_FRAMES];
+ int x_maxframes;
+ long x_framecount;
+ int x_blocksize;
+ int x_blocksperrecv;
+ int x_blockssincerecv;
+
+ int x_nbytes;
+ int x_counter;
+ int x_average[DEFAULT_AVERAGE_NUMBER];
+ int x_averagecur;
+ int x_underflow;
+ int x_overflow;
+
+ long x_samplerate;
+ int x_noutlets;
+ int x_vecsize;
+ t_int **x_myvec; /* vector we pass on to the DSP routine */
+} t_udpreceive_tilde;
+
+/* function prototypes */
+static void udpreceive_tilde_closesocket(t_udpreceive_tilde* x);
+static void udpreceive_tilde_reset(t_udpreceive_tilde* x, t_floatarg buffer);
+static void udpreceive_tilde_datapoll(t_udpreceive_tilde *x);
+static void udpreceive_tilde_connectpoll(t_udpreceive_tilde *x);
+static int udpreceive_tilde_createsocket(t_udpreceive_tilde* x, int portno);
+static t_int *udpreceive_tilde_perform(t_int *w);
+static void udpreceive_tilde_dsp(t_udpreceive_tilde *x, t_signal **sp);
+static void udpreceive_tilde_info(t_udpreceive_tilde *x);
+static void *udpreceive_tilde_new(t_floatarg fportno, t_floatarg outlets, t_floatarg blocksize);
+static void udpreceive_tilde_free(t_udpreceive_tilde *x);
+void udpreceive_tilde_setup(void);
+static int udpreceive_tilde_sockerror(char *s);
+static int udpreceive_tilde_setsocketoptions(int sockfd);
+/* these would require to include some headers that are different
+ between pd 0.36 and later, so it's easier to do it like this! */
+EXTERN void sys_rmpollfn(int fd);
+EXTERN void sys_addpollfn(int fd, void* fn, void *ptr);
+
+static t_class *udpreceive_tilde_class;
+static t_symbol *ps_format, *ps_channels, *ps_framesize, *ps_overflow, *ps_underflow, *ps_packets,
+ *ps_queuesize, *ps_average, *ps_sf_float, *ps_sf_16bit, *ps_sf_8bit,
+ *ps_sf_mp3, *ps_sf_aac, *ps_sf_unknown, *ps_bitrate, *ps_hostname, *ps_nothing;
+
+/* remove all pollfunctions and close socket */
+static void udpreceive_tilde_closesocket(t_udpreceive_tilde* x)
+{
+ sys_rmpollfn(x->x_socket);
+ outlet_float(x->x_outlet1, 0);
+ CLOSESOCKET(x->x_socket);
+ x->x_socket = -1;
+}
+
+static void udpreceive_tilde_reset(t_udpreceive_tilde* x, t_floatarg buffer)
+{
+ int i;
+
+ x->x_counter = 0;
+ x->x_nbytes = 0;
+ x->x_framein = 0;
+ x->x_frameout = 0;
+ x->x_blockssincerecv = 0;
+ x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
+
+ for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
+ x->x_average[i] = x->x_maxframes;
+ x->x_averagecur = 0;
+
i = (int)buffer;
- if ((i > 0)&&(i < DEFAULT_AUDIO_BUFFER_FRAMES))
+ if ((i > 0)&&(i < DEFAULT_AUDIO_BUFFER_FRAMES))
{
- x->x_maxframes = i;
- post("udpreceive~: set buffer to %d frames)", x->x_maxframes);
- }
- else if (i != 0) /* special case of 0 leaves buffer size unchanged */
+ x->x_maxframes = i;
+ post("udpreceive~: set buffer to %d frames)", x->x_maxframes);
+ }
+ else if (i != 0) /* special case of 0 leaves buffer size unchanged */
{
- post("udpreceive~: buffer must be between 1 and %d frames)", DEFAULT_AUDIO_BUFFER_FRAMES-1);
- }
- x->x_underflow = 0;
- x->x_overflow = 0;
-}
-
-static void udpreceive_tilde_datapoll(t_udpreceive_tilde *x)
-{
- int ret;
- int n;
+ post("udpreceive~: buffer must be between 1 and %d frames)", DEFAULT_AUDIO_BUFFER_FRAMES-1);
+ }
+ x->x_underflow = 0;
+ x->x_overflow = 0;
+}
+
+static void udpreceive_tilde_datapoll(t_udpreceive_tilde *x)
+{
+ int ret;
+ int n;
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
long addr;
unsigned short port;
-
- n = x->x_nbytes;
-
- if (x->x_nbytes == 0) /* we ate all the samples and need a new header tag */
- {
- /* receive header tag */
+
+ n = x->x_nbytes;
+
+ if (x->x_nbytes == 0) /* we ate all the samples and need a new header tag */
+ {
+ /* receive header tag */
ret = recvfrom(x->x_socket, (char*)&x->x_frames[x->x_framein].tag, sizeof(t_tag), 0,
(struct sockaddr *)&from, &fromlen);
/* get the sender's ip */
@@ -197,579 +198,579 @@ static void udpreceive_tilde_datapoll(t_udpreceive_tilde *x)
x->x_addrbytes[4].a_w.w_float = port;
outlet_list(x->x_addrout, &s_list, 5L, x->x_addrbytes);
- if (ret <= 0) /* error */
- {
- if (udpreceive_tilde_sockerror("recv tag"))
- goto bail;
- udpreceive_tilde_reset(x, 0);
- x->x_counter = 0;
- return;
- }
- else if (ret != sizeof(t_tag))
- {
- /* incomplete header tag: return and try again later */
- /* in the hope that more data will be available */
- error("udpreceive~: got incomplete header tag");
- return;
- }
- /* adjust byte order if neccessarry */
- if (x->x_frames[x->x_framein].tag.version != SF_BYTE_NATIVE)
- {
- x->x_frames[x->x_framein].tag.count = netsend_long(x->x_frames[x->x_framein].tag.count);
- x->x_frames[x->x_framein].tag.framesize = netsend_long(x->x_frames[x->x_framein].tag.framesize);
- }
- /* get info from header tag */
- if (x->x_frames[x->x_framein].tag.channels > x->x_noutlets)
- {
- error("udpreceive~: incoming stream has too many channels (%d)", x->x_frames[x->x_framein].tag.channels);
- x->x_counter = 0;
- return;
- }
- x->x_nbytes = n = x->x_frames[x->x_framein].tag.framesize;
- }
- else /* we already have header tag or some data and need more */
- {
+ if (ret <= 0) /* error */
+ {
+ if (udpreceive_tilde_sockerror("recv tag"))
+ goto bail;
+ udpreceive_tilde_reset(x, 0);
+ x->x_counter = 0;
+ return;
+ }
+ else if (ret != sizeof(t_tag))
+ {
+ /* incomplete header tag: return and try again later */
+ /* in the hope that more data will be available */
+ error("udpreceive~: got incomplete header tag");
+ return;
+ }
+ /* adjust byte order if neccessarry */
+ if (x->x_frames[x->x_framein].tag.version != SF_BYTE_NATIVE)
+ {
+ x->x_frames[x->x_framein].tag.count = netsend_long(x->x_frames[x->x_framein].tag.count);
+ x->x_frames[x->x_framein].tag.framesize = netsend_long(x->x_frames[x->x_framein].tag.framesize);
+ }
+ /* get info from header tag */
+ if (x->x_frames[x->x_framein].tag.channels > x->x_noutlets)
+ {
+ error("udpreceive~: incoming stream has too many channels (%d)", x->x_frames[x->x_framein].tag.channels);
+ x->x_counter = 0;
+ return;
+ }
+ x->x_nbytes = n = x->x_frames[x->x_framein].tag.framesize;
+ }
+ else /* we already have header tag or some data and need more */
+ {
ret = recvfrom(x->x_socket, (char*)x->x_frames[x->x_framein].data + x->x_frames[x->x_framein].tag.framesize - n,
- n, 0, (struct sockaddr *)&from, &fromlen);
- if (ret > 0)
- {
- n -= ret;
- }
- else if (ret < 0) /* error */
- {
- if (udpreceive_tilde_sockerror("recv data"))
- goto bail;
- udpreceive_tilde_reset(x, 0);
- x->x_counter = 0;
- return;
- }
-
- x->x_nbytes = n;
- if (n == 0) /* a complete packet is received */
- {
- if (x->x_frames[x->x_framein].tag.format == SF_AAC)
- {
- error("udpreceive~: don't know how to decode AAC format");
- return;
- }
- x->x_counter++;
- x->x_framein++;
- x->x_framein %= DEFAULT_AUDIO_BUFFER_FRAMES;
-
- /* check for buffer overflow */
- if (x->x_framein == x->x_frameout)
- {
- x->x_overflow++;
- }
- }
- }
-bail:
-;
-}
-
-static void udpreceive_tilde_connectpoll(t_udpreceive_tilde *x)
-{
- int sockaddrl = (int)sizeof(struct sockaddr);
- struct sockaddr_in incomer_address;
- int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
-
- if (fd < 0)
- {
- post("udpreceive~: accept failed");
- return;
- }
-#ifdef O_NONBLOCK
- fcntl(fd, F_SETFL, O_NONBLOCK);
-#endif
- if (x->x_socket != -1)
- {
- post("udpreceive~: new connection");
- udpreceive_tilde_closesocket(x);
- }
-
- udpreceive_tilde_reset(x, 0);
- x->x_socket = fd;
- x->x_nbytes = 0;
- x->x_hostname = gensym(inet_ntoa(incomer_address.sin_addr));
- sys_addpollfn(fd, udpreceive_tilde_datapoll, x);
- outlet_float(x->x_outlet1, 1);
-}
-
-static int udpreceive_tilde_createsocket(t_udpreceive_tilde* x, int portno)
-{
- struct sockaddr_in server;
- int sockfd;
-
- /* create a socket */
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-
- if (sockfd < 0)
- {
- udpreceive_tilde_sockerror("socket");
- return 0;
- }
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
-
- /* assign server port number */
-
- server.sin_port = htons((u_short)portno);
- post("listening to port number %d", portno);
-
- udpreceive_tilde_setsocketoptions(sockfd);
-
- /* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
- {
- udpreceive_tilde_sockerror("bind");
- CLOSESOCKET(sockfd);
- return 0;
- }
-
- x->x_socket = sockfd;
- x->x_nbytes = 0;
- sys_addpollfn(sockfd, udpreceive_tilde_datapoll, x);
- return 1;
-}
-
-/* Queue is 1 to 16 frames long */
-#define QUEUESIZE (int)((x->x_framein + DEFAULT_AUDIO_BUFFER_FRAMES - x->x_frameout) % DEFAULT_AUDIO_BUFFER_FRAMES)
-/* Block is a set of sample vectors inside a frame, one vector per channel */
-#define BLOCKOFFSET (x->x_blockssincerecv * x->x_vecsize * x->x_frames[x->x_frameout].tag.channels)
-
-static t_int *udpreceive_tilde_perform(t_int *w)
-{
- t_udpreceive_tilde *x = (t_udpreceive_tilde*) (w[1]);
- int n = (int)(w[2]);
- t_float *out[DEFAULT_AUDIO_CHANNELS];
- const int offset = 3;
- const int channels = x->x_frames[x->x_frameout].tag.channels;
- int i = 0;
-
- for (i = 0; i < x->x_noutlets; i++)
- {
- out[i] = (t_float *)(w[offset + i]);
- }
-
- /* set our vector size to the local vector size */
- if (n != x->x_vecsize)
- {
- x->x_vecsize = n;
- x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
- x->x_blockssincerecv = 0;
- }
-
- /* check whether there is enough data in buffer */
- if (x->x_counter < x->x_maxframes)
- {
- goto bail;
- }
-
- /* check for buffer underflow */
- if (x->x_framein == x->x_frameout)
- {
- x->x_underflow++;
- goto bail;
- }
-
- /* queue balancing */
- x->x_average[x->x_averagecur] = QUEUESIZE;
- if (++x->x_averagecur >= DEFAULT_AVERAGE_NUMBER)
- x->x_averagecur = 0;
-
- switch (x->x_frames[x->x_frameout].tag.format)
- {
- case SF_FLOAT:
- {
- t_float* buf = (t_float *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
-
- if (x->x_frames[x->x_frameout].tag.version == SF_BYTE_NATIVE)
- {
- while (n--)
- {
- for (i = 0; i < channels; i++)
- {
- *out[i]++ = *buf++;
- }
- for (i = channels; i < x->x_noutlets; i++)
- {
- *out[i]++ = 0.;
- }
- }
- }
- else /* swap bytes */
- {
- while (n--)
- {
- for (i = 0; i < channels; i++)
- {
- *out[i]++ = netsend_float(*buf++);
- }
- for (i = channels; i < x->x_noutlets; i++)
- {
- *out[i]++ = 0.;
- }
- }
- }
- break;
- }
- case SF_16BIT:
- {
- short* buf = (short *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
-
- if (x->x_frames[x->x_frameout].tag.version == SF_BYTE_NATIVE)
- {
- while (n--)
- {
- for (i = 0; i < channels; i++)
- {
- *out[i]++ = (t_float)(*buf++ * 3.051850e-05);
- }
- for (i = channels; i < x->x_noutlets; i++)
- {
- *out[i]++ = 0.;
- }
- }
- }
- else /* swap bytes */
- {
- while (n--)
- {
- for (i = 0; i < channels; i++)
- {
- *out[i]++ = (t_float)(netsend_short(*buf++) * 3.051850e-05);
- }
- for (i = channels; i < x->x_noutlets; i++)
- {
- *out[i]++ = 0.;
- }
- }
- }
- break;
- }
- case SF_8BIT:
- {
- unsigned char* buf = (char *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
-
- while (n--)
- {
- for (i = 0; i < channels; i++)
- {
- *out[i]++ = (t_float)((0.0078125 * (*buf++)) - 1.0);
- }
- for (i = channels; i < x->x_noutlets; i++)
- {
- *out[i]++ = 0.;
- }
- }
- break;
- }
- case SF_MP3:
- {
- post("udpreceive~: mp3 format not supported");
- }
- case SF_AAC:
- {
- post("udpreceive~: aac format not supported");
- break;
- }
- default:
- post("udpreceive~: unknown format (%d)",x->x_frames[x->x_frameout].tag.format);
- break;
- }
-
- if (!(x->x_blockssincerecv < x->x_blocksperrecv - 1))
- {
- x->x_blockssincerecv = 0;
- x->x_frameout++;
- x->x_frameout %= DEFAULT_AUDIO_BUFFER_FRAMES;
- }
- else
- {
- x->x_blockssincerecv++;
- }
-
- return (w + offset + x->x_noutlets);
-
-bail:
- /* set output to zero */
- while (n--)
- {
- for (i = 0; i < x->x_noutlets; i++)
- {
- *(out[i]++) = 0.;
- }
- }
- return (w + offset + x->x_noutlets);
-}
-
-static void udpreceive_tilde_dsp(t_udpreceive_tilde *x, t_signal **sp)
-{
- int i;
-
- x->x_myvec[0] = (t_int*)x;
- x->x_myvec[1] = (t_int*)sp[0]->s_n;
-
- x->x_samplerate = (long)sp[0]->s_sr;
-
- if (x->x_blocksize % sp[0]->s_n)
- {
- error("netsend~: signal vector size too large (needs to be even divisor of %d)", x->x_blocksize);
- }
- else
- {
- for (i = 0; i < x->x_noutlets; i++)
- {
- x->x_myvec[2 + i] = (t_int*)sp[i + 1]->s_vec;
- }
- dsp_addv(udpreceive_tilde_perform, x->x_noutlets + 2, (t_int*)x->x_myvec);
- }
-}
-
-/* send stream info */
-static void udpreceive_tilde_info(t_udpreceive_tilde *x)
-{
- t_atom list[2];
- t_symbol *sf_format;
- t_float bitrate;
- int i, avg = 0;
-
- for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
- avg += x->x_average[i];
-
- bitrate = (t_float)((SF_SIZEOF(x->x_frames[x->x_frameout].tag.format) * x->x_samplerate * 8 * x->x_frames[x->x_frameout].tag.channels) / 1000.);
-
- switch (x->x_frames[x->x_frameout].tag.format)
- {
- case SF_FLOAT:
- {
- sf_format = ps_sf_float;
- break;
- }
- case SF_16BIT:
- {
- sf_format = ps_sf_16bit;
- break;
- }
- case SF_8BIT:
- {
- sf_format = ps_sf_8bit;
- break;
- }
- case SF_MP3:
- {
- sf_format = ps_sf_mp3;
- break;
- }
- case SF_AAC:
- {
- sf_format = ps_sf_aac;
- break;
- }
- default:
- {
- sf_format = ps_sf_unknown;
- break;
- }
- }
-
- /* --- stream information (t_tag) --- */
- /* audio format */
- SETSYMBOL(list, (t_symbol *)sf_format);
- outlet_anything(x->x_outlet2, ps_format, 1, list);
-
- /* channels */
- SETFLOAT(list, (t_float)x->x_frames[x->x_frameout].tag.channels);
- outlet_anything(x->x_outlet2, ps_channels, 1, list);
-
- /* framesize */
- SETFLOAT(list, (t_float)x->x_frames[x->x_frameout].tag.framesize);
- outlet_anything(x->x_outlet2, ps_framesize, 1, list);
-
- /* bitrate */
- SETFLOAT(list, (t_float)bitrate);
- outlet_anything(x->x_outlet2, ps_bitrate, 1, list);
-
- /* --- internal info (buffer and network) --- */
- /* overflow */
- SETFLOAT(list, (t_float)x->x_overflow);
- outlet_anything(x->x_outlet2, ps_overflow, 1, list);
-
- /* underflow */
- SETFLOAT(list, (t_float)x->x_underflow);
- outlet_anything(x->x_outlet2, ps_underflow, 1, list);
-
- /* queuesize */
- SETFLOAT(list, (t_float)QUEUESIZE);
- outlet_anything(x->x_outlet2, ps_queuesize, 1, list);
-
- /* average queuesize */
- SETFLOAT(list, (t_float)((t_float)avg / (t_float)DEFAULT_AVERAGE_NUMBER));
- outlet_anything(x->x_outlet2, ps_average, 1, list);
-
- /* total packets */
- SETFLOAT(list, (t_float)x->x_counter);
- outlet_anything(x->x_outlet2, ps_packets, 1, list);
-}
-
-static void *udpreceive_tilde_new(t_floatarg fportno, t_floatarg outlets, t_floatarg blocksize)
-{
- t_udpreceive_tilde *x;
- int i;
-
- if (fportno == 0) fportno = DEFAULT_PORT;
-
- x = (t_udpreceive_tilde *)pd_new(udpreceive_tilde_class);
- if (x)
- {
- for (i = sizeof(t_object); i < (int)sizeof(t_udpreceive_tilde); i++)
- ((char *)x)[i] = 0;
-
- x->x_noutlets = CLIP((int)outlets, 1, DEFAULT_AUDIO_CHANNELS);
- for (i = 0; i < x->x_noutlets; i++)
- outlet_new(&x->x_obj, &s_signal);
- x->x_outlet2 = outlet_new(&x->x_obj, &s_anything);
+ n, 0, (struct sockaddr *)&from, &fromlen);
+ if (ret > 0)
+ {
+ n -= ret;
+ }
+ else if (ret < 0) /* error */
+ {
+ if (udpreceive_tilde_sockerror("recv data"))
+ goto bail;
+ udpreceive_tilde_reset(x, 0);
+ x->x_counter = 0;
+ return;
+ }
+
+ x->x_nbytes = n;
+ if (n == 0) /* a complete packet is received */
+ {
+ if (x->x_frames[x->x_framein].tag.format == SF_AAC)
+ {
+ error("udpreceive~: don't know how to decode AAC format");
+ return;
+ }
+ x->x_counter++;
+ x->x_framein++;
+ x->x_framein %= DEFAULT_AUDIO_BUFFER_FRAMES;
+
+ /* check for buffer overflow */
+ if (x->x_framein == x->x_frameout)
+ {
+ x->x_overflow++;
+ }
+ }
+ }
+bail:
+;
+}
+
+static void udpreceive_tilde_connectpoll(t_udpreceive_tilde *x)
+{
+ int sockaddrl = (int)sizeof(struct sockaddr);
+ struct sockaddr_in incomer_address;
+ int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
+
+ if (fd < 0)
+ {
+ post("udpreceive~: accept failed");
+ return;
+ }
+#ifdef O_NONBLOCK
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+ if (x->x_socket != -1)
+ {
+ post("udpreceive~: new connection");
+ udpreceive_tilde_closesocket(x);
+ }
+
+ udpreceive_tilde_reset(x, 0);
+ x->x_socket = fd;
+ x->x_nbytes = 0;
+ x->x_hostname = gensym(inet_ntoa(incomer_address.sin_addr));
+ sys_addpollfn(fd, udpreceive_tilde_datapoll, x);
+ outlet_float(x->x_outlet1, 1);
+}
+
+static int udpreceive_tilde_createsocket(t_udpreceive_tilde* x, int portno)
+{
+ struct sockaddr_in server;
+ int sockfd;
+
+ /* create a socket */
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (sockfd < 0)
+ {
+ udpreceive_tilde_sockerror("socket");
+ return 0;
+ }
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+
+ /* assign server port number */
+
+ server.sin_port = htons((u_short)portno);
+ post("listening to port number %d", portno);
+
+ udpreceive_tilde_setsocketoptions(sockfd);
+
+ /* name the socket */
+ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
+ {
+ udpreceive_tilde_sockerror("bind");
+ CLOSESOCKET(sockfd);
+ return 0;
+ }
+
+ x->x_socket = sockfd;
+ x->x_nbytes = 0;
+ sys_addpollfn(sockfd, udpreceive_tilde_datapoll, x);
+ return 1;
+}
+
+/* Queue is 1 to 16 frames long */
+#define QUEUESIZE (int)((x->x_framein + DEFAULT_AUDIO_BUFFER_FRAMES - x->x_frameout) % DEFAULT_AUDIO_BUFFER_FRAMES)
+/* Block is a set of sample vectors inside a frame, one vector per channel */
+#define BLOCKOFFSET (x->x_blockssincerecv * x->x_vecsize * x->x_frames[x->x_frameout].tag.channels)
+
+static t_int *udpreceive_tilde_perform(t_int *w)
+{
+ t_udpreceive_tilde *x = (t_udpreceive_tilde*) (w[1]);
+ int n = (int)(w[2]);
+ t_float *out[DEFAULT_AUDIO_CHANNELS];
+ const int offset = 3;
+ const int channels = x->x_frames[x->x_frameout].tag.channels;
+ int i = 0;
+
+ for (i = 0; i < x->x_noutlets; i++)
+ {
+ out[i] = (t_float *)(w[offset + i]);
+ }
+
+ /* set our vector size to the local vector size */
+ if (n != x->x_vecsize)
+ {
+ x->x_vecsize = n;
+ x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
+ x->x_blockssincerecv = 0;
+ }
+
+ /* check whether there is enough data in buffer */
+ if (x->x_counter < x->x_maxframes)
+ {
+ goto bail;
+ }
+
+ /* check for buffer underflow */
+ if (x->x_framein == x->x_frameout)
+ {
+ x->x_underflow++;
+ goto bail;
+ }
+
+ /* queue balancing */
+ x->x_average[x->x_averagecur] = QUEUESIZE;
+ if (++x->x_averagecur >= DEFAULT_AVERAGE_NUMBER)
+ x->x_averagecur = 0;
+
+ switch (x->x_frames[x->x_frameout].tag.format)
+ {
+ case SF_FLOAT:
+ {
+ t_float* buf = (t_float *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+ if (x->x_frames[x->x_frameout].tag.version == SF_BYTE_NATIVE)
+ {
+ while (n--)
+ {
+ for (i = 0; i < channels; i++)
+ {
+ *out[i]++ = *buf++;
+ }
+ for (i = channels; i < x->x_noutlets; i++)
+ {
+ *out[i]++ = 0.;
+ }
+ }
+ }
+ else /* swap bytes */
+ {
+ while (n--)
+ {
+ for (i = 0; i < channels; i++)
+ {
+ *out[i]++ = netsend_float(*buf++);
+ }
+ for (i = channels; i < x->x_noutlets; i++)
+ {
+ *out[i]++ = 0.;
+ }
+ }
+ }
+ break;
+ }
+ case SF_16BIT:
+ {
+ short* buf = (short *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+ if (x->x_frames[x->x_frameout].tag.version == SF_BYTE_NATIVE)
+ {
+ while (n--)
+ {
+ for (i = 0; i < channels; i++)
+ {
+ *out[i]++ = (t_float)(*buf++ * 3.051850e-05);
+ }
+ for (i = channels; i < x->x_noutlets; i++)
+ {
+ *out[i]++ = 0.;
+ }
+ }
+ }
+ else /* swap bytes */
+ {
+ while (n--)
+ {
+ for (i = 0; i < channels; i++)
+ {
+ *out[i]++ = (t_float)(netsend_short(*buf++) * 3.051850e-05);
+ }
+ for (i = channels; i < x->x_noutlets; i++)
+ {
+ *out[i]++ = 0.;
+ }
+ }
+ }
+ break;
+ }
+ case SF_8BIT:
+ {
+ unsigned char* buf = (char *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+ while (n--)
+ {
+ for (i = 0; i < channels; i++)
+ {
+ *out[i]++ = (t_float)((0.0078125 * (*buf++)) - 1.0);
+ }
+ for (i = channels; i < x->x_noutlets; i++)
+ {
+ *out[i]++ = 0.;
+ }
+ }
+ break;
+ }
+ case SF_MP3:
+ {
+ post("udpreceive~: mp3 format not supported");
+ }
+ case SF_AAC:
+ {
+ post("udpreceive~: aac format not supported");
+ break;
+ }
+ default:
+ post("udpreceive~: unknown format (%d)",x->x_frames[x->x_frameout].tag.format);
+ break;
+ }
+
+ if (!(x->x_blockssincerecv < x->x_blocksperrecv - 1))
+ {
+ x->x_blockssincerecv = 0;
+ x->x_frameout++;
+ x->x_frameout %= DEFAULT_AUDIO_BUFFER_FRAMES;
+ }
+ else
+ {
+ x->x_blockssincerecv++;
+ }
+
+ return (w + offset + x->x_noutlets);
+
+bail:
+ /* set output to zero */
+ while (n--)
+ {
+ for (i = 0; i < x->x_noutlets; i++)
+ {
+ *(out[i]++) = 0.;
+ }
+ }
+ return (w + offset + x->x_noutlets);
+}
+
+static void udpreceive_tilde_dsp(t_udpreceive_tilde *x, t_signal **sp)
+{
+ int i;
+
+ x->x_myvec[0] = (t_int*)x;
+ x->x_myvec[1] = (t_int*)sp[0]->s_n;
+
+ x->x_samplerate = (long)sp[0]->s_sr;
+
+ if (x->x_blocksize % sp[0]->s_n)
+ {
+ error("netsend~: signal vector size too large (needs to be even divisor of %d)", x->x_blocksize);
+ }
+ else
+ {
+ for (i = 0; i < x->x_noutlets; i++)
+ {
+ x->x_myvec[2 + i] = (t_int*)sp[i + 1]->s_vec;
+ }
+ dsp_addv(udpreceive_tilde_perform, x->x_noutlets + 2, (t_int*)x->x_myvec);
+ }
+}
+
+/* send stream info */
+static void udpreceive_tilde_info(t_udpreceive_tilde *x)
+{
+ t_atom list[2];
+ t_symbol *sf_format;
+ t_float bitrate;
+ int i, avg = 0;
+
+ for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
+ avg += x->x_average[i];
+
+ bitrate = (t_float)((SF_SIZEOF(x->x_frames[x->x_frameout].tag.format) * x->x_samplerate * 8 * x->x_frames[x->x_frameout].tag.channels) / 1000.);
+
+ switch (x->x_frames[x->x_frameout].tag.format)
+ {
+ case SF_FLOAT:
+ {
+ sf_format = ps_sf_float;
+ break;
+ }
+ case SF_16BIT:
+ {
+ sf_format = ps_sf_16bit;
+ break;
+ }
+ case SF_8BIT:
+ {
+ sf_format = ps_sf_8bit;
+ break;
+ }
+ case SF_MP3:
+ {
+ sf_format = ps_sf_mp3;
+ break;
+ }
+ case SF_AAC:
+ {
+ sf_format = ps_sf_aac;
+ break;
+ }
+ default:
+ {
+ sf_format = ps_sf_unknown;
+ break;
+ }
+ }
+
+ /* --- stream information (t_tag) --- */
+ /* audio format */
+ SETSYMBOL(list, (t_symbol *)sf_format);
+ outlet_anything(x->x_outlet2, ps_format, 1, list);
+
+ /* channels */
+ SETFLOAT(list, (t_float)x->x_frames[x->x_frameout].tag.channels);
+ outlet_anything(x->x_outlet2, ps_channels, 1, list);
+
+ /* framesize */
+ SETFLOAT(list, (t_float)x->x_frames[x->x_frameout].tag.framesize);
+ outlet_anything(x->x_outlet2, ps_framesize, 1, list);
+
+ /* bitrate */
+ SETFLOAT(list, (t_float)bitrate);
+ outlet_anything(x->x_outlet2, ps_bitrate, 1, list);
+
+ /* --- internal info (buffer and network) --- */
+ /* overflow */
+ SETFLOAT(list, (t_float)x->x_overflow);
+ outlet_anything(x->x_outlet2, ps_overflow, 1, list);
+
+ /* underflow */
+ SETFLOAT(list, (t_float)x->x_underflow);
+ outlet_anything(x->x_outlet2, ps_underflow, 1, list);
+
+ /* queuesize */
+ SETFLOAT(list, (t_float)QUEUESIZE);
+ outlet_anything(x->x_outlet2, ps_queuesize, 1, list);
+
+ /* average queuesize */
+ SETFLOAT(list, (t_float)((t_float)avg / (t_float)DEFAULT_AVERAGE_NUMBER));
+ outlet_anything(x->x_outlet2, ps_average, 1, list);
+
+ /* total packets */
+ SETFLOAT(list, (t_float)x->x_counter);
+ outlet_anything(x->x_outlet2, ps_packets, 1, list);
+}
+
+static void *udpreceive_tilde_new(t_floatarg fportno, t_floatarg outlets, t_floatarg blocksize)
+{
+ t_udpreceive_tilde *x;
+ int i;
+
+ if (fportno == 0) fportno = DEFAULT_PORT;
+
+ x = (t_udpreceive_tilde *)pd_new(udpreceive_tilde_class);
+ if (x)
+ {
+ for (i = sizeof(t_object); i < (int)sizeof(t_udpreceive_tilde); i++)
+ ((char *)x)[i] = 0;
+
+ x->x_noutlets = CLIP((int)outlets, 1, DEFAULT_AUDIO_CHANNELS);
+ for (i = 0; i < x->x_noutlets; i++)
+ outlet_new(&x->x_obj, &s_signal);
+ x->x_outlet2 = outlet_new(&x->x_obj, &s_anything);
x->x_addrout = outlet_new(&x->x_obj, &s_list);
for (i = 0; i < 5; ++i)
{
x->x_addrbytes[i].a_type = A_FLOAT;
x->x_addrbytes[i].a_w.w_float = 0;
}
- x->x_myvec = (t_int **)t_getbytes(sizeof(t_int *) * (x->x_noutlets + 3));
- if (!x->x_myvec)
- {
- error("udpreceive~: out of memory");
- return NULL;
- }
-
- x->x_connectsocket = -1;
- x->x_socket = -1;
- x->x_nconnections = 0;
- x->x_ndrops = 0;
- x->x_underflow = 0;
- x->x_overflow = 0;
- x->x_hostname = ps_nothing;
-/* allocate space for 16 frames of 1024 X numchannels floats*/
- for (i = 0; i < DEFAULT_AUDIO_BUFFER_FRAMES; i++)
- {
- x->x_frames[i].data = (char *)t_getbytes(DEFAULT_AUDIO_BUFFER_SIZE * x->x_noutlets * sizeof(t_float));
- }
- x->x_framein = 0;
- x->x_frameout = 0;
- x->x_maxframes = DEFAULT_QUEUE_LENGTH;
- x->x_vecsize = 64; /* we'll update this later */
+ x->x_myvec = (t_int **)t_getbytes(sizeof(t_int *) * (x->x_noutlets + 3));
+ if (!x->x_myvec)
+ {
+ error("udpreceive~: out of memory");
+ return NULL;
+ }
+
+ x->x_connectsocket = -1;
+ x->x_socket = -1;
+ x->x_nconnections = 0;
+ x->x_ndrops = 0;
+ x->x_underflow = 0;
+ x->x_overflow = 0;
+ x->x_hostname = ps_nothing;
+/* allocate space for 16 frames of 1024 X numchannels floats*/
+ for (i = 0; i < DEFAULT_AUDIO_BUFFER_FRAMES; i++)
+ {
+ x->x_frames[i].data = (char *)t_getbytes(DEFAULT_AUDIO_BUFFER_SIZE * x->x_noutlets * sizeof(t_float));
+ }
+ x->x_framein = 0;
+ x->x_frameout = 0;
+ x->x_maxframes = DEFAULT_QUEUE_LENGTH;
+ x->x_vecsize = 64; /* we'll update this later */
if (blocksize == 0) x->x_blocksize = DEFAULT_AUDIO_BUFFER_SIZE;
else if (DEFAULT_AUDIO_BUFFER_SIZE%(int)blocksize)
{
- error("udpreceive~: blocksize must fit snugly in %d", DEFAULT_AUDIO_BUFFER_SIZE);
- return NULL;
- }
- else x->x_blocksize = (int)blocksize; //DEFAULT_AUDIO_BUFFER_SIZE; /* <-- the only place blocksize is set */
- x->x_blockssincerecv = 0;
- x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
-
- if (!udpreceive_tilde_createsocket(x, (int)fportno))
- {
- error("udpreceive~: failed to create listening socket");
- return (NULL);
- }
- }
- return (x);
-}
-
-static void udpreceive_tilde_free(t_udpreceive_tilde *x)
-{
- int i;
-
- if (x->x_connectsocket != -1)
- {
- sys_rmpollfn(x->x_connectsocket);
- CLOSESOCKET(x->x_connectsocket);
- }
- if (x->x_socket != -1)
- {
- sys_rmpollfn(x->x_socket);
- CLOSESOCKET(x->x_socket);
- }
-
- /* free memory */
- t_freebytes(x->x_myvec, sizeof(t_int *) * (x->x_noutlets + 3));
- for (i = 0; i < DEFAULT_AUDIO_BUFFER_FRAMES; i++)
- {
- t_freebytes(x->x_frames[i].data, DEFAULT_AUDIO_BUFFER_SIZE * x->x_noutlets * sizeof(t_float));
- }
-}
-
-void udpreceive_tilde_setup(void)
-{
- udpreceive_tilde_class = class_new(gensym("udpreceive~"),
- (t_newmethod) udpreceive_tilde_new, (t_method) udpreceive_tilde_free,
- sizeof(t_udpreceive_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
-
- class_addmethod(udpreceive_tilde_class, nullfn, gensym("signal"), 0);
- class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_info, gensym("info"), 0);
- class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_dsp, gensym("dsp"), 0);
- class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_reset, gensym("reset"), A_DEFFLOAT, 0);
- class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_reset, gensym("buffer"), A_DEFFLOAT, 0);
- post("udpreceive~ v%s, (c) 2004 Olaf Matthes, 2010 Martin Peach", VERSION);
-
- ps_format = gensym("format");
- ps_channels = gensym("channels");
- ps_framesize = gensym("framesize");
- ps_bitrate = gensym("bitrate");
- ps_overflow = gensym("overflow");
- ps_underflow = gensym("underflow");
- ps_queuesize = gensym("queuesize");
- ps_average = gensym("average");
- ps_packets = gensym("packets");
- ps_hostname = gensym("ipaddr");
- ps_sf_float = gensym("_float_");
- ps_sf_16bit = gensym("_16bit_");
- ps_sf_8bit = gensym("_8bit_");
- ps_sf_mp3 = gensym("_mp3_");
- ps_sf_aac = gensym("_aac_");
- ps_sf_unknown = gensym("_unknown_");
- ps_nothing = gensym("");
-}
-
-/* error handlers */
-static int udpreceive_tilde_sockerror(char *s)
-{
-#ifdef _WIN32
- int err = WSAGetLastError();
- if (err == 10054) return 1;
- else if (err == 10040) post("netsend~: %s: message too long (%d)", s, err);
- else if (err == 10053) post("netsend~: %s: software caused connection abort (%d)", s, err);
- else if (err == 10055) post("netsend~: %s: no buffer space available (%d)", s, err);
- else if (err == 10060) post("netsend~: %s: connection timed out (%d)", s, err);
- else if (err == 10061) post("netsend~: %s: connection refused (%d)", s, err);
- else post("udpreceive~: %s: %s (%d)", s, strerror(err), err);
-#else
- int err = errno;
- post("udpreceive~: %s: %s (%d)", s, strerror(err), err);
-#endif
-#ifdef _WIN32
- if (err == WSAEWOULDBLOCK)
-#endif
-#if defined(UNIX) || defined(unix)
- if (err == EAGAIN)
-#endif
- {
- return 1; /* recoverable error */
- }
- return 0; /* indicate non-recoverable error */
-}
-
-static int udpreceive_tilde_setsocketoptions(int sockfd)
-{
- int sockopt = 1;
- if (setsockopt(sockfd, SOL_IP, TCP_NODELAY, (const char*)&sockopt, sizeof(int)) < 0)
- post("setsockopt NODELAY failed");
-
- sockopt = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&sockopt, sizeof(int)) < 0)
- post("udpreceive~: setsockopt REUSEADDR failed");
- return 0;
-}
-
-/* fin udpreceive~.c */
+ error("udpreceive~: blocksize must fit snugly in %d", DEFAULT_AUDIO_BUFFER_SIZE);
+ return NULL;
+ }
+ else x->x_blocksize = (int)blocksize; //DEFAULT_AUDIO_BUFFER_SIZE; /* <-- the only place blocksize is set */
+ x->x_blockssincerecv = 0;
+ x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
+
+ if (!udpreceive_tilde_createsocket(x, (int)fportno))
+ {
+ error("udpreceive~: failed to create listening socket");
+ return (NULL);
+ }
+ }
+ return (x);
+}
+
+static void udpreceive_tilde_free(t_udpreceive_tilde *x)
+{
+ int i;
+
+ if (x->x_connectsocket != -1)
+ {
+ sys_rmpollfn(x->x_connectsocket);
+ CLOSESOCKET(x->x_connectsocket);
+ }
+ if (x->x_socket != -1)
+ {
+ sys_rmpollfn(x->x_socket);
+ CLOSESOCKET(x->x_socket);
+ }
+
+ /* free memory */
+ t_freebytes(x->x_myvec, sizeof(t_int *) * (x->x_noutlets + 3));
+ for (i = 0; i < DEFAULT_AUDIO_BUFFER_FRAMES; i++)
+ {
+ t_freebytes(x->x_frames[i].data, DEFAULT_AUDIO_BUFFER_SIZE * x->x_noutlets * sizeof(t_float));
+ }
+}
+
+void udpreceive_tilde_setup(void)
+{
+ udpreceive_tilde_class = class_new(gensym("udpreceive~"),
+ (t_newmethod) udpreceive_tilde_new, (t_method) udpreceive_tilde_free,
+ sizeof(t_udpreceive_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+
+ class_addmethod(udpreceive_tilde_class, nullfn, gensym("signal"), 0);
+ class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_info, gensym("info"), 0);
+ class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_dsp, gensym("dsp"), 0);
+ class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_reset, gensym("reset"), A_DEFFLOAT, 0);
+ class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_reset, gensym("buffer"), A_DEFFLOAT, 0);
+ post("udpreceive~ v%s, (c) 2004 Olaf Matthes, 2010 Martin Peach", VERSION);
+
+ ps_format = gensym("format");
+ ps_channels = gensym("channels");
+ ps_framesize = gensym("framesize");
+ ps_bitrate = gensym("bitrate");
+ ps_overflow = gensym("overflow");
+ ps_underflow = gensym("underflow");
+ ps_queuesize = gensym("queuesize");
+ ps_average = gensym("average");
+ ps_packets = gensym("packets");
+ ps_hostname = gensym("ipaddr");
+ ps_sf_float = gensym("_float_");
+ ps_sf_16bit = gensym("_16bit_");
+ ps_sf_8bit = gensym("_8bit_");
+ ps_sf_mp3 = gensym("_mp3_");
+ ps_sf_aac = gensym("_aac_");
+ ps_sf_unknown = gensym("_unknown_");
+ ps_nothing = gensym("");
+}
+
+/* error handlers */
+static int udpreceive_tilde_sockerror(char *s)
+{
+#ifdef _WIN32
+ int err = WSAGetLastError();
+ if (err == 10054) return 1;
+ else if (err == 10040) post("netsend~: %s: message too long (%d)", s, err);
+ else if (err == 10053) post("netsend~: %s: software caused connection abort (%d)", s, err);
+ else if (err == 10055) post("netsend~: %s: no buffer space available (%d)", s, err);
+ else if (err == 10060) post("netsend~: %s: connection timed out (%d)", s, err);
+ else if (err == 10061) post("netsend~: %s: connection refused (%d)", s, err);
+ else post("udpreceive~: %s: %s (%d)", s, strerror(err), err);
+#else
+ int err = errno;
+ post("udpreceive~: %s: %s (%d)", s, strerror(err), err);
+#endif
+#ifdef _WIN32
+ if (err == WSAEWOULDBLOCK)
+#endif
+#if defined(UNIX) || defined(unix)
+ if (err == EAGAIN)
+#endif
+ {
+ return 1; /* recoverable error */
+ }
+ return 0; /* indicate non-recoverable error */
+}
+
+static int udpreceive_tilde_setsocketoptions(int sockfd)
+{
+ int sockopt = 1;
+ if (setsockopt(sockfd, SOL_IP, TCP_NODELAY, (const char*)&sockopt, sizeof(int)) < 0)
+ post("setsockopt NODELAY failed");
+
+ sockopt = 1;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&sockopt, sizeof(int)) < 0)
+ post("udpreceive~: setsockopt REUSEADDR failed");
+ return 0;
+}
+
+/* fin udpreceive~.c */
diff --git a/net/udpsend~.c b/net/udpsend~.c
index 2abf288..291891e 100644
--- a/net/udpsend~.c
+++ b/net/udpsend~.c
@@ -1,669 +1,669 @@
-/* udpsend~ started by Martin Peach on 20100110, based on netsend~ */
-/* udpsend~ sends audio via udp only.*/
-/* It is a PD external, all Max stuff has been removed from the source */
-/* ------------------------ netsend~ ------------------------------------------ */
-/* */
-/* Tilde object to send uncompressed audio data to netreceive~. */
-/* Written by Olaf Matthes <olaf.matthes@gmx.de>. */
-/* Based on streamout~ by Guenter Geiger. */
-/* Get source at http://www.akustische-kunst.org/ */
-/* */
-/* This program is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU General Public License */
-/* as published by the Free Software Foundation; either version 2 */
-/* of the License, or (at your option) any later version. */
-/* */
-/* See file LICENSE for further informations on licensing terms. */
-/* */
-/* This program 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 General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/* */
-/* Based on PureData by Miller Puckette and others. */
-/* */
-/* This project was commissioned by the Society for Arts and Technology [SAT], */
-/* Montreal, Quebec, Canada, http://www.sat.qc.ca/. */
-/* */
-/* ---------------------------------------------------------------------------- */
-
-#include "m_pd.h"
-
-#include "udpsend~.h"
-#include "float_cast.h" /* tools for fast conversion from float to int */
-
-#include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
+/* udpsend~ started by Martin Peach on 20100110, based on netsend~ */
+/* udpsend~ sends audio via udp only.*/
+/* It is a PD external, all Max stuff has been removed from the source */
+/* ------------------------ netsend~ ------------------------------------------ */
+/* */
+/* Tilde object to send uncompressed audio data to netreceive~. */
+/* Written by Olaf Matthes <olaf.matthes@gmx.de>. */
+/* Based on streamout~ by Guenter Geiger. */
+/* Get source at http://www.akustische-kunst.org/ */
+/* */
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* See file LICENSE for further informations on licensing terms. */
+/* */
+/* This program 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 General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/* Based on PureData by Miller Puckette and others. */
+/* */
+/* This project was commissioned by the Society for Arts and Technology [SAT], */
+/* Montreal, Quebec, Canada, http://www.sat.qc.ca/. */
+/* */
+/* ---------------------------------------------------------------------------- */
+
+#include "m_pd.h"
+
+#include "udpsend~.h"
+#include "float_cast.h" /* tools for fast conversion from float to int */
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
#if defined(UNIX) || defined(unix)
-#include <sys/socket.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
#include <pthread.h>
-#include <math.h>
-#define SOCKET_ERROR -1
-#endif
-#ifdef _WIN32
-#include <winsock.h>
-#include "pthread.h"
-#endif
-
-#ifdef MSG_NOSIGNAL
-#define SEND_FLAGS /*MSG_DONTWAIT|*/MSG_NOSIGNAL
-#else
-#define SEND_FLAGS 0
-#endif
-
-#ifndef SOL_IP
-#define SOL_IP IPPROTO_IP
-#endif
-
-
-/* ------------------------ udpsend~ ----------------------------- */
-
-static t_class *udpsend_tilde_class;
-
-static t_symbol *ps_nothing, *ps_localhost, *ps_vecsize;
-static t_symbol *ps_format, *ps_channels, *ps_framesize, *ps_overflow, *ps_underflow;
-static t_symbol *ps_queuesize, *ps_average, *ps_sf_float, *ps_sf_16bit, *ps_sf_8bit;
-static t_symbol *ps_sf_mp3, *ps_sf_aac, *ps_sf_unknown, *ps_bitrate, *ps_hostname;
-
-typedef struct _udpsend_tilde
-{
- t_object x_obj;
- t_outlet *x_outlet;
- t_outlet *x_outlet2;
- t_clock *x_clock;
- int x_fd;
- t_tag x_tag;
- t_symbol* x_hostname;
- int x_portno;
- int x_connectstate;
- char *x_cbuf;
- int x_cbufsize;
- int x_blocksize; /* set to DEFAULT_AUDIO_BUFFER_SIZE in udpsend_tilde_new() */
- int x_blockspersend; /* set to x->x_blocksize / x->x_vecsize in udpsend_tilde_perform() */
- int x_blockssincesend;
-
- long x_samplerate; /* samplerate we're running at */
- int x_vecsize; /* current DSP signal vector size */
- int x_ninlets; /* number of inlets */
- int x_channels; /* number of channels we want to stream */
- int x_format; /* format of streamed audio data */
- int x_bitrate; /* specifies bitrate for compressed formats */
- int x_count; /* total number of audio frames */
- t_int **x_myvec; /* vector we pass on in the DSP routine */
-
- pthread_mutex_t x_mutex;
- pthread_cond_t x_requestcondition;
- pthread_cond_t x_answercondition;
- pthread_t x_childthread;
-} t_udpsend_tilde;
-
-/* function prototypes */
-static int udpsend_tilde_sockerror(char *s);
-static void udpsend_tilde_closesocket(int fd);
-static void udpsend_tilde_notify(t_udpsend_tilde *x);
-static void udpsend_tilde_disconnect(t_udpsend_tilde *x);
-static void *udpsend_tilde_doconnect(void *zz);
-static void udpsend_tilde_connect(t_udpsend_tilde *x, t_symbol *host, t_floatarg fportno);
-static t_int *udpsend_tilde_perform(t_int *w);
-static void udpsend_tilde_dsp(t_udpsend_tilde *x, t_signal **sp);
-static void udpsend_tilde_channels(t_udpsend_tilde *x, t_floatarg channels);
-static void udpsend_tilde_format(t_udpsend_tilde *x, t_symbol* form, t_floatarg bitrate);
-static void udpsend_tilde_float(t_udpsend_tilde* x, t_floatarg arg);
-static void udpsend_tilde_info(t_udpsend_tilde *x);
-static void *udpsend_tilde_new(t_floatarg inlets, t_floatarg blocksize);
-static void udpsend_tilde_free(t_udpsend_tilde* x);
-void udpsend_tilde_setup(void);
-
-/* functions */
-static void udpsend_tilde_notify(t_udpsend_tilde *x)
-{
- pthread_mutex_lock(&x->x_mutex);
- x->x_childthread = 0;
- outlet_float(x->x_outlet, x->x_connectstate);
- pthread_mutex_unlock(&x->x_mutex);
-}
-
-static void udpsend_tilde_disconnect(t_udpsend_tilde *x)
-{
- pthread_mutex_lock(&x->x_mutex);
- if (x->x_fd != -1)
- {
- udpsend_tilde_closesocket(x->x_fd);
- x->x_fd = -1;
- x->x_connectstate = 0;
- outlet_float(x->x_outlet, 0);
- }
- pthread_mutex_unlock(&x->x_mutex);
-}
-
-static void *udpsend_tilde_doconnect(void *zz)
-{
- t_udpsend_tilde *x = (t_udpsend_tilde *)zz;
- struct sockaddr_in server;
- struct hostent *hp;
- int intarg = 1;
- int sockfd;
- int portno;
- t_symbol *hostname;
-
- pthread_mutex_lock(&x->x_mutex);
- hostname = x->x_hostname;
- portno = x->x_portno;
- pthread_mutex_unlock(&x->x_mutex);
-
- /* create a socket */
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd < 0)
- {
- post("udpsend~: connection to %s on port %d failed", hostname->s_name,portno);
- udpsend_tilde_sockerror("socket");
- x->x_childthread = 0;
- return (0);
- }
-
- /* connect socket using hostname provided in command line */
- server.sin_family = AF_INET;
- hp = gethostbyname(x->x_hostname->s_name);
- if (hp == 0)
- {
- post("udpsend~: bad host?");
- x->x_childthread = 0;
- return (0);
- }
-
-#ifdef SO_PRIORITY
- /* set high priority, LINUX only */
- intarg = 6; /* select a priority between 0 and 7 */
- if (setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, (const char*)&intarg, sizeof(int)) < 0)
- {
- error("udpsend~: setsockopt(SO_PRIORITY) failed");
- }
-#endif
-
- memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
-
- /* assign client port number */
- server.sin_port = htons((unsigned short)portno);
-
- /* try to connect */
- if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
- {
- udpsend_tilde_sockerror("connecting stream socket");
- udpsend_tilde_closesocket(sockfd);
- x->x_childthread = 0;
- return (0);
- }
-
- post("udpsend~: connected host %s on port %d", hostname->s_name, portno);
-
- pthread_mutex_lock(&x->x_mutex);
- x->x_fd = sockfd;
- x->x_connectstate = 1;
- clock_delay(x->x_clock, 0);
- pthread_mutex_unlock(&x->x_mutex);
- return (0);
-}
-
-static void udpsend_tilde_connect(t_udpsend_tilde *x, t_symbol *host, t_floatarg fportno)
-{
- pthread_mutex_lock(&x->x_mutex);
- if (x->x_childthread != 0)
- {
- pthread_mutex_unlock(&x->x_mutex);
- post("udpsend~: already trying to connect");
- return;
- }
- if (x->x_fd != -1)
- {
- pthread_mutex_unlock(&x->x_mutex);
- post("udpsend~: already connected");
- return;
- }
-
- if (host != ps_nothing)
- x->x_hostname = host;
- else
- x->x_hostname = ps_localhost; /* default host */
-
- if (!fportno)
- x->x_portno = DEFAULT_PORT;
- else
- x->x_portno = (int)fportno;
- x->x_count = 0;
-
- /* start child thread to connect */
- pthread_create(&x->x_childthread, 0, udpsend_tilde_doconnect, x);
- pthread_mutex_unlock(&x->x_mutex);
-}
-
-static t_int *udpsend_tilde_perform(t_int *w)
-{
- t_udpsend_tilde* x = (t_udpsend_tilde*) (w[1]);
- int n = (int)(w[2]);
- t_float *in[DEFAULT_AUDIO_CHANNELS];
- const int offset = 3;
- char* bp = NULL;
- int i, length = x->x_blocksize * SF_SIZEOF(x->x_tag.format) * x->x_tag.channels;
- int sent = 0;
-
- pthread_mutex_lock(&x->x_mutex);
-
- for (i = 0; i < x->x_ninlets; i++)
- in[i] = (t_float *)(w[offset + i]);
-
- if (n != x->x_vecsize) /* resize buffer */
- {
- x->x_vecsize = n;
- x->x_blockspersend = x->x_blocksize / x->x_vecsize;
- x->x_blockssincesend = 0;
- length = x->x_blocksize * SF_SIZEOF(x->x_tag.format) * x->x_tag.channels;
- }
-
- /* format the buffer */
- switch (x->x_tag.format)
- {
- case SF_FLOAT:
- {
- t_float* fbuf = (t_float *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
- while (n--)
- for (i = 0; i < x->x_tag.channels; i++)
- *fbuf++ = *(in[i]++);
- break;
- }
- case SF_16BIT:
- {
- short* cibuf = (short *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
- while (n--)
- for (i = 0; i < x->x_tag.channels; i++)
- *cibuf++ = (short)lrint(32767.0 * *(in[i]++));
- break;
- }
- case SF_8BIT:
- {
- unsigned char* cbuf = (unsigned char*)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
- while (n--)
- for (i = 0; i < x->x_tag.channels; i++)
- *cbuf++ = (unsigned char)(128. * (1.0 + *(in[i]++)));
- break;
- }
- default:
- break;
- }
-
- if (!(x->x_blockssincesend < x->x_blockspersend - 1)) /* time to send the buffer */
- {
- x->x_blockssincesend = 0;
- x->x_count++; /* count data packet we're going to send */
-
- if (x->x_fd != -1)
- {
- bp = (char *)x->x_cbuf;
- /* fill in the header tag */
- x->x_tag.framesize = length;
- x->x_tag.count = x->x_count;
- /* send the format tag */
- if (send(x->x_fd, (char*)&x->x_tag, sizeof(t_tag), SEND_FLAGS) < 0)
- {
- udpsend_tilde_sockerror("send tag");
- pthread_mutex_unlock(&x->x_mutex);
- udpsend_tilde_disconnect(x);
- return (w + offset + x->x_ninlets);
+#include <math.h>
+#define SOCKET_ERROR -1
+#endif
+#ifdef _WIN32
+#include <winsock2.h>
+#include "pthread.h"
+#endif
+
+#ifdef MSG_NOSIGNAL
+#define SEND_FLAGS /*MSG_DONTWAIT|*/MSG_NOSIGNAL
+#else
+#define SEND_FLAGS 0
+#endif
+
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+
+
+/* ------------------------ udpsend~ ----------------------------- */
+
+static t_class *udpsend_tilde_class;
+
+static t_symbol *ps_nothing, *ps_localhost, *ps_vecsize;
+static t_symbol *ps_format, *ps_channels, *ps_framesize, *ps_overflow, *ps_underflow;
+static t_symbol *ps_queuesize, *ps_average, *ps_sf_float, *ps_sf_16bit, *ps_sf_8bit;
+static t_symbol *ps_sf_mp3, *ps_sf_aac, *ps_sf_unknown, *ps_bitrate, *ps_hostname;
+
+typedef struct _udpsend_tilde
+{
+ t_object x_obj;
+ t_outlet *x_outlet;
+ t_outlet *x_outlet2;
+ t_clock *x_clock;
+ int x_fd;
+ t_tag x_tag;
+ t_symbol* x_hostname;
+ int x_portno;
+ int x_connectstate;
+ char *x_cbuf;
+ int x_cbufsize;
+ int x_blocksize; /* set to DEFAULT_AUDIO_BUFFER_SIZE in udpsend_tilde_new() */
+ int x_blockspersend; /* set to x->x_blocksize / x->x_vecsize in udpsend_tilde_perform() */
+ int x_blockssincesend;
+
+ long x_samplerate; /* samplerate we're running at */
+ int x_vecsize; /* current DSP signal vector size */
+ int x_ninlets; /* number of inlets */
+ int x_channels; /* number of channels we want to stream */
+ int x_format; /* format of streamed audio data */
+ int x_bitrate; /* specifies bitrate for compressed formats */
+ int x_count; /* total number of audio frames */
+ t_int **x_myvec; /* vector we pass on in the DSP routine */
+
+ pthread_mutex_t x_mutex;
+ pthread_cond_t x_requestcondition;
+ pthread_cond_t x_answercondition;
+ pthread_t x_childthread;
+} t_udpsend_tilde;
+
+/* function prototypes */
+static int udpsend_tilde_sockerror(char *s);
+static void udpsend_tilde_closesocket(int fd);
+static void udpsend_tilde_notify(t_udpsend_tilde *x);
+static void udpsend_tilde_disconnect(t_udpsend_tilde *x);
+static void *udpsend_tilde_doconnect(void *zz);
+static void udpsend_tilde_connect(t_udpsend_tilde *x, t_symbol *host, t_floatarg fportno);
+static t_int *udpsend_tilde_perform(t_int *w);
+static void udpsend_tilde_dsp(t_udpsend_tilde *x, t_signal **sp);
+static void udpsend_tilde_channels(t_udpsend_tilde *x, t_floatarg channels);
+static void udpsend_tilde_format(t_udpsend_tilde *x, t_symbol* form, t_floatarg bitrate);
+static void udpsend_tilde_float(t_udpsend_tilde* x, t_floatarg arg);
+static void udpsend_tilde_info(t_udpsend_tilde *x);
+static void *udpsend_tilde_new(t_floatarg inlets, t_floatarg blocksize);
+static void udpsend_tilde_free(t_udpsend_tilde* x);
+void udpsend_tilde_setup(void);
+
+/* functions */
+static void udpsend_tilde_notify(t_udpsend_tilde *x)
+{
+ pthread_mutex_lock(&x->x_mutex);
+ x->x_childthread = 0;
+ outlet_float(x->x_outlet, x->x_connectstate);
+ pthread_mutex_unlock(&x->x_mutex);
+}
+
+static void udpsend_tilde_disconnect(t_udpsend_tilde *x)
+{
+ pthread_mutex_lock(&x->x_mutex);
+ if (x->x_fd != -1)
+ {
+ udpsend_tilde_closesocket(x->x_fd);
+ x->x_fd = -1;
+ x->x_connectstate = 0;
+ outlet_float(x->x_outlet, 0);
+ }
+ pthread_mutex_unlock(&x->x_mutex);
+}
+
+static void *udpsend_tilde_doconnect(void *zz)
+{
+ t_udpsend_tilde *x = (t_udpsend_tilde *)zz;
+ struct sockaddr_in server;
+ struct hostent *hp;
+ int intarg = 1;
+ int sockfd;
+ int portno;
+ t_symbol *hostname;
+
+ pthread_mutex_lock(&x->x_mutex);
+ hostname = x->x_hostname;
+ portno = x->x_portno;
+ pthread_mutex_unlock(&x->x_mutex);
+
+ /* create a socket */
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ post("udpsend~: connection to %s on port %d failed", hostname->s_name,portno);
+ udpsend_tilde_sockerror("socket");
+ x->x_childthread = 0;
+ return (0);
+ }
+
+ /* connect socket using hostname provided in command line */
+ server.sin_family = AF_INET;
+ hp = gethostbyname(x->x_hostname->s_name);
+ if (hp == 0)
+ {
+ post("udpsend~: bad host?");
+ x->x_childthread = 0;
+ return (0);
+ }
+
+#ifdef SO_PRIORITY
+ /* set high priority, LINUX only */
+ intarg = 6; /* select a priority between 0 and 7 */
+ if (setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, (const char*)&intarg, sizeof(int)) < 0)
+ {
+ error("udpsend~: setsockopt(SO_PRIORITY) failed");
+ }
+#endif
+
+ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+
+ /* assign client port number */
+ server.sin_port = htons((unsigned short)portno);
+
+ /* try to connect */
+ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
+ {
+ udpsend_tilde_sockerror("connecting stream socket");
+ udpsend_tilde_closesocket(sockfd);
+ x->x_childthread = 0;
+ return (0);
+ }
+
+ post("udpsend~: connected host %s on port %d", hostname->s_name, portno);
+
+ pthread_mutex_lock(&x->x_mutex);
+ x->x_fd = sockfd;
+ x->x_connectstate = 1;
+ clock_delay(x->x_clock, 0);
+ pthread_mutex_unlock(&x->x_mutex);
+ return (0);
+}
+
+static void udpsend_tilde_connect(t_udpsend_tilde *x, t_symbol *host, t_floatarg fportno)
+{
+ pthread_mutex_lock(&x->x_mutex);
+ if (x->x_childthread != 0)
+ {
+ pthread_mutex_unlock(&x->x_mutex);
+ post("udpsend~: already trying to connect");
+ return;
+ }
+ if (x->x_fd != -1)
+ {
+ pthread_mutex_unlock(&x->x_mutex);
+ post("udpsend~: already connected");
+ return;
+ }
+
+ if (host != ps_nothing)
+ x->x_hostname = host;
+ else
+ x->x_hostname = ps_localhost; /* default host */
+
+ if (!fportno)
+ x->x_portno = DEFAULT_PORT;
+ else
+ x->x_portno = (int)fportno;
+ x->x_count = 0;
+
+ /* start child thread to connect */
+ pthread_create(&x->x_childthread, 0, udpsend_tilde_doconnect, x);
+ pthread_mutex_unlock(&x->x_mutex);
+}
+
+static t_int *udpsend_tilde_perform(t_int *w)
+{
+ t_udpsend_tilde* x = (t_udpsend_tilde*) (w[1]);
+ int n = (int)(w[2]);
+ t_float *in[DEFAULT_AUDIO_CHANNELS];
+ const int offset = 3;
+ char* bp = NULL;
+ int i, length = x->x_blocksize * SF_SIZEOF(x->x_tag.format) * x->x_tag.channels;
+ int sent = 0;
+
+ pthread_mutex_lock(&x->x_mutex);
+
+ for (i = 0; i < x->x_ninlets; i++)
+ in[i] = (t_float *)(w[offset + i]);
+
+ if (n != x->x_vecsize) /* resize buffer */
+ {
+ x->x_vecsize = n;
+ x->x_blockspersend = x->x_blocksize / x->x_vecsize;
+ x->x_blockssincesend = 0;
+ length = x->x_blocksize * SF_SIZEOF(x->x_tag.format) * x->x_tag.channels;
+ }
+
+ /* format the buffer */
+ switch (x->x_tag.format)
+ {
+ case SF_FLOAT:
+ {
+ t_float* fbuf = (t_float *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+ while (n--)
+ for (i = 0; i < x->x_tag.channels; i++)
+ *fbuf++ = *(in[i]++);
+ break;
+ }
+ case SF_16BIT:
+ {
+ short* cibuf = (short *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+ while (n--)
+ for (i = 0; i < x->x_tag.channels; i++)
+ *cibuf++ = (short)lrint(32767.0 * *(in[i]++));
+ break;
+ }
+ case SF_8BIT:
+ {
+ unsigned char* cbuf = (unsigned char*)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+ while (n--)
+ for (i = 0; i < x->x_tag.channels; i++)
+ *cbuf++ = (unsigned char)(128. * (1.0 + *(in[i]++)));
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!(x->x_blockssincesend < x->x_blockspersend - 1)) /* time to send the buffer */
+ {
+ x->x_blockssincesend = 0;
+ x->x_count++; /* count data packet we're going to send */
+
+ if (x->x_fd != -1)
+ {
+ bp = (char *)x->x_cbuf;
+ /* fill in the header tag */
+ x->x_tag.framesize = length;
+ x->x_tag.count = x->x_count;
+ /* send the format tag */
+ if (send(x->x_fd, (char*)&x->x_tag, sizeof(t_tag), SEND_FLAGS) < 0)
+ {
+ udpsend_tilde_sockerror("send tag");
+ pthread_mutex_unlock(&x->x_mutex);
+ udpsend_tilde_disconnect(x);
+ return (w + offset + x->x_ninlets);
}
if (length != 0)
-/* UDP: max. packet size is 64k (incl. headers) so we have to split */
- {
-#ifdef __APPLE__
- /* WARNING: due to a 'bug' (maybe Apple would call it a feature?) in OS X
- send calls with data packets larger than 16k fail with error number 40!
- Thus we have to split the data packets into several packets that are
- 16k in size. The other side will reassemble them again. */
- int size = DEFAULT_UDP_PACKT_SIZE;
- if (length < size) /* maybe data fits into one packet? */
- size = length;
- /* send the buffer */
- for (sent = 0; sent < length;)
- {
- int ret = 0;
- ret = send(x->x_fd, bp, size, SEND_FLAGS);
- if (ret <= 0)
- {
- udpsend_tilde_sockerror("send data");
- pthread_mutex_unlock(&x->x_mutex);
- udpsend_tilde_disconnect(x);
- return (w + offset + x->x_ninlets);
- }
- else
- {
- bp += ret;
- sent += ret;
- if ((length - sent) < size)
- size = length - sent;
- }
- }
-#else
- /* If there is any data, send the buffer, the OS might segment it into smaller packets */
- int ret = send(x->x_fd, bp, length, SEND_FLAGS);
- if (ret <= 0)
+/* UDP: max. packet size is 64k (incl. headers) so we have to split */
+ {
+#ifdef __APPLE__
+ /* WARNING: due to a 'bug' (maybe Apple would call it a feature?) in OS X
+ send calls with data packets larger than 16k fail with error number 40!
+ Thus we have to split the data packets into several packets that are
+ 16k in size. The other side will reassemble them again. */
+ int size = DEFAULT_UDP_PACKT_SIZE;
+ if (length < size) /* maybe data fits into one packet? */
+ size = length;
+ /* send the buffer */
+ for (sent = 0; sent < length;)
+ {
+ int ret = 0;
+ ret = send(x->x_fd, bp, size, SEND_FLAGS);
+ if (ret <= 0)
+ {
+ udpsend_tilde_sockerror("send data");
+ pthread_mutex_unlock(&x->x_mutex);
+ udpsend_tilde_disconnect(x);
+ return (w + offset + x->x_ninlets);
+ }
+ else
+ {
+ bp += ret;
+ sent += ret;
+ if ((length - sent) < size)
+ size = length - sent;
+ }
+ }
+#else
+ /* If there is any data, send the buffer, the OS might segment it into smaller packets */
+ int ret = send(x->x_fd, bp, length, SEND_FLAGS);
+ if (ret <= 0)
{
- post ("length %ld", length);
- udpsend_tilde_sockerror("send data");
- pthread_mutex_unlock(&x->x_mutex);
- udpsend_tilde_disconnect(x);
- return (w + offset + x->x_ninlets);
- }
-#endif
- }
- }
-
-/* check whether user has updated any parameters */
- if (x->x_tag.channels != x->x_channels)
- {
- x->x_tag.channels = x->x_channels;
- }
- if (x->x_tag.format != x->x_format)
- {
- x->x_tag.format = x->x_format;
- }
- }
- else
- {
- x->x_blockssincesend++;
- }
- pthread_mutex_unlock(&x->x_mutex);
- return (w + offset + x->x_ninlets);
-}
-
-static void udpsend_tilde_dsp(t_udpsend_tilde *x, t_signal **sp)
-{
- int i;
-
- pthread_mutex_lock(&x->x_mutex);
-
- x->x_myvec[0] = (t_int*)x;
- x->x_myvec[1] = (t_int*)sp[0]->s_n;
-
- x->x_samplerate = sp[0]->s_sr;
-
- for (i = 0; i < x->x_ninlets; i++)
- {
- x->x_myvec[2 + i] = (t_int*)sp[i]->s_vec;
- }
-
- pthread_mutex_unlock(&x->x_mutex);
-
- if (DEFAULT_AUDIO_BUFFER_SIZE % sp[0]->s_n)
- {
- error("udpsend~: signal vector size too large (needs to be even divisor of %d)", DEFAULT_AUDIO_BUFFER_SIZE);
- }
- else
- {
- dsp_addv(udpsend_tilde_perform, x->x_ninlets + 2, (t_int*)x->x_myvec);
- }
-}
-
-static void udpsend_tilde_channels(t_udpsend_tilde *x, t_floatarg channels)
-{
- pthread_mutex_lock(&x->x_mutex);
- if (channels >= 0 && channels <= x->x_ninlets)
- {
- x->x_channels = (int)channels;
- post("udpsend~: channels set to %d", (int)channels);
- }
+ post ("length %ld", length);
+ udpsend_tilde_sockerror("send data");
+ pthread_mutex_unlock(&x->x_mutex);
+ udpsend_tilde_disconnect(x);
+ return (w + offset + x->x_ninlets);
+ }
+#endif
+ }
+ }
+
+/* check whether user has updated any parameters */
+ if (x->x_tag.channels != x->x_channels)
+ {
+ x->x_tag.channels = x->x_channels;
+ }
+ if (x->x_tag.format != x->x_format)
+ {
+ x->x_tag.format = x->x_format;
+ }
+ }
+ else
+ {
+ x->x_blockssincesend++;
+ }
+ pthread_mutex_unlock(&x->x_mutex);
+ return (w + offset + x->x_ninlets);
+}
+
+static void udpsend_tilde_dsp(t_udpsend_tilde *x, t_signal **sp)
+{
+ int i;
+
+ pthread_mutex_lock(&x->x_mutex);
+
+ x->x_myvec[0] = (t_int*)x;
+ x->x_myvec[1] = (t_int*)sp[0]->s_n;
+
+ x->x_samplerate = sp[0]->s_sr;
+
+ for (i = 0; i < x->x_ninlets; i++)
+ {
+ x->x_myvec[2 + i] = (t_int*)sp[i]->s_vec;
+ }
+
+ pthread_mutex_unlock(&x->x_mutex);
+
+ if (DEFAULT_AUDIO_BUFFER_SIZE % sp[0]->s_n)
+ {
+ error("udpsend~: signal vector size too large (needs to be even divisor of %d)", DEFAULT_AUDIO_BUFFER_SIZE);
+ }
+ else
+ {
+ dsp_addv(udpsend_tilde_perform, x->x_ninlets + 2, (t_int*)x->x_myvec);
+ }
+}
+
+static void udpsend_tilde_channels(t_udpsend_tilde *x, t_floatarg channels)
+{
+ pthread_mutex_lock(&x->x_mutex);
+ if (channels >= 0 && channels <= x->x_ninlets)
+ {
+ x->x_channels = (int)channels;
+ post("udpsend~: channels set to %d", (int)channels);
+ }
else post ("udpsend~ number of channels must be between 0 and %d", x->x_ninlets);
- pthread_mutex_unlock(&x->x_mutex);
-}
-
-static void udpsend_tilde_format(t_udpsend_tilde *x, t_symbol* form, t_floatarg bitrate)
-{
- pthread_mutex_lock(&x->x_mutex);
- if (!strncmp(form->s_name,"float", 5) && x->x_tag.format != SF_FLOAT)
- {
- x->x_format = (int)SF_FLOAT;
- }
- else if (!strncmp(form->s_name,"16bit", 5) && x->x_tag.format != SF_16BIT)
- {
- x->x_format = (int)SF_16BIT;
- }
- else if (!strncmp(form->s_name,"8bit", 4) && x->x_tag.format != SF_8BIT)
- {
- x->x_format = (int)SF_8BIT;
- }
-
- post("udpsend~: format set to %s", form->s_name);
- pthread_mutex_unlock(&x->x_mutex);
-}
-
-static void udpsend_tilde_float(t_udpsend_tilde* x, t_floatarg arg)
-{
- if (arg == 0.0)
- udpsend_tilde_disconnect(x);
- else
- udpsend_tilde_connect(x,x->x_hostname,(float) x->x_portno);
-}
-
-/* send stream info */
-static void udpsend_tilde_info(t_udpsend_tilde *x)
-{
- t_atom list[2];
- t_symbol *sf_format;
- t_float bitrate;
-
- bitrate = (t_float)((SF_SIZEOF(x->x_tag.format) * x->x_samplerate * 8 * x->x_tag.channels) / 1000.);
-
- switch (x->x_tag.format)
- {
- case SF_FLOAT:
- {
- sf_format = ps_sf_float;
- break;
- }
- case SF_16BIT:
- {
- sf_format = ps_sf_16bit;
- break;
- }
- case SF_8BIT:
- {
- sf_format = ps_sf_8bit;
- break;
- }
- default:
- {
- sf_format = ps_sf_unknown;
- break;
- }
- }
-
- /* --- stream information (t_tag) --- */
-
- /* audio format */
- SETSYMBOL(list, (t_symbol *)sf_format);
- outlet_anything(x->x_outlet2, ps_format, 1, list);
-
- /* channels */
- SETFLOAT(list, (t_float)x->x_tag.channels);
- outlet_anything(x->x_outlet2, ps_channels, 1, list);
-
+ pthread_mutex_unlock(&x->x_mutex);
+}
+
+static void udpsend_tilde_format(t_udpsend_tilde *x, t_symbol* form, t_floatarg bitrate)
+{
+ pthread_mutex_lock(&x->x_mutex);
+ if (!strncmp(form->s_name,"float", 5) && x->x_tag.format != SF_FLOAT)
+ {
+ x->x_format = (int)SF_FLOAT;
+ }
+ else if (!strncmp(form->s_name,"16bit", 5) && x->x_tag.format != SF_16BIT)
+ {
+ x->x_format = (int)SF_16BIT;
+ }
+ else if (!strncmp(form->s_name,"8bit", 4) && x->x_tag.format != SF_8BIT)
+ {
+ x->x_format = (int)SF_8BIT;
+ }
+
+ post("udpsend~: format set to %s", form->s_name);
+ pthread_mutex_unlock(&x->x_mutex);
+}
+
+static void udpsend_tilde_float(t_udpsend_tilde* x, t_floatarg arg)
+{
+ if (arg == 0.0)
+ udpsend_tilde_disconnect(x);
+ else
+ udpsend_tilde_connect(x,x->x_hostname,(float) x->x_portno);
+}
+
+/* send stream info */
+static void udpsend_tilde_info(t_udpsend_tilde *x)
+{
+ t_atom list[2];
+ t_symbol *sf_format;
+ t_float bitrate;
+
+ bitrate = (t_float)((SF_SIZEOF(x->x_tag.format) * x->x_samplerate * 8 * x->x_tag.channels) / 1000.);
+
+ switch (x->x_tag.format)
+ {
+ case SF_FLOAT:
+ {
+ sf_format = ps_sf_float;
+ break;
+ }
+ case SF_16BIT:
+ {
+ sf_format = ps_sf_16bit;
+ break;
+ }
+ case SF_8BIT:
+ {
+ sf_format = ps_sf_8bit;
+ break;
+ }
+ default:
+ {
+ sf_format = ps_sf_unknown;
+ break;
+ }
+ }
+
+ /* --- stream information (t_tag) --- */
+
+ /* audio format */
+ SETSYMBOL(list, (t_symbol *)sf_format);
+ outlet_anything(x->x_outlet2, ps_format, 1, list);
+
+ /* channels */
+ SETFLOAT(list, (t_float)x->x_tag.channels);
+ outlet_anything(x->x_outlet2, ps_channels, 1, list);
+
/* current signal vector size */
- SETFLOAT(list, (t_float)x->x_vecsize);
- outlet_anything(x->x_outlet2, ps_vecsize, 1, list);
-
- /* framesize */
- SETFLOAT(list, (t_float)x->x_tag.framesize);
- outlet_anything(x->x_outlet2, ps_framesize, 1, list);
-
- /* bitrate */
- SETFLOAT(list, (t_float)bitrate);
- outlet_anything(x->x_outlet2, ps_bitrate, 1, list);
-
- /* IP address */
- SETSYMBOL(list, (t_symbol *)x->x_hostname);
- outlet_anything(x->x_outlet2, ps_hostname, 1, list);
-}
-
-static void *udpsend_tilde_new(t_floatarg inlets, t_floatarg blocksize)
-{
- int i;
-
- t_udpsend_tilde *x = (t_udpsend_tilde *)pd_new(udpsend_tilde_class);
- if (x)
- {
- for (i = sizeof(t_object); i < (int)sizeof(t_udpsend_tilde); i++)
- ((char *)x)[i] = 0;
+ SETFLOAT(list, (t_float)x->x_vecsize);
+ outlet_anything(x->x_outlet2, ps_vecsize, 1, list);
+
+ /* framesize */
+ SETFLOAT(list, (t_float)x->x_tag.framesize);
+ outlet_anything(x->x_outlet2, ps_framesize, 1, list);
+
+ /* bitrate */
+ SETFLOAT(list, (t_float)bitrate);
+ outlet_anything(x->x_outlet2, ps_bitrate, 1, list);
+
+ /* IP address */
+ SETSYMBOL(list, (t_symbol *)x->x_hostname);
+ outlet_anything(x->x_outlet2, ps_hostname, 1, list);
+}
+
+static void *udpsend_tilde_new(t_floatarg inlets, t_floatarg blocksize)
+{
+ int i;
+
+ t_udpsend_tilde *x = (t_udpsend_tilde *)pd_new(udpsend_tilde_class);
+ if (x)
+ {
+ for (i = sizeof(t_object); i < (int)sizeof(t_udpsend_tilde); i++)
+ ((char *)x)[i] = 0;
if ((int)inlets < 1 || (int)inlets > DEFAULT_AUDIO_CHANNELS)
{
error("udpsend~: Number of channels must be between 1 and %d", DEFAULT_AUDIO_CHANNELS);
- return NULL;
- }
- x->x_ninlets = (int)inlets;
- for (i = 1; i < x->x_ninlets; i++)
- inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
-
- x->x_outlet = outlet_new(&x->x_obj, &s_float);
- x->x_outlet2 = outlet_new(&x->x_obj, &s_list);
- x->x_clock = clock_new(x, (t_method)udpsend_tilde_notify);
-
- x->x_myvec = (t_int **)t_getbytes(sizeof(t_int *) * (x->x_ninlets + 3));
- if (!x->x_myvec)
- {
- error("udpsend~: out of memory");
- return NULL;
- }
-
- pthread_mutex_init(&x->x_mutex, 0);
- pthread_cond_init(&x->x_requestcondition, 0);
- pthread_cond_init(&x->x_answercondition, 0);
-
- x->x_hostname = ps_localhost;
- x->x_portno = DEFAULT_PORT;
- x->x_connectstate = 0;
- x->x_childthread = 0;
- x->x_fd = -1;
-
- x->x_tag.format = x->x_format = SF_FLOAT;
- x->x_tag.channels = x->x_channels = x->x_ninlets;
- x->x_tag.version = SF_BYTE_NATIVE; /* native endianness */
- x->x_vecsize = 64; /* this is updated in the perform routine udpsend_tilde_perform */
- x->x_bitrate = 0; /* not specified, use default */
+ return NULL;
+ }
+ x->x_ninlets = (int)inlets;
+ for (i = 1; i < x->x_ninlets; i++)
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+
+ x->x_outlet = outlet_new(&x->x_obj, &s_float);
+ x->x_outlet2 = outlet_new(&x->x_obj, &s_list);
+ x->x_clock = clock_new(x, (t_method)udpsend_tilde_notify);
+
+ x->x_myvec = (t_int **)t_getbytes(sizeof(t_int *) * (x->x_ninlets + 3));
+ if (!x->x_myvec)
+ {
+ error("udpsend~: out of memory");
+ return NULL;
+ }
+
+ pthread_mutex_init(&x->x_mutex, 0);
+ pthread_cond_init(&x->x_requestcondition, 0);
+ pthread_cond_init(&x->x_answercondition, 0);
+
+ x->x_hostname = ps_localhost;
+ x->x_portno = DEFAULT_PORT;
+ x->x_connectstate = 0;
+ x->x_childthread = 0;
+ x->x_fd = -1;
+
+ x->x_tag.format = x->x_format = SF_FLOAT;
+ x->x_tag.channels = x->x_channels = x->x_ninlets;
+ x->x_tag.version = SF_BYTE_NATIVE; /* native endianness */
+ x->x_vecsize = 64; /* this is updated in the perform routine udpsend_tilde_perform */
+ x->x_bitrate = 0; /* not specified, use default */
x->x_cbuf = NULL;
if (blocksize == 0) x->x_blocksize = DEFAULT_AUDIO_BUFFER_SIZE;
else if (DEFAULT_AUDIO_BUFFER_SIZE%(int)blocksize)
{
- error("udpsend~: blocksize must fit snugly in %d", DEFAULT_AUDIO_BUFFER_SIZE);
- return NULL;
- }
- else x->x_blocksize = (int)blocksize; //DEFAULT_AUDIO_BUFFER_SIZE; /* <-- the only place blocksize is set */
- x->x_blockspersend = x->x_blocksize / x->x_vecsize; /* 1024/64 = 16 blocks */
- x->x_blockssincesend = 0;
- x->x_cbufsize = x->x_blocksize * sizeof(t_float) * x->x_ninlets;
- x->x_cbuf = (char *)t_getbytes(x->x_cbufsize);
-
-#if defined(UNIX) || defined(unix)
- /* we don't want to get signaled in case send() fails */
- signal(SIGPIPE, SIG_IGN);
-#endif
- }
-
- return (x);
-}
-
-static void udpsend_tilde_free(t_udpsend_tilde* x)
-{
- udpsend_tilde_disconnect(x);
-
- /* free the memory */
- if (x->x_cbuf)t_freebytes(x->x_cbuf, x->x_cbufsize);
- if (x->x_myvec)t_freebytes(x->x_myvec, sizeof(t_int) * (x->x_ninlets + 3));
-
- clock_free(x->x_clock);
-
- pthread_cond_destroy(&x->x_requestcondition);
- pthread_cond_destroy(&x->x_answercondition);
- pthread_mutex_destroy(&x->x_mutex);
-}
-
-void udpsend_tilde_setup(void)
-{
- udpsend_tilde_class = class_new(gensym("udpsend~"), (t_newmethod)udpsend_tilde_new, (t_method)udpsend_tilde_free,
- sizeof(t_udpsend_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
- class_addmethod(udpsend_tilde_class, nullfn, gensym("signal"), 0);
- class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_dsp, gensym("dsp"), 0);
- class_addfloat(udpsend_tilde_class, udpsend_tilde_float);
- class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_info, gensym("info"), 0);
- class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_connect, gensym("connect"), A_DEFSYM, A_DEFFLOAT, 0);
- class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_disconnect, gensym("disconnect"), 0);
- class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_channels, gensym("channels"), A_FLOAT, 0);
- class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_format, gensym("format"), A_SYMBOL, A_DEFFLOAT, 0);
- class_sethelpsymbol(udpsend_tilde_class, gensym("udpsend~"));
- post("udpsend~ v%s, (c) 2004-2005 Olaf Matthes, 2010 Martin Peach", VERSION);
- post("udpsend~ Default blocksize is %d", DEFAULT_AUDIO_BUFFER_SIZE);
-
- ps_nothing = gensym("");
- ps_localhost = gensym("localhost");
- ps_hostname = gensym("ipaddr");
- ps_format = gensym("format");
+ error("udpsend~: blocksize must fit snugly in %d", DEFAULT_AUDIO_BUFFER_SIZE);
+ return NULL;
+ }
+ else x->x_blocksize = (int)blocksize; //DEFAULT_AUDIO_BUFFER_SIZE; /* <-- the only place blocksize is set */
+ x->x_blockspersend = x->x_blocksize / x->x_vecsize; /* 1024/64 = 16 blocks */
+ x->x_blockssincesend = 0;
+ x->x_cbufsize = x->x_blocksize * sizeof(t_float) * x->x_ninlets;
+ x->x_cbuf = (char *)t_getbytes(x->x_cbufsize);
+
+#if defined(UNIX) || defined(unix)
+ /* we don't want to get signaled in case send() fails */
+ signal(SIGPIPE, SIG_IGN);
+#endif
+ }
+
+ return (x);
+}
+
+static void udpsend_tilde_free(t_udpsend_tilde* x)
+{
+ udpsend_tilde_disconnect(x);
+
+ /* free the memory */
+ if (x->x_cbuf)t_freebytes(x->x_cbuf, x->x_cbufsize);
+ if (x->x_myvec)t_freebytes(x->x_myvec, sizeof(t_int) * (x->x_ninlets + 3));
+
+ clock_free(x->x_clock);
+
+ pthread_cond_destroy(&x->x_requestcondition);
+ pthread_cond_destroy(&x->x_answercondition);
+ pthread_mutex_destroy(&x->x_mutex);
+}
+
+void udpsend_tilde_setup(void)
+{
+ udpsend_tilde_class = class_new(gensym("udpsend~"), (t_newmethod)udpsend_tilde_new, (t_method)udpsend_tilde_free,
+ sizeof(t_udpsend_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+ class_addmethod(udpsend_tilde_class, nullfn, gensym("signal"), 0);
+ class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_dsp, gensym("dsp"), 0);
+ class_addfloat(udpsend_tilde_class, udpsend_tilde_float);
+ class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_info, gensym("info"), 0);
+ class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_connect, gensym("connect"), A_DEFSYM, A_DEFFLOAT, 0);
+ class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_disconnect, gensym("disconnect"), 0);
+ class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_channels, gensym("channels"), A_FLOAT, 0);
+ class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_format, gensym("format"), A_SYMBOL, A_DEFFLOAT, 0);
+ class_sethelpsymbol(udpsend_tilde_class, gensym("udpsend~"));
+ post("udpsend~ v%s, (c) 2004-2005 Olaf Matthes, 2010 Martin Peach", VERSION);
+ post("udpsend~ Default blocksize is %d", DEFAULT_AUDIO_BUFFER_SIZE);
+
+ ps_nothing = gensym("");
+ ps_localhost = gensym("localhost");
+ ps_hostname = gensym("ipaddr");
+ ps_format = gensym("format");
ps_channels = gensym("channels");
- ps_vecsize = gensym("vecsize");
- ps_framesize = gensym("framesize");
- ps_bitrate = gensym("bitrate");
- ps_sf_float = gensym("_float_");
- ps_sf_16bit = gensym("_16bit_");
- ps_sf_8bit = gensym("_8bit_");
- ps_sf_unknown = gensym("_unknown_");
-}
-
-/* Utility functions */
-
-static int udpsend_tilde_sockerror(char *s)
-{
-#ifdef _WIN32
- int err = WSAGetLastError();
- if (err == 10054) return 1;
- else if (err == 10053) post("udpsend~: %s: software caused connection abort (%d)", s, err);
- else if (err == 10055) post("udpsend~: %s: no buffer space available (%d)", s, err);
- else if (err == 10060) post("udpsend~: %s: connection timed out (%d)", s, err);
- else if (err == 10061) post("udpsend~: %s: connection refused (%d)", s, err);
- else post("udpsend~: %s: %s (%d)", s, strerror(err), err);
-#else
- int err = errno;
- post("udpsend~: %s: %s (%d)", s, strerror(err), err);
-#endif
-#ifdef _WIN32
- if (err == WSAEWOULDBLOCK)
-#endif
-#if defined(UNIX) || defined(unix)
- if (err == EAGAIN)
-#endif
- {
- return 1; /* recoverable error */
- }
- return 0; /* indicate non-recoverable error */
-}
-
-static void udpsend_tilde_closesocket(int fd)
-{
-#if defined(UNIX) || defined(unix)
- close(fd);
-#endif
-#ifdef _WIN32
- closesocket(fd);
-#endif
-}
-
-/* fin udpsend~.c */
+ ps_vecsize = gensym("vecsize");
+ ps_framesize = gensym("framesize");
+ ps_bitrate = gensym("bitrate");
+ ps_sf_float = gensym("_float_");
+ ps_sf_16bit = gensym("_16bit_");
+ ps_sf_8bit = gensym("_8bit_");
+ ps_sf_unknown = gensym("_unknown_");
+}
+
+/* Utility functions */
+
+static int udpsend_tilde_sockerror(char *s)
+{
+#ifdef _WIN32
+ int err = WSAGetLastError();
+ if (err == 10054) return 1;
+ else if (err == 10053) post("udpsend~: %s: software caused connection abort (%d)", s, err);
+ else if (err == 10055) post("udpsend~: %s: no buffer space available (%d)", s, err);
+ else if (err == 10060) post("udpsend~: %s: connection timed out (%d)", s, err);
+ else if (err == 10061) post("udpsend~: %s: connection refused (%d)", s, err);
+ else post("udpsend~: %s: %s (%d)", s, strerror(err), err);
+#else
+ int err = errno;
+ post("udpsend~: %s: %s (%d)", s, strerror(err), err);
+#endif
+#ifdef _WIN32
+ if (err == WSAEWOULDBLOCK)
+#endif
+#if defined(UNIX) || defined(unix)
+ if (err == EAGAIN)
+#endif
+ {
+ return 1; /* recoverable error */
+ }
+ return 0; /* indicate non-recoverable error */
+}
+
+static void udpsend_tilde_closesocket(int fd)
+{
+#if defined(UNIX) || defined(unix)
+ close(fd);
+#endif
+#ifdef _WIN32
+ closesocket(fd);
+#endif
+}
+
+/* fin udpsend~.c */