diff options
| author | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-07-03 22:16:11 +0000 |
|---|---|---|
| committer | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-07-03 22:16:11 +0000 |
| commit | 0d4560cb0305029fa5f0739670286176ab47cb65 (patch) | |
| tree | 9899f4324664a77e6a5884fdd1541818a28a2172 /apps/plugins/pdbox/PDa/extra/dumpOSC.c | |
| parent | eabeb928ddfdbe5fc6379efb87d9522803310649 (diff) | |
| download | rockbox-0d4560cb0305029fa5f0739670286176ab47cb65.zip rockbox-0d4560cb0305029fa5f0739670286176ab47cb65.tar.gz rockbox-0d4560cb0305029fa5f0739670286176ab47cb65.tar.bz2 rockbox-0d4560cb0305029fa5f0739670286176ab47cb65.tar.xz | |
Accept FS #10244 by Wincent Balin: more pdbox work done for GSoC; also some keyword and line-ending fixes by me
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21626 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/dumpOSC.c')
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/dumpOSC.c | 1998 |
1 files changed, 999 insertions, 999 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/dumpOSC.c b/apps/plugins/pdbox/PDa/extra/dumpOSC.c index 28b0d82..4e80de1 100644 --- a/apps/plugins/pdbox/PDa/extra/dumpOSC.c +++ b/apps/plugins/pdbox/PDa/extra/dumpOSC.c @@ -1,1000 +1,1000 @@ -/*
-Written by Matt Wright and Adrian Freed, The Center for New Music and
-Audio Technologies, University of California, Berkeley. Copyright (c)
-1992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of
-California (Regents).
-
-Permission to use, copy, modify, distribute, and distribute modified versions
-of this software and its documentation without fee and without a signed
-licensing agreement, is hereby granted, provided that the above copyright
-notice, this paragraph and the following two paragraphs appear in all copies,
-modifications, and distributions.
-
-IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
-SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
-OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
-BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
-HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
-MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-
-
-The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
-*/
-
-
- /*
-
- dumpOSC.c
- server that displays OpenSoundControl messages sent to it
- for debugging client udp and UNIX protocol
-
- by Matt Wright, 6/3/97
- modified from dumpSC.c, by Matt Wright and Adrian Freed
-
- version 0.2: Added "-silent" option a.k.a. "-quiet"
-
- version 0.3: Incorporated patches from Nicola Bernardini to make
- things Linux-friendly. Also added ntohl() in the right places
- to support little-endian architectures.
-
-
-
- compile:
- cc -o dumpOSC dumpOSC.c
-
- to-do:
-
- More robustness in saying exactly what's wrong with ill-formed
- messages. (If they don't make sense, show exactly what was
- received.)
-
- Time-based features: print time-received for each packet
-
- Clean up to separate OSC parsing code from socket/select stuff
-
- pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c
- -------------
- -- added pd functions
- -- socket is made differently than original via pd mechanisms
- -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
- -- the OSX changes from cnmat didnt make it here yet but this compiles
- on OSX anyway.
-
-*/
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "m_pd.h"
-//#include "m_imp.h"
-#include "s_stuff.h"
-
-/* declarations */
-
-// typedef void (*t_fdpollfn)(void *ptr, int fd);
-void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
-
-
-#if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__)
-
-#ifdef WIN32
- #include "OSC-common.h"
- #include <winsock2.h>
- #include <string.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <ctype.h>
- #include <signal.h>
-#else
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <netinet/in.h>
- #include <rpc/rpc.h>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <sys/times.h>
- #include <sys/param.h>
- #include <sys/time.h>
- #include <sys/ioctl.h>
- #include <ctype.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <pwd.h>
- #include <signal.h>
- #include <grp.h>
- #include <sys/file.h>
- //#include <sys/prctl.h>
-
- #ifdef NEED_SCHEDCTL_AND_LOCK
- #include <sys/schedctl.h>
- #include <sys/lock.h>
- #endif
-#endif
-
-
-char *htm_error_string;
-typedef int Boolean;
-typedef void *OBJ;
-
-typedef struct ClientAddressStruct {
- struct sockaddr_in cl_addr;
- int clilen;
- int sockfd;
-} *ClientAddr;
-
-typedef unsigned long long osc_time_t;
-
-Boolean ShowBytes = FALSE;
-Boolean Silent = FALSE;
-
-/* Declarations */
-#ifndef WIN32
-static int unixinitudp(int chan);
-#endif
-
-static int initudp(int chan);
-static void closeudp(int sockfd);
-Boolean ClientReply(int packetsize, void *packet, int socketfd,
- void *clientaddresspointer, int clientaddressbufferlength);
-void sgi_CleanExit(void);
-Boolean sgi_HaveToQuit(void);
-int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy);
-static void catch_sigint();
-static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ;
-char *DataAfterAlignedString(char *string, char *boundary) ;
-Boolean IsNiceString(char *string, char *boundary) ;
-void complain(char *s, ...);
-
-#define MAXMESG 32768
-static char mbuf[MAXMESG];
-
-/* ----------------------------- dumpOSC ------------------------- */
-
-#define MAXOUTAT 50
-
-static t_class *dumpOSC_class;
-
-typedef struct _dumpOSC
-{
- t_object x_obj;
- t_outlet *x_msgout;
- t_outlet *x_connectout;
- t_atom x_outat[MAXOUTAT];
- int x_outatc;
- t_binbuf *x_b;
- int x_connectsocket;
- int x_nconnections;
- int x_udp;
- struct sockaddr_in x_server;
- int x_clilen;
-} t_dumpOSC;
-
-void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr);
-Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd);
-static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr);
-static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n);
-static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma);
-
-static void dumpOSC_read(t_dumpOSC *x, int sockfd) {
- int clilen = x->x_clilen;
- int n;
- struct ClientAddressStruct ras;
- ClientAddr ra = &ras;
-
- //catchupflag= FALSE;
-
-/* if (ShowBytes) { */
-/* int i; */
-/* printf("%d byte message:\n", n); */
-/* for (i = 0; i < n; ++i) { */
-/* printf(" %x (%c)\t", m[i], m[i]); */
-/* if (i%4 == 3) printf("\n"); */
-/* } */
-/* printf("\n"); */
-/* } */
-
- // return catchupflag;
- //struct sockaddr_in x->x_server;
- //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0)
- // while((
-
- #ifdef WIN32
- if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0)
- #else
- if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0)
- #endif
- {
- //int r;
- ras.cl_addr = *((struct sockaddr_in *) &x->x_server);
- ras.clilen = x->x_clilen;
- ras.sockfd = x->x_connectsocket;
-
- #ifdef DEBUG
- printf("dumpOSC_read: received UDP packet of length %d\n", n);
- #endif
-
- if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd))
- {
- dumpOSC_ParsePacket(x, mbuf, n, ra);
- }
- //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd);
- //post ("%d", r);
- //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
- // emsg-msg-1, at + msg + 1);
- // outlet_list(x->x_msgout, 0, n, mbuf);
- //if( sgi_HaveToQuit()) goto out;
- //if(r>0) goto back;
- //clilen = maxclilen;
- }
-}
-
-static void *dumpOSC_new(t_symbol *compatflag,
- t_floatarg fportno) {
- t_dumpOSC *x;
- struct sockaddr_in server;
- int clilen=sizeof(server);
- int sockfd;
- int portno=fportno;
- int udp = 1;
-
- //x->x_b = binbuf_new();
- //x->x_outat = binbuf_getvec(x->x_b);
-
- //{{raf}} pointer not valid yet...moving this down
- //x->x_outatc = 0; {{raf}}
-
- /* create a socket */
- if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1)
- {
- sys_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);
- /* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
- {
- sys_sockerror("bind");
- sys_closesocket(sockfd);
- return (0);
- }
-
- x = (t_dumpOSC *)pd_new(dumpOSC_class);
- x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid)
-
- x->x_msgout = outlet_new(&x->x_obj, &s_anything);
-
- // if (udp) /* datagram protocol */
- {
-
- sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x);
- x->x_connectout = 0;
- }
- // else /* streaming protocol */
- /* { */
- /* if (listen(sockfd, 5) < 0) */
- /* { */
- /* sys_sockerror("listen"); */
- /* sys_closesocket(sockfd); */
- /* sockfd = -1; */
- /* } */
- /* else */
- /* { */
- /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */
- /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */
- /* } */
- /* } */
-
- x->x_connectsocket = sockfd;
- x->x_server = server;
- x->x_clilen = clilen;
- x->x_nconnections = 0;
- x->x_udp = udp;
-
- return (x);
-}
-
-static void dumpOSC_free(t_dumpOSC *x)
-{
- /* LATER make me clean up open connections */
- if (x->x_connectsocket >= 0)
- {
- sys_rmpollfn(x->x_connectsocket);
- sys_closesocket(x->x_connectsocket);
- }
-}
-
-#ifdef WIN32
-OSC_API void dumpOSC_setup(void)
-#else
-void dumpOSC_setup(void)
-#endif
-{
- dumpOSC_class = class_new(gensym("dumpOSC"),
- (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free,
- sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT,
- A_DEFSYM, 0);
- class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd"));
-}
-
-
-#ifndef WIN32
- #define UNIXDG_PATH "/tmp/htm"
- #define UNIXDG_TMP "/tmp/htm.XXXXXX"
- static int unixinitudp(int chan)
- {
- struct sockaddr_un serv_addr;
- int sockfd;
-
- if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
- return sockfd;
-
- bzero((char *)&serv_addr, sizeof(serv_addr));
- serv_addr.sun_family = AF_UNIX;
- strcpy(serv_addr.sun_path, UNIXDG_PATH);
- sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan);
- unlink(serv_addr.sun_path);
- if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0)
- {
- perror("unable to bind\n");
- return -1;
- }
-
- fcntl(sockfd, F_SETFL, FNDELAY);
- return sockfd;
- }
-#endif // #ifndef WIN32
-
-
-
-static int initudp(int chan)
-{
-
-#ifdef WIN32
- struct sockaddr_in serv_addr;
- unsigned int sockfd;
- ULONG nonBlocking = (ULONG) TRUE;
-
- if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) {
- ZeroMemory((char *)&serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(chan);
- if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) {
- // set for non-blocking mode
- if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) {
- perror("unable to set non-blocking\n");
- return -1;
- }
- }
- else { perror("unable to bind\n"); return -1; }
- }
- return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd);
-#else
- struct sockaddr_in serv_addr;
- int sockfd;
-
- if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- return sockfd;
-
- bzero((char *)&serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(chan);
-
- if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
- {
- perror("unable to bind\n");
- return -1;
- }
-
- fcntl(sockfd, F_SETFL, FNDELAY);
- return sockfd;
-#endif
-}
-
-
-
-
-
-
-
-
-static void closeudp(int sockfd) {
- #ifdef WIN32
- closesocket(sockfd);
- #else
- close(sockfd);
- #endif
-}
-
-static Boolean catchupflag=FALSE;
-Boolean ClientReply(int packetsize, void *packet, int socketfd,
- void *clientaddresspointer, int clientaddressbufferlength)
-{
- if(!clientaddresspointer) return FALSE;
- catchupflag= TRUE;
- return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength);
-}
-
-static Boolean exitflag= FALSE;
-void sgi_CleanExit(void) {
- exitflag = TRUE;
-}
-
-Boolean sgi_HaveToQuit(void) {
- return exitflag;
-}
-
-
-/* file descriptor poll table */
-static int npolldevs =0;
-typedef struct polldev
-{
- int fd;
- void (*callbackfunction)(int , void *);
- void *dummy;
-} polldev;
-#define TABMAX 8
-static polldev polldevs[TABMAX];
-
-
-/* Register a device (referred to by a file descriptor that the caller
- should have already successfully obtained from a system call) to be
- polled as real-time constraints allowed.
-
- When a select(2) call indicates activity on the file descriptor, the
- callback function is called with the file descripter as first
- argument and the given dummy argument (presumably a pointer to the
- instance variables associated with the device).
-*/
-int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy)
-{
- if(npolldevs<TABMAX)
- {
- polldevs[npolldevs].fd = fd;
- polldevs[npolldevs].callbackfunction = callbackfunction;
- polldevs[npolldevs].dummy = dummy;
- }
- else return -1;
- return npolldevs++;
-}
-
-static int caught_sigint;
-
-static void catch_sigint() {
- caught_sigint = 1;
-}
-static int sockfd, usockfd;
-
-
-void PrintClientAddr(ClientAddr CA) {
- unsigned long addr = CA->cl_addr.sin_addr.s_addr;
- printf("Client address %p:\n", CA);
- printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd);
- printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family,
- CA->cl_addr.sin_port);
- printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr));
-
- printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n",
- CA->cl_addr.sin_zero[0],
- CA->cl_addr.sin_zero[1],
- CA->cl_addr.sin_zero[2],
- CA->cl_addr.sin_zero[3],
- CA->cl_addr.sin_zero[4],
- CA->cl_addr.sin_zero[5],
- CA->cl_addr.sin_zero[6],
- CA->cl_addr.sin_zero[7]);
-
- printf("\n");
-}
-
-//*******************
-
-void WriteTime(char* dst, osc_time_t osctime)
-{
- *(int32_t*)dst = htonl((int32_t)(osctime >> 32));
- *(int32_t*)(dst+4) = htonl((int32_t)osctime);
-}
-
-void WriteMode(char* dst)
-{
- *(int32_t*)dst = htonl(0);
-}
-
-osc_time_t ReadTime(const char* src)
-{
- osc_time_t osctime = ntohl(*(int32_t*)src);
- return (osctime << 32) + ntohl(*(int32_t*)(src+4));
-}
-
-double TimeToSeconds(osc_time_t osctime)
-{
- return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */;
-}
-
-int timeRound(double x)
-{
- return x >= 0.0 ? x+0.5 : x-0.5;
-}
-/*
-void WriteLogicalTime(char* dst)
-{
- static double startTime = -1.0;
- double sTime;
-
- // Initialisierung der Startzeit.
- // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren.
- // Knnte wahrscheinlich auch 0.0 sein.
- if (startTime < 0.0) {
- startTime = clock_getlogicaltime();
- }
-
- sTime = clock_gettimesince(startTime) * 0.001;
- *(int32_t*)dst = hton'K l((int32_t)sTime);
- *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime));
-}
-*/
-
-void WriteLogicalTime(char* dst)
-{
- double sTime = clock_gettimesince(19230720) / 1000.0;
- double tau = sTime - timeRound(sTime);
-
- //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau);
-
- *(int32_t*)dst = htonl((int32_t)(sTime));
- *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau));
-}
-
-Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd)
-{
- if((n == 24) && (strcmp(buf, "#time") == 0))
- {
- osc_time_t t0, t1, t2;
- double dt0, dt1, dt2;
-
- WriteMode(buf+6);
-
- t0 = ReadTime(buf+8);
-
- WriteLogicalTime(buf+16);
- t1 = ReadTime(buf+16); // reverse
- dt0 = TimeToSeconds(t0); // client time
- dt1 = TimeToSeconds(t1); // server time
-
- // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1);
-
- sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-//**********************
-
-void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) {
- // t_dumpOSC *x;
- int size, messageLen, i;
- char *messageName;
- char *args;
-
- //#ifdef PRINTADDRS
- #ifdef DEBUG
- //PrintClientAddr(returnAddr);
- #endif
-
-
- if ((n%4) != 0) {
- complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n);
- return;
- }
-
- if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) {
- /* This is a bundle message. */
- #ifdef DEBUG
- printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n");
- #endif
-
- if (n < 16) {
- complain("Bundle message too small (%d bytes) for time tag", n);
- return;
- }
-
- /* Print the time tag */
- #ifdef DEBUG
- printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12))));
- #endif
-
- /* Note: if we wanted to actually use the time tag as a little-endian
- 64-bit int, we'd have to word-swap the two 32-bit halves of it */
-
- i = 16; /* Skip "#group\0" and time tag */
-
- while(i<n) {
- size = ntohl(*((int *) (buf + i)));
- if ((size % 4) != 0) {
- complain("Bad size count %d in bundle (not a multiple of 4)", size);
- return;
- }
- if ((size + i + 4) > n) {
- complain("Bad size count %d in bundle (only %d bytes left in entire bundle)",
- size, n-i-4);
- return;
- }
-
- /* Recursively handle element of bundle */
- dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr);
- i += 4 + size;
- }
-
- if (i != n) {
- complain("This can't happen");
- }
- #ifdef DEBUG
- printf("]\n");
- #endif
-
- }
- else if ((n == 24) && (strcmp(buf, "#time") == 0))
- {
- complain("Time message: %s\n :).\n", htm_error_string);
- return;
-
- }
- else
- {
- /* This is not a bundle message */
-
- messageName = buf;
- args = DataAfterAlignedString(messageName, buf+n);
- if (args == 0) {
- complain("Bad message name string: %s\nDropping entire message.\n",
- htm_error_string);
- return;
- }
- messageLen = args-messageName;
- dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr);
- }
-}
-
-#define SMALLEST_POSITIVE_FLOAT 0.000001f
-
-static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) {
- char *chars = v;
- t_atom at;
- //t_atom myargv[50];
-
- int myargc = x->x_outatc;
- t_atom* mya = x->x_outat;
- int myi;
-
-#ifdef DEBUG
- printf("%s ", address);
-#endif
-
- // ztoln+cvt from envgen.c, ggee-0.18 ..
- // outlet_anything's 'symbol' gets set to address
- // so we dont need to append address to the atomlist
- /*
- SETSYMBOL(mya,gensym(address));myargc++;
- x->x_outatc = myargc;
- */
-
- if (n != 0) {
- if (chars[0] == ',') {
- if (chars[1] != ',') {
- /* This message begins with a type-tag string */
- dumpOSC_PrintTypeTaggedArgs(x, v, n);
- } else {
- /* Double comma means an escaped real comma, not a type string */
- dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1);
- }
- } else {
- dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0);
- }
- }
-
- outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat);
- x->x_outatc = 0;
-#ifdef DEBUG
- printf("\n");
-#endif
- fflush(stdout); /* Added for Sami 5/21/98 */
-}
-
-static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) {
- char *typeTags, *thisType;
- char *p;
-
- int myargc = x->x_outatc;
- t_atom* mya = x->x_outat;
- int myi;
-
- typeTags = v;
-
- if (!IsNiceString(typeTags, typeTags+n)) {
- /* No null-termination, so maybe it wasn't a type tag
- string after all */
- dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0);
- return;
- }
-
- p = DataAfterAlignedString(typeTags, typeTags+n);
-
-
- for (thisType = typeTags + 1; *thisType != 0; ++thisType) {
- switch (*thisType) {
- case 'i': case 'r': case 'm': case 'c':
-#ifdef DEBUG
- //post("integer: %d", ntohl(*((int *) p)));
-#endif
- /* Martin Peach fix for negative floats:
- * was: SETFLOAT(mya+myargc,ntohl(*((int *) p)));
- * now is:
- */
- SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p)));
- myargc++;
-
- p += 4;
- break;
-
- case 'f': {
- int i = ntohl(*((int *) p));
- float *floatp = ((float *) (&i));
-#ifdef DEBUG
- post("float: %f", *floatp);
-#endif
- SETFLOAT(mya+myargc,*floatp);
- myargc++;
-
- p += 4;
- }
- break;
-
- case 'h': case 't':
-#ifdef DEBUG
- printf("[A 64-bit int] ");
-#endif
- post("[A 64-bit int] not implemented");
-
- p += 8;
- break;
-
- case 'd':
-#ifdef DEBUG
- printf("[A 64-bit float] ");
-#endif
- post("[A 64-bit float] not implemented");
-
- p += 8;
- break;
-
- case 's': case 'S':
- if (!IsNiceString(p, typeTags+n)) {
- post("Type tag said this arg is a string but it's not!\n");
- return;
- } else {
-#ifdef DEBUG
- post("string: \"%s\"", p);
-#endif
- SETSYMBOL(mya+myargc,gensym(p));
- myargc++;
- //outlet_list(x->x_msgout, 0,sizeof(p), p);
- //outlet_anything(x->x_msgout, 0, sizeof(p), p);
- p = DataAfterAlignedString(p, typeTags+n);
- // append to output vector ..
- }
- break;
-
- case 'T':
-#ifdef DEBUG
- printf("[True] ");
-#endif
- SETFLOAT(mya+myargc,1.);
- myargc++;
- break;
- case 'F':
-#ifdef DEBUG
- printf("[False] ");
-#endif
- SETFLOAT(mya+myargc,0.);
- myargc++;
- break;
- case 'N':
-#ifdef DEBUG
- printf("[Nil]");
-#endif
- post("sendOSC: [Nil] not implemented");
- break;
- case 'I':
-#ifdef DEBUG
- printf("[Infinitum]");
-#endif
- post("sendOSC: [Infinitum] not implemented");
- break;
-
- default:
- post("sendOSC: [Unrecognized type tag %c]", *thisType);
- // return;
- }
- }
- x->x_outatc = myargc;
-}
-
-static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) {
- int i, thisi;
- float thisf;
- int *ints;
- char *chars;
- char *string, *nextString;
-
- int myargc= x->x_outatc;
- t_atom* mya = x->x_outat;
- int myi;
-
-
- /* Go through the arguments 32 bits at a time */
- ints = v;
- chars = v;
-
- for (i = 0; i<n/4; ) {
- string = &chars[i*4];
- thisi = ntohl(ints[i]);
- /* Reinterpret the (potentially byte-reversed) thisi as a float */
- thisf = *(((float *) (&thisi)));
-
- if (thisi >= -1000 && thisi <= 1000000) {
-#ifdef DEBUG
- printf("%d ", thisi);
-#endif
- // append to output vector ..
- SETFLOAT(mya+myargc,(t_float) (thisi));
- myargc++;
- // outlet_float(x->x_msgout, thisi);
- i++;
- } else if (thisf >= -1000.f && thisf <= 1000000.f &&
- (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) {
-#ifdef DEBUG
- printf("%f ", thisf);
-#endif
- // append to output vector ..
- SETFLOAT(mya+myargc,thisf);
- myargc++;
- //outlet_float(x->x_msgout, thisf);
- i++;
- } else if (IsNiceString(string, chars+n)) {
- nextString = DataAfterAlignedString(string, chars+n);
-#ifdef DEBUG
- printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string);
-#endif
- // append to output vector ..
- SETSYMBOL(mya+myargc,gensym(string));
- myargc++;
- //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string));
- i += (nextString-string) / 4;
- } else {
- // unhandled .. ;)
-#ifdef DEBUG
- printf("0x%x xx", ints[i]);
-#endif
- i++;
- }
- x->x_outatc = myargc;
- }
-}
-
-
-#define STRING_ALIGN_PAD 4
-
-char *DataAfterAlignedString(char *string, char *boundary)
-{
- /* The argument is a block of data beginning with a string. The
- string has (presumably) been padded with extra null characters
- so that the overall length is a multiple of STRING_ALIGN_PAD
- bytes. Return a pointer to the next byte after the null
- byte(s). The boundary argument points to the character after
- the last valid character in the buffer---if the string hasn't
- ended by there, something's wrong.
-
- If the data looks wrong, return 0, and set htm_error_string */
-
- int i;
-
- if ((boundary - string) %4 != 0) {
- fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n");
- return 0;
- }
-
- for (i = 0; string[i] != '\0'; i++) {
- if (string + i >= boundary) {
- htm_error_string = "DataAfterAlignedString: Unreasonably long string";
- return 0;
- }
- }
-
- /* Now string[i] is the first null character */
- i++;
-
- for (; (i % STRING_ALIGN_PAD) != 0; i++) {
- if (string + i >= boundary) {
- htm_error_string = "DataAfterAlignedString: Unreasonably long string";
- return 0;
- }
- if (string[i] != '\0') {
- htm_error_string = "DataAfterAlignedString: Incorrectly padded string.";
- return 0;
- }
- }
-
- return string+i;
-}
-
-Boolean IsNiceString(char *string, char *boundary)
-{
- /* Arguments same as DataAfterAlignedString(). Is the given "string"
- really a string? I.e., is it a sequence of isprint() characters
- terminated with 1-4 null characters to align on a 4-byte boundary? */
-
- int i;
-
- if ((boundary - string) %4 != 0) {
- fprintf(stderr, "Internal error: IsNiceString: bad boundary\n");
- return 0;
- }
-
- for (i = 0; string[i] != '\0'; i++) {
- if (!isprint(string[i])) return FALSE;
- if (string + i >= boundary) return FALSE;
- }
-
- /* If we made it this far, it's a null-terminated sequence of printing characters
- in the given boundary. Now we just make sure it's null padded... */
-
- /* Now string[i] is the first null character */
- i++;
- for (; (i % STRING_ALIGN_PAD) != 0; i++) {
- if (string[i] != '\0') return FALSE;
- }
-
- return TRUE;
-}
-
-
-
-
-
-
-
-
-
-#include <stdarg.h>
-void complain(char *s, ...) {
- va_list ap;
- va_start(ap, s);
- fprintf(stderr, "*** ERROR: ");
- vfprintf(stderr, s, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-#endif /* __sgi or LINUX or WIN32 */
+/* +Written by Matt Wright and Adrian Freed, The Center for New Music and +Audio Technologies, University of California, Berkeley. Copyright (c) +1992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of +California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + +The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl +*/ + + + /* + + dumpOSC.c + server that displays OpenSoundControl messages sent to it + for debugging client udp and UNIX protocol + + by Matt Wright, 6/3/97 + modified from dumpSC.c, by Matt Wright and Adrian Freed + + version 0.2: Added "-silent" option a.k.a. "-quiet" + + version 0.3: Incorporated patches from Nicola Bernardini to make + things Linux-friendly. Also added ntohl() in the right places + to support little-endian architectures. + + + + compile: + cc -o dumpOSC dumpOSC.c + + to-do: + + More robustness in saying exactly what's wrong with ill-formed + messages. (If they don't make sense, show exactly what was + received.) + + Time-based features: print time-received for each packet + + Clean up to separate OSC parsing code from socket/select stuff + + pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c + ------------- + -- added pd functions + -- socket is made differently than original via pd mechanisms + -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 + -- the OSX changes from cnmat didnt make it here yet but this compiles + on OSX anyway. + +*/ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include "m_pd.h" +//#include "m_imp.h" +#include "s_stuff.h" + +/* declarations */ + +// typedef void (*t_fdpollfn)(void *ptr, int fd); +void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); + + +#if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__) + +#ifdef WIN32 + #include "OSC-common.h" + #include <winsock2.h> + #include <string.h> + #include <stdlib.h> + #include <fcntl.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <ctype.h> + #include <signal.h> +#else + #include <stdio.h> + #include <string.h> + #include <stdlib.h> + #include <unistd.h> + #include <fcntl.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <netinet/in.h> + #include <rpc/rpc.h> + #include <sys/socket.h> + #include <sys/un.h> + #include <sys/times.h> + #include <sys/param.h> + #include <sys/time.h> + #include <sys/ioctl.h> + #include <ctype.h> + #include <arpa/inet.h> + #include <netdb.h> + #include <pwd.h> + #include <signal.h> + #include <grp.h> + #include <sys/file.h> + //#include <sys/prctl.h> + + #ifdef NEED_SCHEDCTL_AND_LOCK + #include <sys/schedctl.h> + #include <sys/lock.h> + #endif +#endif + + +char *htm_error_string; +typedef int Boolean; +typedef void *OBJ; + +typedef struct ClientAddressStruct { + struct sockaddr_in cl_addr; + int clilen; + int sockfd; +} *ClientAddr; + +typedef unsigned long long osc_time_t; + +Boolean ShowBytes = FALSE; +Boolean Silent = FALSE; + +/* Declarations */ +#ifndef WIN32 +static int unixinitudp(int chan); +#endif + +static int initudp(int chan); +static void closeudp(int sockfd); +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength); +void sgi_CleanExit(void); +Boolean sgi_HaveToQuit(void); +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy); +static void catch_sigint(); +static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ; +char *DataAfterAlignedString(char *string, char *boundary) ; +Boolean IsNiceString(char *string, char *boundary) ; +void complain(char *s, ...); + +#define MAXMESG 32768 +static char mbuf[MAXMESG]; + +/* ----------------------------- dumpOSC ------------------------- */ + +#define MAXOUTAT 50 + +static t_class *dumpOSC_class; + +typedef struct _dumpOSC +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_connectout; + t_atom x_outat[MAXOUTAT]; + int x_outatc; + t_binbuf *x_b; + int x_connectsocket; + int x_nconnections; + int x_udp; + struct sockaddr_in x_server; + int x_clilen; +} t_dumpOSC; + +void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr); +Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd); +static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr); +static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n); +static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma); + +static void dumpOSC_read(t_dumpOSC *x, int sockfd) { + int clilen = x->x_clilen; + int n; + struct ClientAddressStruct ras; + ClientAddr ra = &ras; + + //catchupflag= FALSE; + +/* if (ShowBytes) { */ +/* int i; */ +/* printf("%d byte message:\n", n); */ +/* for (i = 0; i < n; ++i) { */ +/* printf(" %x (%c)\t", m[i], m[i]); */ +/* if (i%4 == 3) printf("\n"); */ +/* } */ +/* printf("\n"); */ +/* } */ + + // return catchupflag; + //struct sockaddr_in x->x_server; + //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0) + // while(( + + #ifdef WIN32 + if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0) + #else + if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0) + #endif + { + //int r; + ras.cl_addr = *((struct sockaddr_in *) &x->x_server); + ras.clilen = x->x_clilen; + ras.sockfd = x->x_connectsocket; + + #ifdef DEBUG + printf("dumpOSC_read: received UDP packet of length %d\n", n); + #endif + + if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd)) + { + dumpOSC_ParsePacket(x, mbuf, n, ra); + } + //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd); + //post ("%d", r); + //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + // emsg-msg-1, at + msg + 1); + // outlet_list(x->x_msgout, 0, n, mbuf); + //if( sgi_HaveToQuit()) goto out; + //if(r>0) goto back; + //clilen = maxclilen; + } +} + +static void *dumpOSC_new(t_symbol *compatflag, + t_floatarg fportno) { + t_dumpOSC *x; + struct sockaddr_in server; + int clilen=sizeof(server); + int sockfd; + int portno=fportno; + int udp = 1; + + //x->x_b = binbuf_new(); + //x->x_outat = binbuf_getvec(x->x_b); + + //{{raf}} pointer not valid yet...moving this down + //x->x_outatc = 0; {{raf}} + + /* create a socket */ + if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1) + { + sys_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); + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("bind"); + sys_closesocket(sockfd); + return (0); + } + + x = (t_dumpOSC *)pd_new(dumpOSC_class); + x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid) + + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + + // if (udp) /* datagram protocol */ + { + + sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x); + x->x_connectout = 0; + } + // else /* streaming protocol */ + /* { */ + /* if (listen(sockfd, 5) < 0) */ + /* { */ + /* sys_sockerror("listen"); */ + /* sys_closesocket(sockfd); */ + /* sockfd = -1; */ + /* } */ + /* else */ + /* { */ + /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */ + /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */ + /* } */ + /* } */ + + x->x_connectsocket = sockfd; + x->x_server = server; + x->x_clilen = clilen; + x->x_nconnections = 0; + x->x_udp = udp; + + return (x); +} + +static void dumpOSC_free(t_dumpOSC *x) +{ + /* LATER make me clean up open connections */ + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } +} + +#ifdef WIN32 +OSC_API void dumpOSC_setup(void) +#else +void dumpOSC_setup(void) +#endif +{ + dumpOSC_class = class_new(gensym("dumpOSC"), + (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free, + sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, + A_DEFSYM, 0); + class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd")); +} + + +#ifndef WIN32 + #define UNIXDG_PATH "/tmp/htm" + #define UNIXDG_TMP "/tmp/htm.XXXXXX" + static int unixinitudp(int chan) + { + struct sockaddr_un serv_addr; + int sockfd; + + if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, UNIXDG_PATH); + sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan); + unlink(serv_addr.sun_path); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; + } +#endif // #ifndef WIN32 + + + +static int initudp(int chan) +{ + +#ifdef WIN32 + struct sockaddr_in serv_addr; + unsigned int sockfd; + ULONG nonBlocking = (ULONG) TRUE; + + if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) { + ZeroMemory((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) { + // set for non-blocking mode + if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) { + perror("unable to set non-blocking\n"); + return -1; + } + } + else { perror("unable to bind\n"); return -1; } + } + return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd); +#else + struct sockaddr_in serv_addr; + int sockfd; + + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; +#endif +} + + + + + + + + +static void closeudp(int sockfd) { + #ifdef WIN32 + closesocket(sockfd); + #else + close(sockfd); + #endif +} + +static Boolean catchupflag=FALSE; +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength) +{ + if(!clientaddresspointer) return FALSE; + catchupflag= TRUE; + return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength); +} + +static Boolean exitflag= FALSE; +void sgi_CleanExit(void) { + exitflag = TRUE; +} + +Boolean sgi_HaveToQuit(void) { + return exitflag; +} + + +/* file descriptor poll table */ +static int npolldevs =0; +typedef struct polldev +{ + int fd; + void (*callbackfunction)(int , void *); + void *dummy; +} polldev; +#define TABMAX 8 +static polldev polldevs[TABMAX]; + + +/* Register a device (referred to by a file descriptor that the caller + should have already successfully obtained from a system call) to be + polled as real-time constraints allowed. + + When a select(2) call indicates activity on the file descriptor, the + callback function is called with the file descripter as first + argument and the given dummy argument (presumably a pointer to the + instance variables associated with the device). +*/ +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy) +{ + if(npolldevs<TABMAX) + { + polldevs[npolldevs].fd = fd; + polldevs[npolldevs].callbackfunction = callbackfunction; + polldevs[npolldevs].dummy = dummy; + } + else return -1; + return npolldevs++; +} + +static int caught_sigint; + +static void catch_sigint() { + caught_sigint = 1; +} +static int sockfd, usockfd; + + +void PrintClientAddr(ClientAddr CA) { + unsigned long addr = CA->cl_addr.sin_addr.s_addr; + printf("Client address %p:\n", CA); + printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd); + printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family, + CA->cl_addr.sin_port); + printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr)); + + printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n", + CA->cl_addr.sin_zero[0], + CA->cl_addr.sin_zero[1], + CA->cl_addr.sin_zero[2], + CA->cl_addr.sin_zero[3], + CA->cl_addr.sin_zero[4], + CA->cl_addr.sin_zero[5], + CA->cl_addr.sin_zero[6], + CA->cl_addr.sin_zero[7]); + + printf("\n"); +} + +//******************* + +void WriteTime(char* dst, osc_time_t osctime) +{ + *(int32_t*)dst = htonl((int32_t)(osctime >> 32)); + *(int32_t*)(dst+4) = htonl((int32_t)osctime); +} + +void WriteMode(char* dst) +{ + *(int32_t*)dst = htonl(0); +} + +osc_time_t ReadTime(const char* src) +{ + osc_time_t osctime = ntohl(*(int32_t*)src); + return (osctime << 32) + ntohl(*(int32_t*)(src+4)); +} + +double TimeToSeconds(osc_time_t osctime) +{ + return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */; +} + +int timeRound(double x) +{ + return x >= 0.0 ? x+0.5 : x-0.5; +} +/* +void WriteLogicalTime(char* dst) +{ + static double startTime = -1.0; + double sTime; + + // Initialisierung der Startzeit. + // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren. + // Knnte wahrscheinlich auch 0.0 sein. + if (startTime < 0.0) { + startTime = clock_getlogicaltime(); + } + + sTime = clock_gettimesince(startTime) * 0.001; + *(int32_t*)dst = hton'K l((int32_t)sTime); + *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime)); +} +*/ + +void WriteLogicalTime(char* dst) +{ + double sTime = clock_gettimesince(19230720) / 1000.0; + double tau = sTime - timeRound(sTime); + + //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau); + + *(int32_t*)dst = htonl((int32_t)(sTime)); + *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau)); +} + +Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd) +{ + if((n == 24) && (strcmp(buf, "#time") == 0)) + { + osc_time_t t0, t1, t2; + double dt0, dt1, dt2; + + WriteMode(buf+6); + + t0 = ReadTime(buf+8); + + WriteLogicalTime(buf+16); + t1 = ReadTime(buf+16); // reverse + dt0 = TimeToSeconds(t0); // client time + dt1 = TimeToSeconds(t1); // server time + + // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1); + + sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght); + return TRUE; + } + else + { + return FALSE; + } +} + +//********************** + +void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) { + // t_dumpOSC *x; + int size, messageLen, i; + char *messageName; + char *args; + + //#ifdef PRINTADDRS + #ifdef DEBUG + //PrintClientAddr(returnAddr); + #endif + + + if ((n%4) != 0) { + complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n); + return; + } + + if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { + /* This is a bundle message. */ + #ifdef DEBUG + printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n"); + #endif + + if (n < 16) { + complain("Bundle message too small (%d bytes) for time tag", n); + return; + } + + /* Print the time tag */ + #ifdef DEBUG + printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12)))); + #endif + + /* Note: if we wanted to actually use the time tag as a little-endian + 64-bit int, we'd have to word-swap the two 32-bit halves of it */ + + i = 16; /* Skip "#group\0" and time tag */ + + while(i<n) { + size = ntohl(*((int *) (buf + i))); + if ((size % 4) != 0) { + complain("Bad size count %d in bundle (not a multiple of 4)", size); + return; + } + if ((size + i + 4) > n) { + complain("Bad size count %d in bundle (only %d bytes left in entire bundle)", + size, n-i-4); + return; + } + + /* Recursively handle element of bundle */ + dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr); + i += 4 + size; + } + + if (i != n) { + complain("This can't happen"); + } + #ifdef DEBUG + printf("]\n"); + #endif + + } + else if ((n == 24) && (strcmp(buf, "#time") == 0)) + { + complain("Time message: %s\n :).\n", htm_error_string); + return; + + } + else + { + /* This is not a bundle message */ + + messageName = buf; + args = DataAfterAlignedString(messageName, buf+n); + if (args == 0) { + complain("Bad message name string: %s\nDropping entire message.\n", + htm_error_string); + return; + } + messageLen = args-messageName; + dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr); + } +} + +#define SMALLEST_POSITIVE_FLOAT 0.000001f + +static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) { + char *chars = v; + t_atom at; + //t_atom myargv[50]; + + int myargc = x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + +#ifdef DEBUG + printf("%s ", address); +#endif + + // ztoln+cvt from envgen.c, ggee-0.18 .. + // outlet_anything's 'symbol' gets set to address + // so we dont need to append address to the atomlist + /* + SETSYMBOL(mya,gensym(address));myargc++; + x->x_outatc = myargc; + */ + + if (n != 0) { + if (chars[0] == ',') { + if (chars[1] != ',') { + /* This message begins with a type-tag string */ + dumpOSC_PrintTypeTaggedArgs(x, v, n); + } else { + /* Double comma means an escaped real comma, not a type string */ + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1); + } + } else { + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + } + } + + outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat); + x->x_outatc = 0; +#ifdef DEBUG + printf("\n"); +#endif + fflush(stdout); /* Added for Sami 5/21/98 */ +} + +static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) { + char *typeTags, *thisType; + char *p; + + int myargc = x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + + typeTags = v; + + if (!IsNiceString(typeTags, typeTags+n)) { + /* No null-termination, so maybe it wasn't a type tag + string after all */ + dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + return; + } + + p = DataAfterAlignedString(typeTags, typeTags+n); + + + for (thisType = typeTags + 1; *thisType != 0; ++thisType) { + switch (*thisType) { + case 'i': case 'r': case 'm': case 'c': +#ifdef DEBUG + //post("integer: %d", ntohl(*((int *) p))); +#endif + /* Martin Peach fix for negative floats: + * was: SETFLOAT(mya+myargc,ntohl(*((int *) p))); + * now is: + */ + SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p))); + myargc++; + + p += 4; + break; + + case 'f': { + int i = ntohl(*((int *) p)); + float *floatp = ((float *) (&i)); +#ifdef DEBUG + post("float: %f", *floatp); +#endif + SETFLOAT(mya+myargc,*floatp); + myargc++; + + p += 4; + } + break; + + case 'h': case 't': +#ifdef DEBUG + printf("[A 64-bit int] "); +#endif + post("[A 64-bit int] not implemented"); + + p += 8; + break; + + case 'd': +#ifdef DEBUG + printf("[A 64-bit float] "); +#endif + post("[A 64-bit float] not implemented"); + + p += 8; + break; + + case 's': case 'S': + if (!IsNiceString(p, typeTags+n)) { + post("Type tag said this arg is a string but it's not!\n"); + return; + } else { +#ifdef DEBUG + post("string: \"%s\"", p); +#endif + SETSYMBOL(mya+myargc,gensym(p)); + myargc++; + //outlet_list(x->x_msgout, 0,sizeof(p), p); + //outlet_anything(x->x_msgout, 0, sizeof(p), p); + p = DataAfterAlignedString(p, typeTags+n); + // append to output vector .. + } + break; + + case 'T': +#ifdef DEBUG + printf("[True] "); +#endif + SETFLOAT(mya+myargc,1.); + myargc++; + break; + case 'F': +#ifdef DEBUG + printf("[False] "); +#endif + SETFLOAT(mya+myargc,0.); + myargc++; + break; + case 'N': +#ifdef DEBUG + printf("[Nil]"); +#endif + post("sendOSC: [Nil] not implemented"); + break; + case 'I': +#ifdef DEBUG + printf("[Infinitum]"); +#endif + post("sendOSC: [Infinitum] not implemented"); + break; + + default: + post("sendOSC: [Unrecognized type tag %c]", *thisType); + // return; + } + } + x->x_outatc = myargc; +} + +static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) { + int i, thisi; + float thisf; + int *ints; + char *chars; + char *string, *nextString; + + int myargc= x->x_outatc; + t_atom* mya = x->x_outat; + int myi; + + + /* Go through the arguments 32 bits at a time */ + ints = v; + chars = v; + + for (i = 0; i<n/4; ) { + string = &chars[i*4]; + thisi = ntohl(ints[i]); + /* Reinterpret the (potentially byte-reversed) thisi as a float */ + thisf = *(((float *) (&thisi))); + + if (thisi >= -1000 && thisi <= 1000000) { +#ifdef DEBUG + printf("%d ", thisi); +#endif + // append to output vector .. + SETFLOAT(mya+myargc,(t_float) (thisi)); + myargc++; + // outlet_float(x->x_msgout, thisi); + i++; + } else if (thisf >= -1000.f && thisf <= 1000000.f && + (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) { +#ifdef DEBUG + printf("%f ", thisf); +#endif + // append to output vector .. + SETFLOAT(mya+myargc,thisf); + myargc++; + //outlet_float(x->x_msgout, thisf); + i++; + } else if (IsNiceString(string, chars+n)) { + nextString = DataAfterAlignedString(string, chars+n); +#ifdef DEBUG + printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string); +#endif + // append to output vector .. + SETSYMBOL(mya+myargc,gensym(string)); + myargc++; + //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string)); + i += (nextString-string) / 4; + } else { + // unhandled .. ;) +#ifdef DEBUG + printf("0x%x xx", ints[i]); +#endif + i++; + } + x->x_outatc = myargc; + } +} + + +#define STRING_ALIGN_PAD 4 + +char *DataAfterAlignedString(char *string, char *boundary) +{ + /* The argument is a block of data beginning with a string. The + string has (presumably) been padded with extra null characters + so that the overall length is a multiple of STRING_ALIGN_PAD + bytes. Return a pointer to the next byte after the null + byte(s). The boundary argument points to the character after + the last valid character in the buffer---if the string hasn't + ended by there, something's wrong. + + If the data looks wrong, return 0, and set htm_error_string */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + } + + /* Now string[i] is the first null character */ + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + if (string[i] != '\0') { + htm_error_string = "DataAfterAlignedString: Incorrectly padded string."; + return 0; + } + } + + return string+i; +} + +Boolean IsNiceString(char *string, char *boundary) +{ + /* Arguments same as DataAfterAlignedString(). Is the given "string" + really a string? I.e., is it a sequence of isprint() characters + terminated with 1-4 null characters to align on a 4-byte boundary? */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: IsNiceString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (!isprint(string[i])) return FALSE; + if (string + i >= boundary) return FALSE; + } + + /* If we made it this far, it's a null-terminated sequence of printing characters + in the given boundary. Now we just make sure it's null padded... */ + + /* Now string[i] is the first null character */ + i++; + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string[i] != '\0') return FALSE; + } + + return TRUE; +} + + + + + + + + + +#include <stdarg.h> +void complain(char *s, ...) { + va_list ap; + va_start(ap, s); + fprintf(stderr, "*** ERROR: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +#endif /* __sgi or LINUX or WIN32 */ |