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 | |
| 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')
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/OSCroute.c | 30 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/bandpass.c | 180 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/dumpOSC.c | 1998 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/equalizer.c | 177 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/filters.h | 155 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/gcanvas.c | 829 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/highpass.c | 177 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/highshelf.c | 186 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/hlshelf.c | 466 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/image.c | 38 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/lowpass.c | 179 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/lowshelf.c | 187 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/moog~.c | 376 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/notch.c | 176 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/sendOSC.c | 2920 | ||||
| -rw-r--r-- | apps/plugins/pdbox/PDa/extra/shell.c | 622 |
16 files changed, 4453 insertions, 4243 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/OSCroute.c b/apps/plugins/pdbox/PDa/extra/OSCroute.c index 24860d0..34af5aa 100644 --- a/apps/plugins/pdbox/PDa/extra/OSCroute.c +++ b/apps/plugins/pdbox/PDa/extra/OSCroute.c @@ -42,6 +42,10 @@ The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl */ +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#else /* ROCKBOX */ #ifdef WIN32 #include <stdlib.h> #include <string.h> @@ -52,6 +56,7 @@ The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl #ifdef UNIX #include <stdio.h> #endif +#endif /* ROCKBOX */ /* structure definition of your object */ @@ -114,6 +119,9 @@ static void StrCopyUntilSlash(char *target, const char *source); // free static void OSCroute_free(t_OSCroute *x) { +#ifdef ROCKBOX + (void) x; +#endif // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); } @@ -154,7 +162,9 @@ void OSCroute_setup(void) { void *OSCroute_new(t_symbol *s, int argc, t_atom *argv) { - +#ifdef ROCKBOX + (void) s; +#endif t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize int i; //{{raf}} n not used @@ -236,6 +246,9 @@ void *OSCroute_new(t_symbol *s, int argc, t_atom *argv) void OSCroute_version (t_OSCroute *x) { +#ifdef ROCKBOX + (void) x; +#endif // EnterCallback(); post("OSCroute Version " OSC_ROUTE_VERSION ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__); @@ -248,15 +261,27 @@ void OSCroute_version (t_OSCroute *x) { void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg, char *dstString) { +#ifdef ROCKBOX + (void) box; +#endif // EnterCallback(); if (msg==ASSIST_INLET) { +#ifdef ROCKBOX + strcpy(dstString, "Incoming OSC messages"); +#else sprintf(dstString, "Incoming OSC messages"); +#endif } else if (msg==ASSIST_OUTLET) { if (arg < 0 || arg >= x->x_num) { post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg); } else { +#ifdef ROCKBOX + strcpy(dstString, "subaddress + args for prefix "); + strcat(dstString, x->x_prefixes[arg]); +#else sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]); +#endif } } else { post("* OSCroute_assist: unrecognized message %ld", msg); @@ -266,6 +291,9 @@ void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg, } void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { +#ifdef ROCKBOX + (void) s; +#endif // EnterCallback(); if (argc > 0 && argv[0].a_type == A_SYMBOL) { /* Ignore the fact that this is a "list" */ diff --git a/apps/plugins/pdbox/PDa/extra/bandpass.c b/apps/plugins/pdbox/PDa/extra/bandpass.c index 127a1ee..50a0b42 100644 --- a/apps/plugins/pdbox/PDa/extra/bandpass.c +++ b/apps/plugins/pdbox/PDa/extra/bandpass.c @@ -1,87 +1,95 @@ -
-/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-/* ------------------- bandpass ----------------------------*/
-
-static t_class *bandpass_class;
-
-void bandpass_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float alpha = e_alpha(x->x_bw* 0.01,omega);
- t_float b1 = 0.;
- t_float b0 = alpha;
- t_float b2 = -alpha;
- t_float a0 = 1 + alpha;
- t_float a1 = -2.*cos(omega);
- t_float a2 = 1 - alpha;
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("bandpass: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void bandpass_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- bandpass_bang(x);
-}
-
-
-static void *bandpass_new(t_floatarg f,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
-/* floatinlet_new(&x->x_obj, &x->x_gain); */
- floatinlet_new(&x->x_obj, &x->x_bw);
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- return (x);
-}
-
-
-void bandpass_setup(void)
-{
- bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(bandpass_class,bandpass_bang);
- class_addfloat(bandpass_class,bandpass_float);
-}
-
-
-
+ +/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + +/* ------------------- bandpass ----------------------------*/ + +static t_class *bandpass_class; + +void bandpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = 0.; + t_float b0 = alpha; + t_float b2 = -alpha; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("bandpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void bandpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + bandpass_bang(x); +} + + +static void *bandpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void bandpass_setup(void) +{ + bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(bandpass_class,bandpass_bang); + class_addfloat(bandpass_class,bandpass_float); +} + + + 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 */ diff --git a/apps/plugins/pdbox/PDa/extra/equalizer.c b/apps/plugins/pdbox/PDa/extra/equalizer.c index 7438323..18f84ee 100644 --- a/apps/plugins/pdbox/PDa/extra/equalizer.c +++ b/apps/plugins/pdbox/PDa/extra/equalizer.c @@ -1,86 +1,93 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-
-
-/* ------------------- equ ----------------------------*/
-static t_class *equ_class;
-
-void equ_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float alpha = e_alpha(x->x_bw*0.01,omega);
- t_float b0 = 1 + alpha*e_A(x->x_gain);
- t_float b1 = -2.*cos(omega);
- t_float b2 = 1 - alpha*e_A(x->x_gain);
- t_float a0 = 1 + alpha/e_A(x->x_gain);
- t_float a1 = -2.*cos(omega);
- t_float a2 = 1 - alpha/e_A(x->x_gain);
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("equ: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void equ_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- equ_bang(x);
-}
-
-
-static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
- floatinlet_new(&x->x_obj, &x->x_gain);
- floatinlet_new(&x->x_obj, &x->x_bw);
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- if (g != 0.) x->x_gain = g;
- return (x);
-}
-
-
-void equalizer_setup(void)
-{
- equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(equ_class,equ_bang);
- class_addfloat(equ_class,equ_float);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + + +/* ------------------- equ ----------------------------*/ +static t_class *equ_class; + +void equ_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b0 = 1 + alpha*e_A(x->x_gain); + t_float b1 = -2.*cos(omega); + t_float b2 = 1 - alpha*e_A(x->x_gain); + t_float a0 = 1 + alpha/e_A(x->x_gain); + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha/e_A(x->x_gain); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("equ: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void equ_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + equ_bang(x); +} + + +static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void equalizer_setup(void) +{ + equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(equ_class,equ_bang); + class_addfloat(equ_class,equ_float); +} + diff --git a/apps/plugins/pdbox/PDa/extra/filters.h b/apps/plugins/pdbox/PDa/extra/filters.h index 8a91f75..2eaf2b0 100644 --- a/apps/plugins/pdbox/PDa/extra/filters.h +++ b/apps/plugins/pdbox/PDa/extra/filters.h @@ -1,75 +1,82 @@ -/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-
-#ifndef __GGEE_FILTERS_H__
-#define __GGEE_FILTERS_H__
-
-
-
-#ifndef M_PI
-#define M_PI 3.141593f
-#endif
-
-
-#include <math.h>
-#define LN2 0.69314718
-#define e_A(g) (pow(10,(g/40.)))
-#define e_omega(f,r) (2.0*M_PI*f/r)
-#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega)))
-#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1)))
-
-
-
-
-typedef struct _rbjfilter
-{
- t_object x_obj;
- t_float x_rate;
- t_float x_freq;
- t_float x_gain;
- t_float x_bw;
-} t_rbjfilter;
-
-
-static int check_stability(t_float fb1,
- t_float fb2,
- t_float ff1,
- t_float ff2,
- t_float ff3)
-{
- float discriminant = fb1 * fb1 + 4 * fb2;
-
- if (discriminant < 0) /* imaginary roots -- resonant filter */
- {
- /* they're conjugates so we just check that the product
- is less than one */
- if (fb2 >= -1.0f) goto stable;
- }
- else /* real roots */
- {
- /* check that the parabola 1 - fb1 x - fb2 x^2 has a
- vertex between -1 and 1, and that it's nonnegative
- at both ends, which implies both roots are in [1-,1]. */
- if (fb1 <= 2.0f && fb1 >= -2.0f &&
- 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
- goto stable;
- }
- return 0;
-stable:
- return 1;
-}
-
-
-
-
-
-
-#endif
+/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + + +#ifndef __GGEE_FILTERS_H__ +#define __GGEE_FILTERS_H__ + +#ifdef ROCKBOX +#include "math.h" +#else +#include <math.h> +#endif + +#ifndef M_PI +#define M_PI 3.141593f +#endif + +#define LN2 0.69314718 +#define e_A(g) (pow(10,(g/40.))) +#define e_omega(f,r) (2.0*M_PI*f/r) +#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega))) +#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1))) + + + + +typedef struct _rbjfilter +{ + t_object x_obj; + t_float x_rate; + t_float x_freq; + t_float x_gain; + t_float x_bw; +} t_rbjfilter; + + +static int check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ +#ifdef ROCKBOX + (void) ff1; + (void) ff2; + (void) ff3; +#endif + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + + + + + +#endif diff --git a/apps/plugins/pdbox/PDa/extra/gcanvas.c b/apps/plugins/pdbox/PDa/extra/gcanvas.c index 9e3f934..09c1206 100644 --- a/apps/plugins/pdbox/PDa/extra/gcanvas.c +++ b/apps/plugins/pdbox/PDa/extra/gcanvas.c @@ -1,379 +1,452 @@ -/* (C) Guenter Geiger <geiger@xdv.org> */
-
-
-#include "m_pd.h"
-#include "g_canvas.h"
-
-/* ------------------------ gcanvas ----------------------------- */
-
-
-#define BACKGROUNDCOLOR "grey"
-
-#define DEFAULTSIZE 80
-
-static t_class *gcanvas_class;
-
-typedef struct _gcanvas
-{
- t_object x_obj;
- t_glist * x_glist;
- t_outlet* out2;
- t_outlet* out3;
- int x_width;
- int x_height;
- int x;
- int y;
- int x_xgrid;
- int x_ygrid;
-} t_gcanvas;
-
-
-static void rectangle(void* cv,void* o,char c,int x, int y,int w,int h,char* color) {
- sys_vgui(".x%x.c create rectangle \
- %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color);
-}
-
-static void move_object(void* cv,void* o,char c,int x, int y,int w,int h) {
- sys_vgui(".x%x.c coords %x%c %d %d %d %d\n",
- cv,o,c,x,y,x+w,y+h);
-
-}
-
-static void color_object(void* cv,void* o,char c,char* color) {
- sys_vgui(".x%x.c itemconfigure %x%c -fill %s\n", cv,
- o, c,color);
-}
-
-static void delete_object(void* cv,void* o,char c) {
- sys_vgui(".x%x.c delete %x%c\n",
- cv, o,c);
-}
-
-static void line(void* cv,void* o,char c,int x,int y,int w,int h,char* color) {
- sys_vgui(".x%x.c create line \
- %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color);
-}
-
-
-/* widget helper functions */
-
-void gcanvas_drawme(t_gcanvas *x, t_glist *glist, int firsttime)
-{
- int i;
- if (firsttime) {
- rectangle(glist_getcanvas(glist),x,'a',
- x->x_obj.te_xpix, x->x_obj.te_ypix,
- x->x_width, x->x_height,BACKGROUNDCOLOR);
- for (i=1;i<x->x_xgrid;i++)
- line(glist_getcanvas(glist),x,'b'+ i,
- x->x_obj.te_xpix + x->x_width*i/x->x_xgrid,
- x->x_obj.te_ypix,
- 0, x->x_height,"red");
- for (i=1;i<x->x_ygrid;i++)
- line(glist_getcanvas(glist),x,'B'+ i,
- x->x_obj.te_xpix,
- x->x_obj.te_ypix + x->x_height*i/x->x_ygrid,
- x->x_width, 0,"blue");
- }
- else {
- move_object(
- glist_getcanvas(glist),x,'a',
- x->x_obj.te_xpix, x->x_obj.te_ypix,
- x->x_width, x->x_height);
- for (i=1;i<x->x_xgrid;i++)
- move_object(glist_getcanvas(glist),x,'b'+ i,
- x->x_obj.te_xpix + x->x_width*i/x->x_xgrid,
- x->x_obj.te_ypix,
- 0, x->x_height);
- for (i=1;i<x->x_ygrid;i++)
- move_object(glist_getcanvas(glist),x,'B'+ i,
- x->x_obj.te_xpix,
- x->x_obj.te_ypix + x->x_height*i/x->x_ygrid,
- x->x_width, 0);
- }
-
- {
- /* outlets */
- int n = 3;
- int nplus, i;
- nplus = (n == 1 ? 1 : n-1);
- for (i = 0; i < n; i++)
- {
- int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus;
- if (firsttime)
- sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n",
- glist_getcanvas(glist),
- onset, x->x_obj.te_ypix + x->x_height - 1,
- onset + IOWIDTH, x->x_obj.te_ypix + x->x_height,
- x, i);
- else
- sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
- glist_getcanvas(glist), x, i,
- onset, x->x_obj.te_ypix + x->x_height - 1,
- onset + IOWIDTH, x->x_obj.te_ypix + x->x_height);
- }
- /* inlets */
- n = 0;
- nplus = (n == 1 ? 1 : n-1);
- for (i = 0; i < n; i++)
- {
- int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus;
- if (firsttime)
- sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
- glist_getcanvas(glist),
- onset, x->x_obj.te_ypix,
- onset + IOWIDTH, x->x_obj.te_ypix + 1,
- x, i);
- else
- sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
- glist_getcanvas(glist), x, i,
- onset, x->x_obj.te_ypix,
- onset + IOWIDTH, x->x_obj.te_ypix + 1);
-
- }
- }
-
-}
-
-
-
-
-void gcanvas_erase(t_gcanvas* x,t_glist* glist)
-{
- int n,i;
- delete_object(glist_getcanvas(glist),x,'a');
- for (i=1;i<x->x_xgrid;i++)
- delete_object(glist_getcanvas(glist),x,'b'+ i);
- for (i=1;i<x->x_ygrid;i++)
- delete_object(glist_getcanvas(glist),x,'B'+ i);
-
- n = 2;
- while (n--) {
- sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,n);
- }
-}
-
-
-
-/* ------------------------ gcanvas widgetbehaviour----------------------------- */
-
-
-static void gcanvas_getrect(t_gobj *z, t_glist *owner,
- int *xp1, int *yp1, int *xp2, int *yp2)
-{
- int width, height;
- t_gcanvas* s = (t_gcanvas*)z;
-
-
- width = s->x_width;
- height = s->x_height;
- *xp1 = s->x_obj.te_xpix;
- *yp1 = s->x_obj.te_ypix;
- *xp2 = s->x_obj.te_xpix + width;
- *yp2 = s->x_obj.te_ypix + height;
-}
-
-static void gcanvas_displace(t_gobj *z, t_glist *glist,
- int dx, int dy)
-{
- t_gcanvas *x = (t_gcanvas *)z;
- x->x_obj.te_xpix += dx;
- x->x_obj.te_ypix += dy;
- gcanvas_drawme(x, glist, 0);
- canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
-}
-
-static void gcanvas_select(t_gobj *z, t_glist *glist, int state)
-{
- t_gcanvas *x = (t_gcanvas *)z;
- color_object(glist,x,'a',state ? "blue" : BACKGROUNDCOLOR);
-}
-
-
-static void gcanvas_activate(t_gobj *z, t_glist *glist, int state)
-{
-/* t_text *x = (t_text *)z;
- t_rtext *y = glist_findrtext(glist, x);
- if (z->g_pd != gatom_class) rtext_activate(y, state);*/
-}
-
-static void gcanvas_delete(t_gobj *z, t_glist *glist)
-{
- t_text *x = (t_text *)z;
- canvas_deletelinesfor(glist_getcanvas(glist), x);
-}
-
-
-static void gcanvas_vis(t_gobj *z, t_glist *glist, int vis)
-{
- t_gcanvas* s = (t_gcanvas*)z;
- if (vis)
- gcanvas_drawme(s, glist, 1);
- else
- gcanvas_erase(s,glist);
-}
-
-/* can we use the normal text save function ?? */
-
-static void gcanvas_save(t_gobj *z, t_binbuf *b)
-{
- t_gcanvas *x = (t_gcanvas *)z;
- binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"),
- (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix,
- gensym("gcanvas"),x->x_width,x->x_height,
- x->x_xgrid,
- x->x_ygrid);
- binbuf_addv(b, ";");
-}
-
-
-t_widgetbehavior gcanvas_widgetbehavior;
-
-static void gcanvas_motion(t_gcanvas *x, t_floatarg dx, t_floatarg dy)
-{
- x->x += dx;
- x->y += dy;
- outlet_float(x->out2,x->y);
- outlet_float(x->x_obj.ob_outlet,x->x);
-}
-
-void gcanvas_key(t_gcanvas *x, t_floatarg f)
-{
- post("key");
-}
-
-
-static void gcanvas_click(t_gcanvas *x,
- t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
- t_floatarg doit,int up)
-{
- glist_grab(x->x_glist, &x->x_obj.te_g, (t_glistmotionfn) gcanvas_motion,
- (t_glistkeyfn) NULL, xpos, ypos);
-
- x->x = xpos - x->x_obj.te_xpix;
- x->y = ypos - x->x_obj.te_ypix;
- outlet_float(x->out2,x->y);
- outlet_float(x->x_obj.ob_outlet,x->x);
- outlet_float(x->out3,0);
-}
-
-static int gcanvas_newclick(t_gobj *z, struct _glist *glist,
- int xpix, int ypix, int shift, int alt, int dbl, int doit)
-{
- if (doit)
- gcanvas_click((t_gcanvas *)z, (t_floatarg)xpix, (t_floatarg)ypix,
- (t_floatarg)shift, 0, (t_floatarg)alt,dbl);
-
- if (dbl) outlet_float(((t_gcanvas*)z)->out3,1);
- return (1);
-}
-
-void gcanvas_size(t_gcanvas* x,t_floatarg w,t_floatarg h) {
- x->x_width = w;
- x->x_height = h;
- gcanvas_drawme(x, x->x_glist, 0);
-}
-
-static void gcanvas_setwidget(void)
-{
- gcanvas_widgetbehavior.w_getrectfn = gcanvas_getrect;
- gcanvas_widgetbehavior.w_displacefn = gcanvas_displace;
- gcanvas_widgetbehavior.w_selectfn = gcanvas_select;
- gcanvas_widgetbehavior.w_activatefn = gcanvas_activate;
- gcanvas_widgetbehavior.w_deletefn = gcanvas_delete;
- gcanvas_widgetbehavior.w_visfn = gcanvas_vis;
- gcanvas_widgetbehavior.w_clickfn = gcanvas_newclick;
- class_setsavefn(gcanvas_class,gcanvas_save);
-}
-
-
-static void *gcanvas_new(t_symbol* s,t_int ac,t_atom* at)
-{
- t_gcanvas *x = (t_gcanvas *)pd_new(gcanvas_class);
-
- x->x_glist = (t_glist*) canvas_getcurrent();
-
-
- /* Fetch the width */
-
- x->x_width = DEFAULTSIZE;
- if (ac-- > 0) {
- if (at->a_type != A_FLOAT)
- error("gcanvas: wrong argument type");
- else
- x->x_width = atom_getfloat(at++);
-
- if (x->x_width < 0 || x->x_width > 2000) {
- error("gcanvas: unallowed width %f",x->x_width);
- x->x_width = DEFAULTSIZE;
- }
- }
-
- /* Fetch the height */
-
- x->x_height = DEFAULTSIZE;
- if (ac-- > 0) {
- if (at->a_type != A_FLOAT)
- error("gcanvas: wrong argument type");
- else
- x->x_height = atom_getfloat(at++);
-
- if (x->x_height < 0 || x->x_height > 2000) {
- error("gcanvas: unallowed height %f",x->x_height);
- x->x_width = DEFAULTSIZE;
- }
- }
-
- /* Fetch the xgrid */
-
- x->x_xgrid = 0;
- if (ac-- > 0) {
- if (at->a_type != A_FLOAT)
- error("gcanvas: wrong argument type");
- else
- x->x_xgrid = atom_getfloat(at++);
-
- if (x->x_xgrid < 0 || x->x_xgrid > x->x_width/2) {
- error("gcanvas: unallowed xgrid %f",x->x_xgrid);
- x->x_xgrid = 0;
- }
- }
-
- /* Fetch the ygrid */
-
- x->x_ygrid = 0;
- if (ac-- > 0) {
- if (at->a_type != A_FLOAT)
- error("gcanvas: wrong argument type");
- else
- x->x_ygrid = atom_getfloat(at++);
-
- if (x->x_ygrid < 0 || x->x_ygrid > x->x_height/2) {
- error("gcanvas: unallowed xgrid %f",x->x_ygrid);
- x->x_ygrid = 0;
- }
- }
-
- outlet_new(&x->x_obj, &s_float);
- x->out2 = outlet_new(&x->x_obj, &s_float);
- x->out3 = outlet_new(&x->x_obj, &s_float);
- return (x);
-}
-
-
-
-void gcanvas_setup(void)
-{
- gcanvas_class = class_new(gensym("gcanvas"), (t_newmethod)gcanvas_new, 0,
- sizeof(t_gcanvas),0, A_GIMME,0);
-
- class_addmethod(gcanvas_class, (t_method)gcanvas_click, gensym("click"),
- A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
- class_addmethod(gcanvas_class, (t_method)gcanvas_size, gensym("size"),
- A_FLOAT, A_FLOAT, 0);
-
- gcanvas_setwidget();
- class_setwidget(gcanvas_class,&gcanvas_widgetbehavior);
-}
-
+/* (C) Guenter Geiger <geiger@xdv.org> */ + + +#include "m_pd.h" +#include "g_canvas.h" + +/* ------------------------ gcanvas ----------------------------- */ + + +#define BACKGROUNDCOLOR "grey" + +#define DEFAULTSIZE 80 + +static t_class *gcanvas_class; + +typedef struct _gcanvas +{ + t_object x_obj; + t_glist * x_glist; + t_outlet* out2; + t_outlet* out3; + int x_width; + int x_height; + int x; + int y; + int x_xgrid; + int x_ygrid; +} t_gcanvas; + + +static void rectangle(void* cv,void* o,char c,int x, int y,int w,int h,char* color) { +#ifdef ROCKBOX + (void) cv; + (void) o; + (void) c; + (void) x; + (void) y; + (void) w; + (void) h; + (void) color; +#else /* ROCKBOX */ + sys_vgui(".x%x.c create rectangle \ + %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color); +#endif /* ROCKBOX */ +} + +static void move_object(void* cv,void* o,char c,int x, int y,int w,int h) { +#ifdef ROCKBOX + (void) cv; + (void) o; + (void) c; + (void) x; + (void) y; + (void) w; + (void) h; +#else /* ROCKBOX */ + sys_vgui(".x%x.c coords %x%c %d %d %d %d\n", + cv,o,c,x,y,x+w,y+h); +#endif /* ROCKBOX */ +} + +static void color_object(void* cv,void* o,char c,char* color) { +#ifdef ROCKBOX + (void) cv; + (void) o; + (void) c; + (void) color; +#else /* ROCKBOX */ + sys_vgui(".x%x.c itemconfigure %x%c -fill %s\n", cv, + o, c,color); +#endif /* ROCKBOX */ +} + +static void delete_object(void* cv,void* o,char c) { +#ifdef ROCKBOX + (void) cv; + (void) o; + (void) c; +#else /* ROCKBOX */ + sys_vgui(".x%x.c delete %x%c\n", + cv, o,c); +#endif /* ROCKBOX */ +} + +static void line(void* cv,void* o,char c,int x,int y,int w,int h,char* color) { +#ifdef ROCKBOX + (void) cv; + (void) o; + (void) c; + (void) x; + (void) y; + (void) w; + (void) h; + (void) color; +#else /* ROCKBOX */ + sys_vgui(".x%x.c create line \ + %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color); +#endif /* ROCKBOX */ +} + + +/* widget helper functions */ + +void gcanvas_drawme(t_gcanvas *x, t_glist *glist, int firsttime) +{ + int i; + if (firsttime) { + rectangle(glist_getcanvas(glist),x,'a', + x->x_obj.te_xpix, x->x_obj.te_ypix, + x->x_width, x->x_height,BACKGROUNDCOLOR); + for (i=1;i<x->x_xgrid;i++) + line(glist_getcanvas(glist),x,'b'+ i, + x->x_obj.te_xpix + x->x_width*i/x->x_xgrid, + x->x_obj.te_ypix, + 0, x->x_height,"red"); + for (i=1;i<x->x_ygrid;i++) + line(glist_getcanvas(glist),x,'B'+ i, + x->x_obj.te_xpix, + x->x_obj.te_ypix + x->x_height*i/x->x_ygrid, + x->x_width, 0,"blue"); + } + else { + move_object( + glist_getcanvas(glist),x,'a', + x->x_obj.te_xpix, x->x_obj.te_ypix, + x->x_width, x->x_height); + for (i=1;i<x->x_xgrid;i++) + move_object(glist_getcanvas(glist),x,'b'+ i, + x->x_obj.te_xpix + x->x_width*i/x->x_xgrid, + x->x_obj.te_ypix, + 0, x->x_height); + for (i=1;i<x->x_ygrid;i++) + move_object(glist_getcanvas(glist),x,'B'+ i, + x->x_obj.te_xpix, + x->x_obj.te_ypix + x->x_height*i/x->x_ygrid, + x->x_width, 0); + } + + { + /* outlets */ + int n = 3; + int nplus, i; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { +#ifndef ROCKBOX + int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, x->x_obj.te_ypix + x->x_height - 1, + onset + IOWIDTH, x->x_obj.te_ypix + x->x_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, x->x_obj.te_ypix + x->x_height - 1, + onset + IOWIDTH, x->x_obj.te_ypix + x->x_height); +#endif /* ROCKBOX */ + } + /* inlets */ + n = 0; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { +#ifndef ROCKBOX + int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, x->x_obj.te_ypix, + onset + IOWIDTH, x->x_obj.te_ypix + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, x->x_obj.te_ypix, + onset + IOWIDTH, x->x_obj.te_ypix + 1); +#endif /* ROCKBOX */ + } + } + +} + + + + +void gcanvas_erase(t_gcanvas* x,t_glist* glist) +{ + int n,i; + delete_object(glist_getcanvas(glist),x,'a'); + for (i=1;i<x->x_xgrid;i++) + delete_object(glist_getcanvas(glist),x,'b'+ i); + for (i=1;i<x->x_ygrid;i++) + delete_object(glist_getcanvas(glist),x,'B'+ i); + + n = 2; + while (n--) { +#ifndef ROCKBOX + sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,n); +#endif + } +} + + + +/* ------------------------ gcanvas widgetbehaviour----------------------------- */ + + +static void gcanvas_getrect(t_gobj *z, t_glist *owner, + int *xp1, int *yp1, int *xp2, int *yp2) +{ +#ifdef ROCKBOX + (void) owner; +#endif + int width, height; + t_gcanvas* s = (t_gcanvas*)z; + + + width = s->x_width; + height = s->x_height; + *xp1 = s->x_obj.te_xpix; + *yp1 = s->x_obj.te_ypix; + *xp2 = s->x_obj.te_xpix + width; + *yp2 = s->x_obj.te_ypix + height; +} + +static void gcanvas_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_gcanvas *x = (t_gcanvas *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + gcanvas_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void gcanvas_select(t_gobj *z, t_glist *glist, int state) +{ + t_gcanvas *x = (t_gcanvas *)z; + color_object(glist,x,'a',state ? "blue" : BACKGROUNDCOLOR); +} + + +static void gcanvas_activate(t_gobj *z, t_glist *glist, int state) +{ +#ifdef ROCKBOX + (void) z; + (void) glist; + (void) state; +#endif +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void gcanvas_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist_getcanvas(glist), x); +} + + +static void gcanvas_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_gcanvas* s = (t_gcanvas*)z; + if (vis) + gcanvas_drawme(s, glist, 1); + else + gcanvas_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void gcanvas_save(t_gobj *z, t_binbuf *b) +{ + t_gcanvas *x = (t_gcanvas *)z; + binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix, + gensym("gcanvas"),x->x_width,x->x_height, + x->x_xgrid, + x->x_ygrid); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior gcanvas_widgetbehavior; + +static void gcanvas_motion(t_gcanvas *x, t_floatarg dx, t_floatarg dy) +{ + x->x += dx; + x->y += dy; + outlet_float(x->out2,x->y); + outlet_float(x->x_obj.ob_outlet,x->x); +} + +void gcanvas_key(t_gcanvas *x, t_floatarg f) +{ +#ifdef ROCKBOX + (void) x; + (void) f; +#endif + post("key"); +} + + +static void gcanvas_click(t_gcanvas *x, + t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, + t_floatarg doit,int up) +{ +#ifdef ROCKBOX + (void) shift; + (void) ctrl; + (void) doit; + (void) up; +#endif + glist_grab(x->x_glist, &x->x_obj.te_g, (t_glistmotionfn) gcanvas_motion, + (t_glistkeyfn) NULL, xpos, ypos); + + x->x = xpos - x->x_obj.te_xpix; + x->y = ypos - x->x_obj.te_ypix; + outlet_float(x->out2,x->y); + outlet_float(x->x_obj.ob_outlet,x->x); + outlet_float(x->out3,0); +} + +static int gcanvas_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ +#ifdef ROCKBOX + (void) glist; +#endif + if (doit) + gcanvas_click((t_gcanvas *)z, (t_floatarg)xpix, (t_floatarg)ypix, + (t_floatarg)shift, 0, (t_floatarg)alt,dbl); + + if (dbl) outlet_float(((t_gcanvas*)z)->out3,1); + return (1); +} + +void gcanvas_size(t_gcanvas* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; + gcanvas_drawme(x, x->x_glist, 0); +} + +static void gcanvas_setwidget(void) +{ + gcanvas_widgetbehavior.w_getrectfn = gcanvas_getrect; + gcanvas_widgetbehavior.w_displacefn = gcanvas_displace; + gcanvas_widgetbehavior.w_selectfn = gcanvas_select; + gcanvas_widgetbehavior.w_activatefn = gcanvas_activate; + gcanvas_widgetbehavior.w_deletefn = gcanvas_delete; + gcanvas_widgetbehavior.w_visfn = gcanvas_vis; + gcanvas_widgetbehavior.w_clickfn = gcanvas_newclick; + class_setsavefn(gcanvas_class,gcanvas_save); +} + + +static void *gcanvas_new(t_symbol* s,t_int ac,t_atom* at) +{ +#ifdef ROCKBOX + (void) s; +#endif + t_gcanvas *x = (t_gcanvas *)pd_new(gcanvas_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + + /* Fetch the width */ + + x->x_width = DEFAULTSIZE; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_width = atom_getfloat(at++); + + if (x->x_width < 0 || x->x_width > 2000) { + error("gcanvas: unallowed width %f",x->x_width); + x->x_width = DEFAULTSIZE; + } + } + + /* Fetch the height */ + + x->x_height = DEFAULTSIZE; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_height = atom_getfloat(at++); + + if (x->x_height < 0 || x->x_height > 2000) { + error("gcanvas: unallowed height %f",x->x_height); + x->x_width = DEFAULTSIZE; + } + } + + /* Fetch the xgrid */ + + x->x_xgrid = 0; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_xgrid = atom_getfloat(at++); + + if (x->x_xgrid < 0 || x->x_xgrid > x->x_width/2) { + error("gcanvas: unallowed xgrid %f",x->x_xgrid); + x->x_xgrid = 0; + } + } + + /* Fetch the ygrid */ + + x->x_ygrid = 0; + if (ac-- > 0) { + if (at->a_type != A_FLOAT) + error("gcanvas: wrong argument type"); + else + x->x_ygrid = atom_getfloat(at++); + + if (x->x_ygrid < 0 || x->x_ygrid > x->x_height/2) { + error("gcanvas: unallowed xgrid %f",x->x_ygrid); + x->x_ygrid = 0; + } + } + + outlet_new(&x->x_obj, &s_float); + x->out2 = outlet_new(&x->x_obj, &s_float); + x->out3 = outlet_new(&x->x_obj, &s_float); + return (x); +} + + + +void gcanvas_setup(void) +{ + gcanvas_class = class_new(gensym("gcanvas"), (t_newmethod)gcanvas_new, 0, + sizeof(t_gcanvas),0, A_GIMME,0); + + class_addmethod(gcanvas_class, (t_method)gcanvas_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(gcanvas_class, (t_method)gcanvas_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + gcanvas_setwidget(); + class_setwidget(gcanvas_class,&gcanvas_widgetbehavior); +} + diff --git a/apps/plugins/pdbox/PDa/extra/highpass.c b/apps/plugins/pdbox/PDa/extra/highpass.c index f97ca23..05e8a06 100644 --- a/apps/plugins/pdbox/PDa/extra/highpass.c +++ b/apps/plugins/pdbox/PDa/extra/highpass.c @@ -1,85 +1,94 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-
-/* ------------------- highpass ----------------------------*/
-
-static t_class *highpass_class;
-
-void highpass_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float alpha = e_alpha(x->x_bw* 0.01,omega);
- t_float b1 = -(1 + cos(omega));
- t_float b0 = -b1/2.;
- t_float b2 = b0;
- t_float a0 = 1 + alpha;
- t_float a1 = -2.*cos(omega);
- t_float a2 = 1 - alpha;
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("highpass: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void highpass_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- highpass_bang(x);
-}
-
-
-static void *highpass_new(t_floatarg f,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
-/* floatinlet_new(&x->x_obj, &x->x_gain); */
- floatinlet_new(&x->x_obj, &x->x_bw);
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- return (x);
-}
-
-
-void highpass_setup(void)
-{
- highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(highpass_class,highpass_bang);
- class_addfloat(highpass_class,highpass_float);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + + +/* ------------------- highpass ----------------------------*/ + +static t_class *highpass_class; + +void highpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = -(1 + cos(omega)); + t_float b0 = -b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highpass_bang(x); +} + + +static void *highpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void highpass_setup(void) +{ + highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highpass_class,highpass_bang); + class_addfloat(highpass_class,highpass_float); +} + diff --git a/apps/plugins/pdbox/PDa/extra/highshelf.c b/apps/plugins/pdbox/PDa/extra/highshelf.c index 74db291..b058a2a 100644 --- a/apps/plugins/pdbox/PDa/extra/highshelf.c +++ b/apps/plugins/pdbox/PDa/extra/highshelf.c @@ -1,90 +1,98 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-
-/* ------------------- highshelf ----------------------------*/
-
-static t_class *highshelf_class;
-
-void highshelf_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float A = e_A(x->x_gain);
- t_float cs = cos(omega);
- t_float sn = sin(omega);
- t_float beta = e_beta(A,x->x_bw* 0.01);
-
- t_float b0 = A*((A+1) + (A-1)*cs + beta*sn);
- t_float b1 =-2.*A*((A-1) + (A+1)*cs);
- t_float b2 = A*((A+1) + (A-1)*cs - beta*sn);
- t_float a0 = ((A+1) - (A-1)*cs + beta*sn);
- t_float a1 = 2.*((A-1) - (A+1)*cs);
- t_float a2 = ((A+1) - (A-1)*cs - beta*sn);
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("highshelf: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void highshelf_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- highshelf_bang(x);
-}
-
-
-static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
- floatinlet_new(&x->x_obj, &x->x_gain);
- floatinlet_new(&x->x_obj, &x->x_bw);
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- if (g != 0.) x->x_gain = g;
- return (x);
-}
-
-
-void highshelf_setup(void)
-{
- highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(highshelf_class,highshelf_bang);
- class_addfloat(highshelf_class,highshelf_float);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + + +/* ------------------- highshelf ----------------------------*/ + +static t_class *highshelf_class; + +void highshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw* 0.01); + + t_float b0 = A*((A+1) + (A-1)*cs + beta*sn); + t_float b1 =-2.*A*((A-1) + (A+1)*cs); + t_float b2 = A*((A+1) + (A-1)*cs - beta*sn); + t_float a0 = ((A+1) - (A-1)*cs + beta*sn); + t_float a1 = 2.*((A-1) - (A+1)*cs); + t_float a2 = ((A+1) - (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("highshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void highshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + highshelf_bang(x); +} + + +static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void highshelf_setup(void) +{ + highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(highshelf_class,highshelf_bang); + class_addfloat(highshelf_class,highshelf_float); +} + diff --git a/apps/plugins/pdbox/PDa/extra/hlshelf.c b/apps/plugins/pdbox/PDa/extra/hlshelf.c index 242a2e6..49f413f 100644 --- a/apps/plugins/pdbox/PDa/extra/hlshelf.c +++ b/apps/plugins/pdbox/PDa/extra/hlshelf.c @@ -1,226 +1,242 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-#include <m_pd.h>
-#include <math.h>
-
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-
-/* ------------------------ hlshelf ----------------------------- */
-
-
-#ifndef M_PI
-#define M_PI 3.141593f
-#endif
-
-#define SRATE 44100.0
-#define MAX_GAIN 120.0f
-
-static t_class *hlshelf_class;
-
-
-typedef struct _hlshelf
-{
- t_object x_obj;
- float s_rate;
- float s_gain0;
- float s_gain1;
- float s_gain2;
- float s_ltransfq;
- float s_htransfq;
- float s_lradians;
- float s_hradians;
-} t_hlshelf;
-
-
-int hlshelf_check_stability(t_float fb1,
- t_float fb2,
- t_float ff1,
- t_float ff2,
- t_float ff3)
-{
- float discriminant = fb1 * fb1 + 4 * fb2;
-
- if (discriminant < 0) /* imaginary roots -- resonant filter */
- {
- /* they're conjugates so we just check that the product
- is less than one */
- if (fb2 >= -1.0f) goto stable;
- }
- else /* real roots */
- {
- /* check that the parabola 1 - fb1 x - fb2 x^2 has a
- vertex between -1 and 1, and that it's nonnegative
- at both ends, which implies both roots are in [1-,1]. */
- if (fb1 <= 2.0f && fb1 >= -2.0f &&
- 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
- goto stable;
- }
- return 0;
-stable:
- return 1;
-}
-
-
-void hlshelf_check(t_hlshelf *x)
-{
-
- if(x->s_gain0 - x->s_gain1 > MAX_GAIN) {
- x->s_gain0 = x->s_gain1 + MAX_GAIN;
- post("setting gain0 to %f",x->s_gain0);
- }
-
-
- if(x->s_gain1 > MAX_GAIN) {
- x->s_gain1 = MAX_GAIN;
- post("setting gain1 to %f",x->s_gain1);
- }
-
- if(x->s_gain2 - x->s_gain1 > MAX_GAIN) {
- x->s_gain2 = x->s_gain1 + MAX_GAIN;
- post("setting gain2 to %f",x->s_gain2);
- }
-
- /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */
- x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f;
-
- if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f;
-
- x->s_lradians = M_PI * x->s_ltransfq / x->s_rate;
- x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate));
-
-}
-
-
-void hlshelf_bang(t_hlshelf *x)
-{
- t_atom at[6];
- float c0, c1, c2, d0, d1, d2; /* output coefs */
- float a1, a2, b1, b2, g1, g2; /* temp coefs */
- double xf;
-
- hlshelf_check(x);
-
- /* low shelf */
- xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */
- if(xf < -200.) /* exp(x) -> 0 */
- {
- a1 = 1.0f;
- b1 = -1.0f;
- g1 = 0.0f;
- }
- else
- {
- double t = tan(x->s_lradians);
- double e = exp(xf);
- double r = t / e;
- double kr = t * e;
-
- a1 = (r - 1) / (r + 1);
- b1 = (kr - 1) / (kr + 1);
- g1 = (kr + 1) / (r + 1);
- }
-
- /* high shelf */
- xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */
- if(xf < -200.) /* exp(x) -> 0 */
- {
- a2 = -1.0f;
- b2 = 1.0f;
- g2 = 0.0f;
- }
- else
- {
- double t = tan(x->s_hradians);
- double e = exp(xf);
- double r = t / e;
- double kr = t * e;
-
- a2 = (1 - r) / (1 + r);
- b2 = (1 - kr) / (1 + kr);
- g2 = (1 + kr) / (1 + r);
- }
-
- /* form product */
- c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ;
- c1 = a1 + a2;
- c2 = a1 * a2;
- d0 = 1.0f;
- d1 = b1 + b2;
- d2 = b1 * b2;
-
- if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) {
- post("hlshelf: filter unstable -> resetting");
- c0=1.;c1=0.;c2=0.;
- d0=1.;d1=0.;d2=0.;
- }
-
- SETFLOAT(at,-c1/d0);
- SETFLOAT(at+1,-c2/d0);
- SETFLOAT(at+2,d0/d0);
- SETFLOAT(at+3,d1/d0);
- SETFLOAT(at+4,d2/d0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-void hlshelf_float(t_hlshelf *x,t_floatarg f)
-{
- x->s_gain0 = f;
- hlshelf_bang(x);
-}
-
-
-static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at)
-{
- t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class);
- t_float k0 = atom_getfloat(at);
- t_float k1 = atom_getfloat(at+1);
- t_float k2 = atom_getfloat(at+2);
- t_float f1 = atom_getfloat(at+3);
- t_float f2 = atom_getfloat(at+4);
-
-
- f1 = atom_getfloat(at);
- f2 = atom_getfloat(at);
-
- if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */
- f1 = 150.0f;
- f2 = 5000.0f;
- }
-
- if (f1 < 0) f1 = 0.0f;
- if (f2 > SRATE) f2 = .5f*SRATE;
-
- x->s_rate = SRATE; /* srate default */
- x->s_gain0 = k0;
- x->s_gain1 = k1;
- x->s_gain2 = k2;
-
- x->s_ltransfq = 0.0f;
- x->s_htransfq = SRATE/2;
-
- x->s_lradians = M_PI * x->s_ltransfq / x->s_rate;
- x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate));
-
- floatinlet_new(&x->x_obj, &x->s_gain1);
- floatinlet_new(&x->x_obj, &x->s_gain2);
- floatinlet_new(&x->x_obj, &x->s_ltransfq);
- floatinlet_new(&x->x_obj, &x->s_htransfq);
- outlet_new(&x->x_obj, &s_list);
-
- return (x);
-}
-
-void hlshelf_setup(void)
-{
- hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0,
- sizeof(t_hlshelf), 0, A_GIMME, 0);
- class_addbang(hlshelf_class,hlshelf_bang);
- class_addfloat(hlshelf_class,hlshelf_float);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#else /* ROCKBOX */ +#include <m_pd.h> +#include <math.h> + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#endif /* ROCKBOX */ + +/* ------------------------ hlshelf ----------------------------- */ + + +#ifndef M_PI +#define M_PI 3.141593f +#endif + +#define SRATE 44100.0 +#define MAX_GAIN 120.0f + +static t_class *hlshelf_class; + + +typedef struct _hlshelf +{ + t_object x_obj; + float s_rate; + float s_gain0; + float s_gain1; + float s_gain2; + float s_ltransfq; + float s_htransfq; + float s_lradians; + float s_hradians; +} t_hlshelf; + + +int hlshelf_check_stability(t_float fb1, + t_float fb2, + t_float ff1, + t_float ff2, + t_float ff3) +{ +#ifdef ROCKBOX + (void) ff1; + (void) ff2; + (void) ff3; +#endif + float discriminant = fb1 * fb1 + 4 * fb2; + + if (discriminant < 0) /* imaginary roots -- resonant filter */ + { + /* they're conjugates so we just check that the product + is less than one */ + if (fb2 >= -1.0f) goto stable; + } + else /* real roots */ + { + /* check that the parabola 1 - fb1 x - fb2 x^2 has a + vertex between -1 and 1, and that it's nonnegative + at both ends, which implies both roots are in [1-,1]. */ + if (fb1 <= 2.0f && fb1 >= -2.0f && + 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) + goto stable; + } + return 0; +stable: + return 1; +} + + +void hlshelf_check(t_hlshelf *x) +{ + + if(x->s_gain0 - x->s_gain1 > MAX_GAIN) { + x->s_gain0 = x->s_gain1 + MAX_GAIN; + post("setting gain0 to %f",x->s_gain0); + } + + + if(x->s_gain1 > MAX_GAIN) { + x->s_gain1 = MAX_GAIN; + post("setting gain1 to %f",x->s_gain1); + } + + if(x->s_gain2 - x->s_gain1 > MAX_GAIN) { + x->s_gain2 = x->s_gain1 + MAX_GAIN; + post("setting gain2 to %f",x->s_gain2); + } + + /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */ + x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f; + + if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + +} + + +void hlshelf_bang(t_hlshelf *x) +{ + t_atom at[6]; + float c0, c1, c2, d0, d1, d2; /* output coefs */ + float a1, a2, b1, b2, g1, g2; /* temp coefs */ + double xf; + + hlshelf_check(x); + + /* low shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a1 = 1.0f; + b1 = -1.0f; + g1 = 0.0f; + } + else + { + double t = tan(x->s_lradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a1 = (r - 1) / (r + 1); + b1 = (kr - 1) / (kr + 1); + g1 = (kr + 1) / (r + 1); + } + + /* high shelf */ + xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ + if(xf < -200.) /* exp(x) -> 0 */ + { + a2 = -1.0f; + b2 = 1.0f; + g2 = 0.0f; + } + else + { + double t = tan(x->s_hradians); + double e = exp(xf); + double r = t / e; + double kr = t * e; + + a2 = (1 - r) / (1 + r); + b2 = (1 - kr) / (1 + kr); + g2 = (1 + kr) / (1 + r); + } + + /* form product */ + c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ; + c1 = a1 + a2; + c2 = a1 * a2; + d0 = 1.0f; + d1 = b1 + b2; + d2 = b1 * b2; + + if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) { + post("hlshelf: filter unstable -> resetting"); + c0=1.;c1=0.;c2=0.; + d0=1.;d1=0.;d2=0.; + } + + SETFLOAT(at,-c1/d0); + SETFLOAT(at+1,-c2/d0); + SETFLOAT(at+2,d0/d0); + SETFLOAT(at+3,d1/d0); + SETFLOAT(at+4,d2/d0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + +void hlshelf_float(t_hlshelf *x,t_floatarg f) +{ + x->s_gain0 = f; + hlshelf_bang(x); +} + + +static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at) +{ +#ifdef ROCKBOX + (void) s; + (void) argc; +#endif + t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class); + t_float k0 = atom_getfloat(at); + t_float k1 = atom_getfloat(at+1); + t_float k2 = atom_getfloat(at+2); + t_float f1 = atom_getfloat(at+3); + t_float f2 = atom_getfloat(at+4); + + + f1 = atom_getfloat(at); + f2 = atom_getfloat(at); + + if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */ + f1 = 150.0f; + f2 = 5000.0f; + } + + if (f1 < 0) f1 = 0.0f; + if (f2 > SRATE) f2 = .5f*SRATE; + + x->s_rate = SRATE; /* srate default */ + x->s_gain0 = k0; + x->s_gain1 = k1; + x->s_gain2 = k2; + + x->s_ltransfq = 0.0f; + x->s_htransfq = SRATE/2; + + x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; + x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); + + floatinlet_new(&x->x_obj, &x->s_gain1); + floatinlet_new(&x->x_obj, &x->s_gain2); + floatinlet_new(&x->x_obj, &x->s_ltransfq); + floatinlet_new(&x->x_obj, &x->s_htransfq); + outlet_new(&x->x_obj, &s_list); + + return (x); +} + +void hlshelf_setup(void) +{ + hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0, + sizeof(t_hlshelf), 0, A_GIMME, 0); + class_addbang(hlshelf_class,hlshelf_bang); + class_addfloat(hlshelf_class,hlshelf_float); +} + diff --git a/apps/plugins/pdbox/PDa/extra/image.c b/apps/plugins/pdbox/PDa/extra/image.c index 946a363..7f55a01 100644 --- a/apps/plugins/pdbox/PDa/extra/image.c +++ b/apps/plugins/pdbox/PDa/extra/image.c @@ -23,6 +23,11 @@ typedef struct _image void image_drawme(t_image *x, t_glist *glist, int firsttime) { +#ifdef ROCKBOX + (void) x; + (void) glist; + (void) firsttime; +#else /* ROCKBOX */ if (firsttime) { char fname[MAXPDSTRING]; canvas_makefilename(glist_getcanvas(x->x_glist), x->x_fname->s_name, @@ -42,16 +47,20 @@ void image_drawme(t_image *x, t_glist *glist, int firsttime) glist_getcanvas(glist), x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); } - +#endif /* ROCKBOX */ } void image_erase(t_image* x,t_glist* glist) { +#ifdef ROCKBOX + (void) x; + (void) glist; +#else /* ROCKBOX */ int n; sys_vgui(".x%x.c delete %xS\n", glist_getcanvas(glist), x); - +#endif /* ROCKBOX */ } @@ -80,17 +89,23 @@ static void image_displace(t_gobj *z, t_glist *glist, t_image *x = (t_image *)z; x->x_obj.te_xpix += dx; x->x_obj.te_ypix += dy; +#ifndef ROCKBOX sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", glist_getcanvas(glist), x, text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height); - +#endif image_drawme(x, glist, 0); canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); } static void image_select(t_gobj *z, t_glist *glist, int state) { +#ifdef ROCKBOX + (void) z; + (void) glist; + (void) state; +#else /* ROCKBOX */ t_image *x = (t_image *)z; if (state) { sys_vgui(".x%x.c create rectangle \ @@ -104,14 +119,17 @@ static void image_select(t_gobj *z, t_glist *glist, int state) sys_vgui(".x%x.c delete %xSEL\n", glist_getcanvas(glist), x); } - - - +#endif /* ROCKBOX */ } static void image_activate(t_gobj *z, t_glist *glist, int state) { +#ifdef ROCKBOX + (void) z; + (void) glist; + (void) state; +#endif /* t_text *x = (t_text *)z; t_rtext *y = glist_findrtext(glist, x); if (z->g_pd != gatom_class) rtext_activate(y, state);*/ @@ -154,6 +172,10 @@ void image_size(t_image* x,t_floatarg w,t_floatarg h) { void image_color(t_image* x,t_symbol* col) { +#ifdef ROCKBOX + (void) x; + (void) col; +#endif /* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang .. so color black does the same as bang, but doesn't forward the bang */ @@ -167,11 +189,11 @@ static void image_setwidget(void) image_widgetbehavior.w_activatefn = image_activate; image_widgetbehavior.w_deletefn = image_delete; image_widgetbehavior.w_visfn = image_vis; -#if (PD_VERSION_MINOR > 31) +#if defined(PD_VERSION_MINOR) && (PD_VERSION_MINOR > 31) image_widgetbehavior.w_clickfn = NULL; image_widgetbehavior.w_propertiesfn = NULL; #endif -#if PD_MINOR_VERSION < 37 +#if defined(PD_VERSION_MINOR) && PD_MINOR_VERSION < 37 image_widgetbehavior.w_savefn = image_save; #endif } diff --git a/apps/plugins/pdbox/PDa/extra/lowpass.c b/apps/plugins/pdbox/PDa/extra/lowpass.c index 251b717..18de4af 100644 --- a/apps/plugins/pdbox/PDa/extra/lowpass.c +++ b/apps/plugins/pdbox/PDa/extra/lowpass.c @@ -1,87 +1,94 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-
-
-/* ------------------- lowpass ----------------------------*/
-
-static t_class *lowpass_class;
-
-void lowpass_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float alpha = e_alpha(x->x_bw*0.01,omega);
- t_float b1 = 1 - cos(omega);
- t_float b0 = b1/2.;
- t_float b2 = b0;
- t_float a0 = 1 + alpha;
- t_float a1 = -2.*cos(omega);
- t_float a2 = 1 - alpha;
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("lowpass: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void lowpass_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- lowpass_bang(x);
-}
-
-
-static void *lowpass_new(t_floatarg f,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
-/* floatinlet_new(&x->x_obj, &x->x_gain); */
- floatinlet_new(&x->x_obj, &x->x_bw);
-
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- return (x);
-}
-
-
-void lowpass_setup(void)
-{
- lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(lowpass_class,lowpass_bang);
- class_addfloat(lowpass_class,lowpass_float);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + + +/* ------------------- lowpass ----------------------------*/ + +static t_class *lowpass_class; + +void lowpass_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw*0.01,omega); + t_float b1 = 1 - cos(omega); + t_float b0 = b1/2.; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowpass: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowpass_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowpass_bang(x); +} + + +static void *lowpass_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void lowpass_setup(void) +{ + lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowpass_class,lowpass_bang); + class_addfloat(lowpass_class,lowpass_float); +} + diff --git a/apps/plugins/pdbox/PDa/extra/lowshelf.c b/apps/plugins/pdbox/PDa/extra/lowshelf.c index ba32b6d..77086ba 100644 --- a/apps/plugins/pdbox/PDa/extra/lowshelf.c +++ b/apps/plugins/pdbox/PDa/extra/lowshelf.c @@ -1,91 +1,98 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-
-
-/* ------------------- lowshelf ----------------------------*/
-
-static t_class *lowshelf_class;
-
-void lowshelf_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float A = e_A(x->x_gain);
- t_float cs = cos(omega);
- t_float sn = sin(omega);
- t_float beta = e_beta(A,x->x_bw*0.01);
-
- t_float b0 = A*((A+1) - (A-1)*cs + beta*sn);
- t_float b1 = 2.*A*((A-1) - (A+1)*cs);
- t_float b2 = A*((A+1) - (A-1)*cs - beta*sn);
- t_float a0 = ((A+1) + (A-1)*cs + beta*sn);
- t_float a1 = -2.*((A-1) + (A+1)*cs);
- t_float a2 = ((A+1) + (A-1)*cs - beta*sn);
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("lowshelf: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void lowshelf_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- lowshelf_bang(x);
-}
-
-
-static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
- floatinlet_new(&x->x_obj, &x->x_gain);
- floatinlet_new(&x->x_obj, &x->x_bw);
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- if (g != 0.) x->x_gain = g;
- return (x);
-}
-
-
-void lowshelf_setup(void)
-{
- lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(lowshelf_class,lowshelf_bang);
- class_addfloat(lowshelf_class,lowshelf_float);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + + +/* ------------------- lowshelf ----------------------------*/ + +static t_class *lowshelf_class; + +void lowshelf_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float A = e_A(x->x_gain); + t_float cs = cos(omega); + t_float sn = sin(omega); + t_float beta = e_beta(A,x->x_bw*0.01); + + t_float b0 = A*((A+1) - (A-1)*cs + beta*sn); + t_float b1 = 2.*A*((A-1) - (A+1)*cs); + t_float b2 = A*((A+1) - (A-1)*cs - beta*sn); + t_float a0 = ((A+1) + (A-1)*cs + beta*sn); + t_float a1 = -2.*((A-1) + (A+1)*cs); + t_float a2 = ((A+1) + (A-1)*cs - beta*sn); + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("lowshelf: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void lowshelf_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + lowshelf_bang(x); +} + + +static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); + floatinlet_new(&x->x_obj, &x->x_gain); + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + if (g != 0.) x->x_gain = g; + return (x); +} + + +void lowshelf_setup(void) +{ + lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(lowshelf_class,lowshelf_bang); + class_addfloat(lowshelf_class,lowshelf_float); +} + diff --git a/apps/plugins/pdbox/PDa/extra/moog~.c b/apps/plugins/pdbox/PDa/extra/moog~.c index 48d4dfe..29525db 100644 --- a/apps/plugins/pdbox/PDa/extra/moog~.c +++ b/apps/plugins/pdbox/PDa/extra/moog~.c @@ -1,184 +1,194 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-#include "math.h"
-#include <m_pd.h>
-
-/* ----------------------------- moog ----------------------------- */
-static t_class *moog_class;
-
-
-typedef struct _moog
-{
- t_object x_obj;
- t_pd in2;
- t_sample x_1,x_2,x_3,x_4;
- t_sample y_1,y_2,y_3,y_4;
-} t_moog;
-
-static void moog_reset(t_moog *x)
-{
- x->x_1 = x->x_2 = x->x_3 = x->x_4 = 0;
- x->y_1 = x->y_2 = x->y_3 = x->y_4 = 0;
-
-}
-
-
-
-static void *moog_new(t_symbol *s, int argc, t_atom *argv)
-{
- if (argc > 1) post("moog~: extra arguments ignored");
- {
- t_moog *x = (t_moog *)pd_new(moog_class);
- outlet_new(&x->x_obj, &s_signal);
- inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
- inlet_new(&x->x_obj, &x->in2, &s_signal, &s_signal);
- moog_reset(x);
- return (x);
- }
-
-
-}
-
-
-
-static t_sample calc_k(t_sample f,t_sample k) {
- if (k>itofix(4)) k = itofix(4);
- if (k < 0) k = 0;
- if (f <= itofix(3800)) return k;
- k = k - mult(0.5,(f-idiv(itofix(3800),itofix(4300))));
- return k;
-}
-
-t_int *moog_perform(t_int *w)
-{
- t_moog* x = (t_moog*) (w[1]);
- t_sample *in1 = (t_sample *)(w[2]);
- t_sample *p = (t_sample *)(w[3]);
- t_sample *k = (t_sample *)(w[4]);
-
- t_sample *out = (t_sample *)(w[5]);
- int n = (int)(w[6]);
- t_sample in;
- t_sample pt,pt1;
-
- t_sample x1 = x->x_1;
- t_sample x2 = x->x_2;
- t_sample x3 = x->x_3;
- t_sample x4 = x->x_4;
- t_sample ys1 = x->y_1;
- t_sample ys2 = x->y_2;
- t_sample ys3 = x->y_3;
- t_sample ys4 = x->y_4;
-
-
- while (n--) {
- if (*p > itofix(8140)) *p = itofix(8140);
- *k = calc_k(*p,*k);
- pt =*p;
- pt1=mult((pt+1),ftofix(0.76923077));
- in = *in1++ - mult(*k,ys4);
- ys1 = mult(pt1,in) + mult(0.3,x1) - mult(pt,ys1);
- x1 = in;
- ys2 = mult(pt1,ys1) + mult(0.3,x2) - mult(pt,ys2);
- x2 = ys1;
- ys3 = mult(pt1,ys2) + mult(0.3,x3) - mult(pt,ys3);
- x3 = ys2;
- ys4 = mult(pt1,ys3) + mult(0.3,x4) - mult(pt,ys4);
- x4 = ys3;
- *out++ = ys4;
- }
-
-
- x->y_1 = ys1;
- x->y_2 = ys2;
- x->y_3 = ys3;
- x->y_4 = ys4;
- x->x_1 = x1;
- x->x_2 = x2;
- x->x_3 = x3;
- x->x_4 = x4;
-
- return (w+7);
-}
-
-
-#define CLIP(x) x = ((x) > 1.0 ? (1.0) : (x))
-
-t_int *moog_perf8(t_int *w)
-{
- t_moog* x = (t_moog*) (w[1]);
- t_sample *in1 = (t_sample *)(w[2]);
- t_sample *p = (t_sample *)(w[3]);
- t_sample *k = (t_sample *)(w[4]);
- t_sample *out = (t_sample *)(w[5]);
- int n = (int)(w[6]);
-
- t_sample x1 = x->x_1;
- t_sample x2 = x->x_2;
- t_sample x3 = x->x_3;
- t_sample x4 = x->x_4;
- t_sample ys1 = x->y_1;
- t_sample ys2 = x->y_2;
- t_sample ys3 = x->y_3;
- t_sample ys4 = x->y_4;
-
- t_sample temp,temp2;
- t_sample pt,pt1;
- t_sample in;
-
- while (n--) {
- if (*p > itofix(8140)) *p = itofix(8140);
- *k = calc_k(*p,*k);
-
- pt =mult(*p, ftofix(0.01*0.0140845)) - ftofix(0.9999999f);
- pt1=mult((pt+itofix(1)),ftofix(0.76923077));
- in = *in1++ - mult(*k,ys4);
- ys1 = mult(pt1,(in + mult(ftofix(0.3),x1))) - mult(pt,ys1);
- x1 = in;
- ys2 = mult(pt1,(ys1 + mult(0.3,x2))) - mult(pt,ys2);
- x2 = ys1;
- ys3 = mult(pt1,(ys2 + mult(0.3,x3))) - mult(pt,ys3);
- x3 = ys2;
- ys4 = mult(pt1,(ys3 + mult(0.3,x4))) - mult(pt,ys4);
- x4 = ys3;
- *out++ = ys4;
-
- p++;k++;
- }
-
- x->y_1 = ys1;
- x->y_2 = ys2;
- x->y_3 = ys3;
- x->y_4 = ys4;
- x->x_1 = x1;
- x->x_2 = x2;
- x->x_3 = x3;
- x->x_4 = x4;
-
- return (w+7);
-}
-
-void dsp_add_moog(t_moog *x, t_sample *in1, t_sample *in2, t_sample *in3, t_sample *out, int n)
-{
- if (n&7)
- dsp_add(moog_perform, 6,(t_int)x, in1,in2,in3, out, n);
- else
- dsp_add(moog_perf8, 6,(t_int) x, in1, in2, in3, out, n);
-}
-
-static void moog_dsp(t_moog *x, t_signal **sp)
-{
- dsp_add_moog(x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,sp[0]->s_n);
-}
-
-
-void moog_tilde_setup(void)
-{
- moog_class = class_new(gensym("moog~"), (t_newmethod)moog_new, 0,
- sizeof(t_moog), 0, A_GIMME, 0);
- class_addmethod(moog_class, nullfn, gensym("signal"), 0);
- class_addmethod(moog_class, (t_method)moog_reset, gensym("reset"), 0);
- class_addmethod(moog_class, (t_method)moog_dsp, gensym("dsp"), A_NULL);
-}
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +#include "math.h" +#ifdef ROCKBOX +#include "m_pd.h" +#else +#include <m_pd.h> +#endif + +/* ----------------------------- moog ----------------------------- */ +static t_class *moog_class; + + +typedef struct _moog +{ + t_object x_obj; + t_pd in2; + t_sample x_1,x_2,x_3,x_4; + t_sample y_1,y_2,y_3,y_4; +} t_moog; + +static void moog_reset(t_moog *x) +{ + x->x_1 = x->x_2 = x->x_3 = x->x_4 = 0; + x->y_1 = x->y_2 = x->y_3 = x->y_4 = 0; + +} + + + +static void *moog_new(t_symbol *s, int argc, t_atom *argv) +{ +#ifdef ROCKBOX + (void) s; + (void) argv; +#endif + if (argc > 1) post("moog~: extra arguments ignored"); + { + t_moog *x = (t_moog *)pd_new(moog_class); + outlet_new(&x->x_obj, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->in2, &s_signal, &s_signal); + moog_reset(x); + return (x); + } + + +} + + + +static t_sample calc_k(t_sample f,t_sample k) { + if (k>itofix(4)) k = itofix(4); + if (k < 0) k = 0; + if (f <= itofix(3800)) return k; + k = k - mult(0.5,(f-idiv(itofix(3800),itofix(4300)))); + return k; +} + +t_int *moog_perform(t_int *w) +{ + t_moog* x = (t_moog*) (w[1]); + t_sample *in1 = (t_sample *)(w[2]); + t_sample *p = (t_sample *)(w[3]); + t_sample *k = (t_sample *)(w[4]); + + t_sample *out = (t_sample *)(w[5]); + int n = (int)(w[6]); + t_sample in; + t_sample pt,pt1; + + t_sample x1 = x->x_1; + t_sample x2 = x->x_2; + t_sample x3 = x->x_3; + t_sample x4 = x->x_4; + t_sample ys1 = x->y_1; + t_sample ys2 = x->y_2; + t_sample ys3 = x->y_3; + t_sample ys4 = x->y_4; + + + while (n--) { + if (*p > itofix(8140)) *p = itofix(8140); + *k = calc_k(*p,*k); + pt =*p; + pt1=mult((pt+1),ftofix(0.76923077)); + in = *in1++ - mult(*k,ys4); + ys1 = mult(pt1,in) + mult(0.3,x1) - mult(pt,ys1); + x1 = in; + ys2 = mult(pt1,ys1) + mult(0.3,x2) - mult(pt,ys2); + x2 = ys1; + ys3 = mult(pt1,ys2) + mult(0.3,x3) - mult(pt,ys3); + x3 = ys2; + ys4 = mult(pt1,ys3) + mult(0.3,x4) - mult(pt,ys4); + x4 = ys3; + *out++ = ys4; + } + + + x->y_1 = ys1; + x->y_2 = ys2; + x->y_3 = ys3; + x->y_4 = ys4; + x->x_1 = x1; + x->x_2 = x2; + x->x_3 = x3; + x->x_4 = x4; + + return (w+7); +} + + +#define CLIP(x) x = ((x) > 1.0 ? (1.0) : (x)) + +t_int *moog_perf8(t_int *w) +{ + t_moog* x = (t_moog*) (w[1]); + t_sample *in1 = (t_sample *)(w[2]); + t_sample *p = (t_sample *)(w[3]); + t_sample *k = (t_sample *)(w[4]); + t_sample *out = (t_sample *)(w[5]); + int n = (int)(w[6]); + + t_sample x1 = x->x_1; + t_sample x2 = x->x_2; + t_sample x3 = x->x_3; + t_sample x4 = x->x_4; + t_sample ys1 = x->y_1; + t_sample ys2 = x->y_2; + t_sample ys3 = x->y_3; + t_sample ys4 = x->y_4; + +#ifndef ROCKBOX + t_sample temp,temp2; +#endif + t_sample pt,pt1; + t_sample in; + + while (n--) { + if (*p > itofix(8140)) *p = itofix(8140); + *k = calc_k(*p,*k); + + pt =mult(*p, ftofix(0.01*0.0140845)) - ftofix(0.9999999f); + pt1=mult((pt+itofix(1)),ftofix(0.76923077)); + in = *in1++ - mult(*k,ys4); + ys1 = mult(pt1,(in + mult(ftofix(0.3),x1))) - mult(pt,ys1); + x1 = in; + ys2 = mult(pt1,(ys1 + mult(0.3,x2))) - mult(pt,ys2); + x2 = ys1; + ys3 = mult(pt1,(ys2 + mult(0.3,x3))) - mult(pt,ys3); + x3 = ys2; + ys4 = mult(pt1,(ys3 + mult(0.3,x4))) - mult(pt,ys4); + x4 = ys3; + *out++ = ys4; + + p++;k++; + } + + x->y_1 = ys1; + x->y_2 = ys2; + x->y_3 = ys3; + x->y_4 = ys4; + x->x_1 = x1; + x->x_2 = x2; + x->x_3 = x3; + x->x_4 = x4; + + return (w+7); +} + +void dsp_add_moog(t_moog *x, t_sample *in1, t_sample *in2, t_sample *in3, t_sample *out, int n) +{ + if (n&7) + dsp_add(moog_perform, 6,(t_int)x, in1,in2,in3, out, n); + else + dsp_add(moog_perf8, 6,(t_int) x, in1, in2, in3, out, n); +} + +static void moog_dsp(t_moog *x, t_signal **sp) +{ + dsp_add_moog(x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,sp[0]->s_n); +} + + +void moog_tilde_setup(void) +{ + moog_class = class_new(gensym("moog~"), (t_newmethod)moog_new, 0, + sizeof(t_moog), 0, A_GIMME, 0); + class_addmethod(moog_class, nullfn, gensym("signal"), 0); + class_addmethod(moog_class, (t_method)moog_reset, gensym("reset"), 0); + class_addmethod(moog_class, (t_method)moog_dsp, gensym("dsp"), A_NULL); +} diff --git a/apps/plugins/pdbox/PDa/extra/notch.c b/apps/plugins/pdbox/PDa/extra/notch.c index 0ab4332..44f0299 100644 --- a/apps/plugins/pdbox/PDa/extra/notch.c +++ b/apps/plugins/pdbox/PDa/extra/notch.c @@ -1,85 +1,93 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-
-/*
-
- These filter coefficients computations are taken from
- http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
-
- written by Robert Bristow-Johnson
-
-*/
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-#include <math.h>
-#include "filters.h"
-
-
-
-/* ------------------- notch ----------------------------*/
-
-static t_class *notch_class;
-
-void notch_bang(t_rbjfilter *x)
-{
- t_atom at[5];
- t_float omega = e_omega(x->x_freq,x->x_rate);
- t_float alpha = e_alpha(x->x_bw* 0.01,omega);
- t_float b1 = -2.*cos(omega);
- t_float b0 = 1;
- t_float b2 = b0;
- t_float a0 = 1 + alpha;
- t_float a1 = -2.*cos(omega);
- t_float a2 = 1 - alpha;
-
-/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
-
- if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
- post("notch: filter unstable -> resetting");
- a0=1.;a1=0.;a2=0.;
- b0=1.;b1=0.;b2=0.;
- }
-
- SETFLOAT(at,-a1/a0);
- SETFLOAT(at+1,-a2/a0);
- SETFLOAT(at+2,b0/a0);
- SETFLOAT(at+3,b1/a0);
- SETFLOAT(at+4,b2/a0);
-
- outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
-}
-
-
-void notch_float(t_rbjfilter *x,t_floatarg f)
-{
- x->x_freq = f;
- notch_bang(x);
-}
-
-
-static void *notch_new(t_floatarg f,t_floatarg bw)
-{
- t_rbjfilter *x = (t_rbjfilter *)pd_new(notch_class);
-
- x->x_rate = 44100.0;
- outlet_new(&x->x_obj,&s_float);
-/* floatinlet_new(&x->x_obj, &x->x_gain); */
- floatinlet_new(&x->x_obj, &x->x_bw);
- if (f > 0.) x->x_freq = f;
- if (bw > 0.) x->x_bw = bw;
- return (x);
-}
-
-
-void notch_setup(void)
-{
- notch_class = class_new(gensym("notch"), (t_newmethod)notch_new, 0,
- sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
- class_addbang(notch_class,notch_bang);
- class_addfloat(notch_class,notch_float);
-}
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + + +/* + + These filter coefficients computations are taken from + http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt + + written by Robert Bristow-Johnson + +*/ + +#ifdef ROCKBOX +#include "plugin.h" +#include "pdbox.h" +#include "m_pd.h" +#include "math.h" +#include "filters.h" +#else /* ROCKBOX */ +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif +#include <math.h> +#include "filters.h" +#endif /* ROCKBOX */ + + + +/* ------------------- notch ----------------------------*/ + +static t_class *notch_class; + +void notch_bang(t_rbjfilter *x) +{ + t_atom at[5]; + t_float omega = e_omega(x->x_freq,x->x_rate); + t_float alpha = e_alpha(x->x_bw* 0.01,omega); + t_float b1 = -2.*cos(omega); + t_float b0 = 1; + t_float b2 = b0; + t_float a0 = 1 + alpha; + t_float a1 = -2.*cos(omega); + t_float a2 = 1 - alpha; + +/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */ + + if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) { + post("notch: filter unstable -> resetting"); + a0=1.;a1=0.;a2=0.; + b0=1.;b1=0.;b2=0.; + } + + SETFLOAT(at,-a1/a0); + SETFLOAT(at+1,-a2/a0); + SETFLOAT(at+2,b0/a0); + SETFLOAT(at+3,b1/a0); + SETFLOAT(at+4,b2/a0); + + outlet_list(x->x_obj.ob_outlet,&s_list,5,at); +} + + +void notch_float(t_rbjfilter *x,t_floatarg f) +{ + x->x_freq = f; + notch_bang(x); +} + + +static void *notch_new(t_floatarg f,t_floatarg bw) +{ + t_rbjfilter *x = (t_rbjfilter *)pd_new(notch_class); + + x->x_rate = 44100.0; + outlet_new(&x->x_obj,&s_float); +/* floatinlet_new(&x->x_obj, &x->x_gain); */ + floatinlet_new(&x->x_obj, &x->x_bw); + if (f > 0.) x->x_freq = f; + if (bw > 0.) x->x_bw = bw; + return (x); +} + + +void notch_setup(void) +{ + notch_class = class_new(gensym("notch"), (t_newmethod)notch_new, 0, + sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0); + class_addbang(notch_class,notch_bang); + class_addfloat(notch_class,notch_float); +} diff --git a/apps/plugins/pdbox/PDa/extra/sendOSC.c b/apps/plugins/pdbox/PDa/extra/sendOSC.c index bc983cc..ac7ae37 100644 --- a/apps/plugins/pdbox/PDa/extra/sendOSC.c +++ b/apps/plugins/pdbox/PDa/extra/sendOSC.c @@ -1,1461 +1,1461 @@ -/*
-Written by Matt Wright, The Center for New Music and Audio Technologies,
-University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
-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
-*/
-
-
-/* sendOSC.c
-
- Matt Wright, 6/3/97
- based on sendOSC.c, which was based on a version by Adrian Freed
-
- Text-based OpenSoundControl client. User can enter messages via command
- line arguments or standard input.
-
- Version 0.1: "play" feature
- Version 0.2: Message type tags.
-
- pd version branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/sendOSC/sendOSC.c
- -------------
- -- added bundle stuff to send. jdl 20020416
- -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
- -- ost_at_test.at + i22_at_test.at, 2000-2002
- modified to compile as pd externel
-*/
-
-#define MAX_ARGS 2000
-#define SC_BUFFER_SIZE 64000
-
-#include "m_pd.h"
-#include "OSC-client.h"
-
-#include <string.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <io.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <signal.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <rpc/rpc.h>
-#include <sys/times.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <netdb.h>
-#endif
-
-#ifdef __APPLE__
- #include <string.h>
-#endif
-
-#define UNIXDG_PATH "/tmp/htm"
-#define UNIXDG_TMP "/tmp/htm.XXXXXX"
-
-
-
-OSCTimeTag OSCTT_Immediately(void) {
- OSCTimeTag result;
- result.seconds = 0;
- result.fraction = 1;
- return result;
-}
-
-
-OSCTimeTag OSCTT_CurrentTime(void) {
- OSCTimeTag result;
- result.seconds = 0;
- result.fraction = 1;
- return result;
-}
-
-OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
- OSCTimeTag result;
- result.seconds = 0;
- result.fraction = 1;
- return result;
-}
-
-
-typedef int bool;
-
-typedef struct
-{
- float srate;
-
- struct sockaddr_in serv_addr; /* udp socket */
- #ifndef WIN32
- struct sockaddr_un userv_addr; /* UNIX socket */
- #endif
- int sockfd; /* socket file descriptor */
- int index, len,uservlen;
- void *addr;
- int id;
-} desc;
-
-
-/* open a socket for HTM communication to given host on given portnumber */
-/* if host is 0 then UNIX protocol is used (i.e. local communication */
-void *OpenHTMSocket(char *host, int portnumber)
-{
- struct sockaddr_in cl_addr;
- #ifndef WIN32
- int sockfd;
- struct sockaddr_un ucl_addr;
- #else
- unsigned int sockfd;
- #endif
-
- desc *o;
- int oval = 1;
- o = malloc(sizeof(*o));
- if(!o) return 0;
-
- #ifndef WIN32
-
- if(!host)
- {
- char *mktemp(char *);
- int clilen;
- o->len = sizeof(ucl_addr);
- /*
- * Fill in the structure "userv_addr" with the address of the
- * server that we want to send to.
- */
-
- bzero((char *) &o->userv_addr, sizeof(o->userv_addr));
- o->userv_addr.sun_family = AF_UNIX;
- strcpy(o->userv_addr.sun_path, UNIXDG_PATH);
- sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber);
- o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path);
- o->addr = &(o->userv_addr);
- /*
- * Open a socket (a UNIX domain datagram socket).
- */
-
- if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0)
- {
- /*
- * Bind a local address for us.
- * In the UNIX domain we have to choose our own name (that
- * should be unique). We'll use mktemp() to create a unique
- * pathname, based on our process id.
- */
-
- bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */
- ucl_addr.sun_family = AF_UNIX;
- strcpy(ucl_addr.sun_path, UNIXDG_TMP);
-
- mktemp(ucl_addr.sun_path);
- clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path);
-
- if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0)
- {
- perror("client: can't bind local address");
- close(sockfd);
- sockfd = -1;
- }
- }
- else
- perror("unable to make socket\n");
-
- }else
-
- #endif
-
- {
- /*
- * Fill in the structure "serv_addr" with the address of the
- * server that we want to send to.
- */
- o->len = sizeof(cl_addr);
-
- #ifdef WIN32
- ZeroMemory((char *)&o->serv_addr, sizeof(o->serv_addr));
- #else
- bzero((char *)&o->serv_addr, sizeof(o->serv_addr));
- #endif
-
- o->serv_addr.sin_family = AF_INET;
-
- /* MW 6/6/96: Call gethostbyname() instead of inet_addr(),
- so that host can be either an Internet host name (e.g.,
- "les") or an Internet address in standard dot notation
- (e.g., "128.32.122.13") */
- {
- struct hostent *hostsEntry;
- unsigned long address;
-
- hostsEntry = gethostbyname(host);
- if (hostsEntry == NULL) {
- fprintf(stderr, "Couldn't decipher host name \"%s\"\n", host);
- #ifndef WIN32
- herror(NULL);
- #endif
- return 0;
- }
- address = *((unsigned long *) hostsEntry->h_addr_list[0]);
- o->serv_addr.sin_addr.s_addr = address;
- }
-
- /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */
-
- /* End MW changes */
-
- /*
- * Open a socket (a UDP domain datagram socket).
- */
-
-
- #ifdef WIN32
- o->serv_addr.sin_port = htons((USHORT)portnumber);
- o->addr = &(o->serv_addr);
- if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) {
- ZeroMemory((char *)&cl_addr, sizeof(cl_addr));
- cl_addr.sin_family = AF_INET;
- cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- cl_addr.sin_port = htons(0);
-
- // enable broadcast: jdl ~2003
- if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
- perror("setsockopt");
- }
-
- if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
- perror("could not bind\n");
- closesocket(sockfd);
- sockfd = -1;
- }
- }
- else { perror("unable to make socket\n");}
- #else
- o->serv_addr.sin_port = htons(portnumber);
- o->addr = &(o->serv_addr);
- if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
- bzero((char *)&cl_addr, sizeof(cl_addr));
- cl_addr.sin_family = AF_INET;
- cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- cl_addr.sin_port = htons(0);
-
- // enable broadcast: jdl ~2003
- if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
- perror("setsockopt");
- }
-
- if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
- perror("could not bind\n");
- close(sockfd);
- sockfd = -1;
- }
- }
- else { perror("unable to make socket\n");}
- #endif
- }
- #ifdef WIN32
- if(sockfd == INVALID_SOCKET) {
- #else
- if(sockfd < 0) {
- #endif
- free(o);
- o = 0;
- }
- else
- o->sockfd = sockfd;
- return o;
-}
-
-static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b)
-{
- int rcount;
- if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count)
- {
- printf("sockfd %d count %d rcount %dlength %d\n", sockfd,count,rcount,length);
- return FALSE;
- }
- return TRUE;
-}
-
-bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer)
-{
- desc *o = (desc *)htmsendhandle;
- return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer);
-}
-void CloseHTMSocket(void *htmsendhandle)
-{
- desc *o = (desc *)htmsendhandle;
- #ifdef WIN32
- if(SOCKET_ERROR == closesocket(o->sockfd)) {
- perror("CloseHTMSocket::closesocket failed\n");
- return;
- }
- #else
- if(close(o->sockfd) == -1)
- {
- perror("CloseHTMSocket::closesocket failed");
- return;
- }
- #endif
-
- free(o);
-}
-
-
-///////////////////////
-// from sendOSC
-
-typedef struct {
- //enum {INT, FLOAT, STRING} type;
- enum {INT_osc, FLOAT_osc, STRING_osc} type;
- union {
- int i;
- float f;
- char *s;
- } datum;
-} typedArg;
-
-void CommandLineMode(int argc, char *argv[], void *htmsocket);
-OSCTimeTag ParseTimeTag(char *s);
-void ParseInteractiveLine(OSCbuf *buf, char *mesg);
-typedArg ParseToken(char *token);
-int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args);
-void SendBuffer(void *htmsocket, OSCbuf *buf);
-void SendData(void *htmsocket, int size, char *data);
-/* defined in OSC-system-dependent.c now */
-
-//static void *htmsocket;
-static int exitStatus = 0;
-static int useTypeTags = 0;
-
-static char bufferForOSCbuf[SC_BUFFER_SIZE];
-
-
-/////////
-// end from sendOSC
-
-static t_class *sendOSC_class;
-
-typedef struct _sendOSC
-{
- t_object x_obj;
- int x_protocol; // UDP/TCP (udp only atm)
- t_int x_typetags; // typetag flag
- void *x_htmsocket; // sending socket
- int x_bundle; // bundle open flag
- OSCbuf x_oscbuf[1]; // OSCbuffer
- t_outlet *x_bdpthout;// bundle-depth floatoutlet
-} t_sendOSC;
-
-static void *sendOSC_new(t_floatarg udpflag)
-{
- t_sendOSC *x = (t_sendOSC *)pd_new(sendOSC_class);
- outlet_new(&x->x_obj, &s_float);
- x->x_htmsocket = 0; // {{raf}}
- // set udp
- x->x_protocol = SOCK_STREAM;
- // set typetags to 1 by default
- x->x_typetags = 1;
- // bunlde is closed
- x->x_bundle = 0;
- OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
- x->x_bdpthout = outlet_new(&x->x_obj, 0); // outlet_float();
- //x->x_oscbuf =
- return (x);
-}
-
-
-void sendOSC_openbundle(t_sendOSC *x)
-{
- if (x->x_oscbuf->bundleDepth + 1 >= MAX_BUNDLE_NESTING ||
- OSC_openBundle(x->x_oscbuf, OSCTT_Immediately()))
- {
- post("Problem opening bundle: %s\n", OSC_errorMessage);
- return;
- }
- x->x_bundle = 1;
- outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
-}
-
-static void sendOSC_closebundle(t_sendOSC *x)
-{
- if (OSC_closeBundle(x->x_oscbuf)) {
- post("Problem closing bundle: %s\n", OSC_errorMessage);
- return;
- }
- outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
- // in bundle mode we send when bundle is closed?
- if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) {
- // post("x_oscbuf: something inside me?");
- if (x->x_htmsocket) {
- SendBuffer(x->x_htmsocket, x->x_oscbuf);
- } else {
- post("sendOSC: not connected");
- }
- OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
- x->x_bundle = 0;
- return;
- }
- // post("x_oscbuf: something went wrong");
-}
-
-static void sendOSC_settypetags(t_sendOSC *x, t_float *f)
- {
- x->x_typetags = (int)f;
- post("sendOSC.c: setting typetags %d",x->x_typetags);
- }
-
-
-static void sendOSC_connect(t_sendOSC *x, t_symbol *hostname,
- t_floatarg fportno)
-{
- int portno = fportno;
- /* create a socket */
-
- // make sure handle is available
- if(x->x_htmsocket == 0) {
- //
- x->x_htmsocket = OpenHTMSocket(hostname->s_name, portno);
- if (!x->x_htmsocket)
- post("Couldn't open socket: ");
- else {
- post("connected to port %s:%d (hSock=%d)", hostname->s_name, portno, x->x_htmsocket);
- outlet_float(x->x_obj.ob_outlet, 1);
- }
- }
- else
- perror("call to sendOSC_connect() against UNavailable socket handle");
-}
-
-void sendOSC_disconnect(t_sendOSC *x)
-{
- if (x->x_htmsocket)
- {
- post("disconnecting htmsock (hSock=%d)...", x->x_htmsocket);
- CloseHTMSocket(x->x_htmsocket);
- x->x_htmsocket = 0; // {{raf}} semi-quasi-semaphorize this
- outlet_float(x->x_obj.ob_outlet, 0);
- }
- else {
- perror("call to sendOSC_disconnect() against unused socket handle");
- }
-}
-
-void sendOSC_senduntyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
-{
- char* targv[MAXPDARG];
- char tmparg[MAXPDSTRING];
- char* tmp = tmparg;
- //char testarg[MAXPDSTRING];
- int c;
-
- post("sendOSC: use typetags 0/1 message and plain send method so send untypetagged...");
- return;
-
- //atom_string(argv,testarg, MAXPDSTRING);
- for (c=0;c<argc;c++) {
- atom_string(argv+c,tmp, 80);
- targv[c] = tmp;
- tmp += strlen(tmp)+1;
- }
-
- // this sock needs to be larger than 0, not >= ..
- if (x->x_htmsocket)
- {
- CommandLineMode(argc, targv, x->x_htmsocket);
- // post("test %d", c);
- }
- else {
- post("sendOSC: not connected");
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-// this is the real and only sending routine now, for both typed and
-// undtyped mode.
-
-static void sendOSC_sendtyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
-{
- char* targv[MAX_ARGS];
- char tmparg[MAXPDSTRING];
- char* tmp = tmparg;
- int c;
-
- char *messageName;
- char *token;
- typedArg args[MAX_ARGS];
- int i,j;
- int numArgs = 0;
-
- messageName = "";
-#ifdef DEBUG
- post ("sendOSC: messageName: %s", messageName);
-#endif
-
-
-
- for (c=0;c<argc;c++) {
- atom_string(argv+c,tmp, 80);
-
-#ifdef DEBUG
- // post ("sendOSC: %d, %s",c, tmp);
-#endif
-
- targv[c] = tmp;
- tmp += strlen(tmp)+1;
-
-#ifdef DEBUG
- // post ("sendOSC: %d, %s",c, targv[c]);
-#endif
- }
-
- // this sock needs to be larger than 0, not >= ..
- if (x->x_htmsocket > 0)
- {
-#ifdef DEBUG
- post ("sendOSC: type tags? %d", useTypeTags);
-#endif
-
- messageName = strtok(targv[0], ",");
- j = 1;
- for (i = j; i < argc; i++) {
- token = strtok(targv[i],",");
- args[i-j] = ParseToken(token);
-#ifdef DEBUG
- printf("cell-cont: %s\n", targv[i]);
- printf(" type-id: %d\n", args[i-j]);
-#endif
- numArgs = i;
- }
-
-
- if(WriteMessage(x->x_oscbuf, messageName, numArgs, args)) {
- post("sendOSC: usage error, write-msg failed: %s", OSC_errorMessage);
- return;
- }
-
- if(!x->x_bundle) {
- SendBuffer(x->x_htmsocket, x->x_oscbuf);
- OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
- }
-
- //CommandLineMode(argc, targv, x->x_htmsocket);
- //useTypeTags = 0;
- }
- else {
- post("sendOSC: not connected");
- }
-}
-
-void sendOSC_send(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
-{
- if(!argc) {
- post("not sending empty message.");
- return;
- }
- if(x->x_typetags) {
- useTypeTags = 1;
- sendOSC_sendtyped(x,s,argc,argv);
- useTypeTags = 0;
- } else {
- sendOSC_sendtyped(x,s,argc,argv);
- }
-}
-
-static void sendOSC_free(t_sendOSC *x)
-{
- sendOSC_disconnect(x);
-}
-
-#ifdef WIN32
- OSC_API void sendOSC_setup(void) {
-#else
- void sendOSC_setup(void) {
-#endif
- sendOSC_class = class_new(gensym("sendOSC"), (t_newmethod)sendOSC_new,
- (t_method)sendOSC_free,
- sizeof(t_sendOSC), 0, A_DEFFLOAT, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_connect,
- gensym("connect"), A_SYMBOL, A_FLOAT, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_disconnect,
- gensym("disconnect"), 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_settypetags,
- gensym("typetags"),
- A_FLOAT, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_send,
- gensym("send"),
- A_GIMME, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_send,
- gensym("senduntyped"),
- A_GIMME, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_send,
- gensym("sendtyped"),
- A_GIMME, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_openbundle,
- gensym("["),
- 0, 0);
- class_addmethod(sendOSC_class, (t_method)sendOSC_closebundle,
- gensym("]"),
- 0, 0);
- class_sethelpsymbol(sendOSC_class, gensym("sendOSC-help.pd"));
-}
-
-
-
-
-
-/* Exit status codes:
- 0: successful
- 2: Message(s) dropped because of buffer overflow
- 3: Socket error
- 4: Usage error
- 5: Internal error
-*/
-
-void CommandLineMode(int argc, char *argv[], void *htmsocket) {
- char *messageName;
- char *token;
- typedArg args[MAX_ARGS];
- int i,j, numArgs;
- OSCbuf buf[1];
-
- OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
-
- if (argc > 1) {
- post("argc (%d) > 1", argc);
- }
-
- // ParseInteractiveLine(buf, argv);
- messageName = strtok(argv[0], ",");
-
- j = 1;
- for (i = j; i < argc; i++) {
- token = strtok(argv[i],",");
- args[i-j] = ParseToken(token);
-#ifdef DEBUG
- printf("cell-cont: %s\n", argv[i]);
- printf(" type-id: %d\n", args[i-j]);
-#endif
- numArgs = i;
- }
-
- if(WriteMessage(buf, messageName, numArgs, args)) {
- post("sendOSC: usage error. write-msg failed: %s", OSC_errorMessage);
- return;
- }
-
- SendBuffer(htmsocket, buf);
-}
-
-#define MAXMESG 2048
-
-void InteractiveMode(void *htmsocket) {
- char mesg[MAXMESG];
- OSCbuf buf[1];
- int bundleDepth = 0; /* At first, we haven't seen "[". */
-
- OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
-
- while (fgets(mesg, MAXMESG, stdin) != NULL) {
- if (mesg[0] == '\n') {
- if (bundleDepth > 0) {
- /* Ignore blank lines inside a group. */
- } else {
- /* blank line => repeat previous send */
- SendBuffer(htmsocket, buf);
- }
- continue;
- }
-
- if (bundleDepth == 0) {
- OSC_resetBuffer(buf);
- }
-
- if (mesg[0] == '[') {
- OSCTimeTag tt = ParseTimeTag(mesg+1);
- if (OSC_openBundle(buf, tt)) {
- post("Problem opening bundle: %s\n", OSC_errorMessage);
- OSC_resetBuffer(buf);
- bundleDepth = 0;
- continue;
- }
- bundleDepth++;
- } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') {
- if (bundleDepth == 0) {
- post("Unexpected ']': not currently in a bundle.\n");
- } else {
- if (OSC_closeBundle(buf)) {
- post("Problem closing bundle: %s\n", OSC_errorMessage);
- OSC_resetBuffer(buf);
- bundleDepth = 0;
- continue;
- }
-
- bundleDepth--;
- if (bundleDepth == 0) {
- SendBuffer(htmsocket, buf);
- }
- }
- } else {
- ParseInteractiveLine(buf, mesg);
- if (bundleDepth != 0) {
- /* Don't send anything until we close all bundles */
- } else {
- SendBuffer(htmsocket, buf);
- }
- }
- }
-}
-
-OSCTimeTag ParseTimeTag(char *s) {
- char *p, *newline;
- typedArg arg;
-
- p = s;
- while (isspace(*p)) p++;
- if (*p == '\0') return OSCTT_Immediately();
-
- if (*p == '+') {
- /* Time tag is for some time in the future. It should be a
- number of seconds as an int or float */
-
- newline = strchr(s, '\n');
- if (newline != NULL) *newline = '\0';
-
- p++; /* Skip '+' */
- while (isspace(*p)) p++;
-
- arg = ParseToken(p);
- if (arg.type == STRING_osc) {
- post("warning: inscrutable time tag request: %s\n", s);
- return OSCTT_Immediately();
- } else if (arg.type == INT_osc) {
- return OSCTT_PlusSeconds(OSCTT_CurrentTime(),
- (float) arg.datum.i);
- } else if (arg.type == FLOAT_osc) {
- return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f);
- } else {
- error("This can't happen!");
- }
- }
-
- if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) {
- /* They specified the 8-byte tag in hex */
- OSCTimeTag tt;
- if (sscanf(p, "%llx", &tt) != 1) {
- post("warning: couldn't parse time tag %s\n", s);
- return OSCTT_Immediately();
- }
-#ifndef HAS8BYTEINT
- if (ntohl(1) != 1) {
- /* tt is a struct of seconds and fractional part,
- and this machine is little-endian, so sscanf
- wrote each half of the time tag in the wrong half
- of the struct. */
- int temp;
- temp = tt.seconds;
- tt.seconds = tt.fraction ;
- tt.fraction = temp;
- }
-#endif
- return tt;
- }
-
- post("warning: invalid time tag: %s\n", s);
- return OSCTT_Immediately();
-}
-
-
-void ParseInteractiveLine(OSCbuf *buf, char *mesg) {
- char *messageName, *token, *p;
- typedArg args[MAX_ARGS];
- int thisArg;
-
- p = mesg;
- while (isspace(*p)) p++;
- if (*p == '\0') return;
-
- messageName = p;
-
- if (strcmp(messageName, "play\n") == 0) {
- /* Special kludge feature to save typing */
- typedArg arg;
-
- if (OSC_openBundle(buf, OSCTT_Immediately())) {
- post("Problem opening bundle: %s\n", OSC_errorMessage);
- return;
- }
-
- arg.type = INT_osc;
- arg.datum.i = 0;
- WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg);
-
- arg.type = FLOAT_osc;
- arg.datum.i = 0.0f;
- WriteMessage(buf, "/voices/0/tm/goto", 1, &arg);
-
- if (OSC_closeBundle(buf)) {
- post("Problem closing bundle: %s\n", OSC_errorMessage);
- }
-
- return;
- }
-
- while (!isspace(*p) && *p != '\0') p++;
- if (isspace(*p)) {
- *p = '\0';
- p++;
- }
-
- thisArg = 0;
- while (*p != '\0') {
- /* flush leading whitespace */
- while (isspace(*p)) p++;
- if (*p == '\0') break;
-
- if (*p == '"') {
- /* A string argument: scan for close quotes */
- p++;
- args[thisArg].type = STRING_osc;
- args[thisArg].datum.s = p;
-
- while (*p != '"') {
- if (*p == '\0') {
- post("Unterminated quote mark: ignoring line\n");
- return;
- }
- p++;
- }
- *p = '\0';
- p++;
- } else {
- token = p;
- while (!isspace(*p) && (*p != '\0')) p++;
- if (isspace(*p)) {
- *p = '\0';
- p++;
- }
- args[thisArg] = ParseToken(token);
- }
- thisArg++;
- if (thisArg >= MAX_ARGS) {
- post("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n",
- MAX_ARGS);
- break;
- }
- }
-
- if (WriteMessage(buf, messageName, thisArg, args) != 0) {
- post("Problem sending message: %s\n", OSC_errorMessage);
- }
-}
-
-typedArg ParseToken(char *token) {
- char *p = token;
- typedArg returnVal;
-
- /* It might be an int, a float, or a string */
-
- if (*p == '-') p++;
-
- if (isdigit(*p) || *p == '.') {
- while (isdigit(*p)) p++;
- if (*p == '\0') {
- returnVal.type = INT_osc;
- returnVal.datum.i = atoi(token);
- return returnVal;
- }
- if (*p == '.') {
- p++;
- while (isdigit(*p)) p++;
- if (*p == '\0') {
- returnVal.type = FLOAT_osc;
- returnVal.datum.f = atof(token);
- return returnVal;
- }
- }
- }
-
- returnVal.type = STRING_osc;
- returnVal.datum.s = token;
- return returnVal;
-}
-
-int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) {
- int j, returnVal;
- const int wmERROR = -1;
-
- returnVal = 0;
-
-#ifdef DEBUG
- printf("WriteMessage: %s ", messageName);
-
- for (j = 0; j < numArgs; j++) {
- switch (args[j].type) {
- case INT_osc:
- printf("%d ", args[j].datum.i);
- break;
-
- case FLOAT_osc:
- printf("%f ", args[j].datum.f);
- break;
-
- case STRING_osc:
- printf("%s ", args[j].datum.s);
- break;
-
- default:
- error("Unrecognized arg type, (not exiting)");
- return(wmERROR);
- }
- }
- printf("\n");
-#endif
-
- if (!useTypeTags) {
- returnVal = OSC_writeAddress(buf, messageName);
- if (returnVal) {
- post("Problem writing address: %s\n", OSC_errorMessage);
- }
- } else {
- /* First figure out the type tags */
- char typeTags[MAX_ARGS+2];
- int i;
-
- typeTags[0] = ',';
-
- for (i = 0; i < numArgs; ++i) {
- switch (args[i].type) {
- case INT_osc:
- typeTags[i+1] = 'i';
- break;
-
- case FLOAT_osc:
- typeTags[i+1] = 'f';
- break;
-
- case STRING_osc:
- typeTags[i+1] = 's';
- break;
-
- default:
- error("Unrecognized arg type (not exiting)");
- return(wmERROR);
- }
- }
- typeTags[i+1] = '\0';
-
- returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags);
- if (returnVal) {
- post("Problem writing address: %s\n", OSC_errorMessage);
- }
- }
-
- for (j = 0; j < numArgs; j++) {
- switch (args[j].type) {
- case INT_osc:
- if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) {
- return returnVal;
- }
- break;
-
- case FLOAT_osc:
- if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) {
- return returnVal;
- }
- break;
-
- case STRING_osc:
- if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) {
- return returnVal;
- }
- break;
-
- default:
- error("Unrecognized arg type (not exiting)");
- returnVal = wmERROR;
- }
- }
- return returnVal;
-}
-
-void SendBuffer(void *htmsocket, OSCbuf *buf) {
-#ifdef DEBUG
- printf("Sending buffer...\n");
-#endif
- if (OSC_isBufferEmpty(buf)) {
- post("SendBuffer() called but buffer empty");
- return;
- }
- if (!OSC_isBufferDone(buf)) {
- error("SendBuffer() called but buffer not ready!, not exiting");
- return; //{{raf}}
- }
- SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf));
-}
-
-void SendData(void *htmsocket, int size, char *data) {
- if (!SendHTMSocket(htmsocket, size, data)) {
- post("SendData::SendHTMSocket()failure -- not connected");
- CloseHTMSocket(htmsocket);
- }
-}
-
-
-
-/* ----------------------
- OSC-client code
-
- */
-
-/* Here are the possible values of the state field: */
-
-#define EMPTY 0 /* Nothing written to packet yet */
-#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
-#define NEED_COUNT 2 /* Just opened a bundle; must write message name or
- open another bundle */
-#define GET_ARGS 3 /* Getting arguments to a message. If we see a message
- name or a bundle open/close then the current message
- will end. */
-#define DONE 4 /* All open bundles have been closed, so can't write
- anything else */
-
-#ifdef WIN32
- #include <winsock2.h>
- #include <io.h>
- #include <stdio.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-#endif
-
-#ifdef __APPLE__
- #include <sys/types.h>
-#endif
-
-#ifdef unix
- #include <netinet/in.h>
- #include <stdio.h>
-#endif
-
-
-char *OSC_errorMessage;
-
-static int OSC_padString(char *dest, char *str);
-static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
-static int OSC_WritePadding(char *dest, int i);
-static int CheckTypeTag(OSCbuf *buf, char expectedType);
-
-void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
- buf->buffer = byteArray;
- buf->size = size;
- OSC_resetBuffer(buf);
-}
-
-void OSC_resetBuffer(OSCbuf *buf) {
- buf->bufptr = buf->buffer;
- buf->state = EMPTY;
- buf->bundleDepth = 0;
- buf->prevCounts[0] = 0;
- buf->gettingFirstUntypedArg = 0;
- buf->typeStringPtr = 0;
-}
-
-int OSC_isBufferEmpty(OSCbuf *buf) {
- return buf->bufptr == buf->buffer;
-}
-
-int OSC_freeSpaceInBuffer(OSCbuf *buf) {
- return buf->size - (buf->bufptr - buf->buffer);
-}
-
-int OSC_isBufferDone(OSCbuf *buf) {
- return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
-}
-
-char *OSC_getPacket(OSCbuf *buf) {
-#ifdef ERROR_CHECK_GETPACKET
- if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
- return buf->buffer;
- } else {
- OSC_errorMessage = "Packet has unterminated bundles";
- return 0;
- }
-#else
- return buf->buffer;
-#endif
-}
-
-int OSC_packetSize(OSCbuf *buf) {
-#ifdef ERROR_CHECK_PACKETSIZE
- if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
- return (buf->bufptr - buf->buffer);
- } else {
- OSC_errorMessage = "Packet has unterminated bundles";
- return 0;
- }
-#else
- return (buf->bufptr - buf->buffer);
-#endif
-}
-
-#define CheckOverflow(buf, bytesNeeded) { if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) {OSC_errorMessage = "buffer overflow"; return 1;}}
-
-static void PatchMessageSize(OSCbuf *buf) {
- int4byte size;
- size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
- *(buf->thisMsgSize) = htonl(size);
-}
-
-int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
- if (buf->state == ONE_MSG_ARGS) {
- OSC_errorMessage = "Can't open a bundle in a one-message packet";
- return 3;
- }
-
- if (buf->state == DONE) {
- OSC_errorMessage = "This packet is finished; can't open a new bundle";
- return 4;
- }
-
- if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
- OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
- return 2;
- }
-
- if (CheckTypeTag(buf, '\0')) return 9;
-
- if (buf->state == GET_ARGS) {
- PatchMessageSize(buf);
- }
-
- if (buf->state == EMPTY) {
- /* Need 16 bytes for "#bundle" and time tag */
- CheckOverflow(buf, 16);
- } else {
- /* This bundle is inside another bundle, so we need to leave
- a blank size count for the size of this current bundle. */
- CheckOverflow(buf, 20);
- *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
- buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
-
- buf->bufptr += 4;
- }
-
- buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
-
-
- *((OSCTimeTag *) buf->bufptr) = tt;
-
- if (htonl(1) != 1) {
- /* Byte swap the 8-byte integer time tag */
- int4byte *intp = (int4byte *)buf->bufptr;
- intp[0] = htonl(intp[0]);
- intp[1] = htonl(intp[1]);
-
-#ifdef HAS8BYTEINT
- { /* tt is a 64-bit int so we have to swap the two 32-bit words.
- (Otherwise tt is a struct of two 32-bit words, and even though
- each word was wrong-endian, they were in the right order
- in the struct.) */
- int4byte temp = intp[0];
- intp[0] = intp[1];
- intp[1] = temp;
- }
-#endif
- }
-
- buf->bufptr += sizeof(OSCTimeTag);
-
- buf->state = NEED_COUNT;
-
- buf->gettingFirstUntypedArg = 0;
- buf->typeStringPtr = 0;
- return 0;
-}
-
-
-int OSC_closeBundle(OSCbuf *buf) {
- if (buf->bundleDepth == 0) {
- /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
- OSC_errorMessage = "Can't close bundle; no bundle is open!";
- return 5;
- }
-
- if (CheckTypeTag(buf, '\0')) return 9;
-
- if (buf->state == GET_ARGS) {
- PatchMessageSize(buf);
- }
-
- if (buf->bundleDepth == 1) {
- /* Closing the last bundle: No bundle size to patch */
- buf->state = DONE;
- } else {
- /* Closing a sub-bundle: patch bundle size */
- int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
- *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
- buf->state = NEED_COUNT;
- }
-
- --buf->bundleDepth;
- buf->gettingFirstUntypedArg = 0;
- buf->typeStringPtr = 0;
- return 0;
-}
-
-
-int OSC_closeAllBundles(OSCbuf *buf) {
- if (buf->bundleDepth == 0) {
- /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
- OSC_errorMessage = "Can't close all bundles; no bundle is open!";
- return 6;
- }
-
- if (CheckTypeTag(buf, '\0')) return 9;
-
- while (buf->bundleDepth > 0) {
- OSC_closeBundle(buf);
- }
- buf->typeStringPtr = 0;
- return 0;
-}
-
-int OSC_writeAddress(OSCbuf *buf, char *name) {
- int4byte paddedLength;
-
- if (buf->state == ONE_MSG_ARGS) {
- OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
- return 7;
- }
-
- if (buf->state == DONE) {
- OSC_errorMessage = "This packet is finished; can't write another address";
- return 8;
- }
-
- if (CheckTypeTag(buf, '\0')) return 9;
-
- paddedLength = OSC_effectiveStringLength(name);
-
- if (buf->state == EMPTY) {
- /* This will be a one-message packet, so no sizes to worry about */
- CheckOverflow(buf, paddedLength);
- buf->state = ONE_MSG_ARGS;
- } else {
- /* GET_ARGS or NEED_COUNT */
- CheckOverflow(buf, 4+paddedLength);
- if (buf->state == GET_ARGS) {
- /* Close the old message */
- PatchMessageSize(buf);
- }
- buf->thisMsgSize = (int4byte *)buf->bufptr;
- *(buf->thisMsgSize) = 0xbbbbbbbb;
- buf->bufptr += 4;
- buf->state = GET_ARGS;
- }
-
- /* Now write the name */
- buf->bufptr += OSC_padString(buf->bufptr, name);
- buf->typeStringPtr = 0;
- buf->gettingFirstUntypedArg = 1;
-
- return 0;
-}
-
-int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) {
- int result;
- int4byte paddedLength;
-
- if (CheckTypeTag(buf, '\0')) return 9;
-
- result = OSC_writeAddress(buf, name);
-
- if (result) return result;
-
- paddedLength = OSC_effectiveStringLength(types);
-
- CheckOverflow(buf, paddedLength);
-
- buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
- buf->bufptr += OSC_padString(buf->bufptr, types);
-
- buf->gettingFirstUntypedArg = 0;
- return 0;
-}
-
-static int CheckTypeTag(OSCbuf *buf, char expectedType) {
- if (buf->typeStringPtr) {
- if (*(buf->typeStringPtr) != expectedType) {
- if (expectedType == '\0') {
- OSC_errorMessage =
- "According to the type tag I expected more arguments.";
- } else if (*(buf->typeStringPtr) == '\0') {
- OSC_errorMessage =
- "According to the type tag I didn't expect any more arguments.";
- } else {
- OSC_errorMessage =
- "According to the type tag I expected an argument of a different type.";
- printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
- }
- return 9;
- }
- ++(buf->typeStringPtr);
- }
- return 0;
-}
-
-
-int OSC_writeFloatArg(OSCbuf *buf, float arg) {
- int4byte *intp;
- //int result;
-
- CheckOverflow(buf, 4);
-
- if (CheckTypeTag(buf, 'f')) return 9;
-
- /* Pretend arg is a long int so we can use htonl() */
- intp = ((int4byte *) &arg);
- *((int4byte *) buf->bufptr) = htonl(*intp);
-
- buf->bufptr += 4;
-
- buf->gettingFirstUntypedArg = 0;
- return 0;
-}
-
-
-
-int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
- int i;
- int4byte *intp;
-
- CheckOverflow(buf, 4 * numFloats);
-
- /* Pretend args are long ints so we can use htonl() */
- intp = ((int4byte *) args);
-
- for (i = 0; i < numFloats; i++) {
- if (CheckTypeTag(buf, 'f')) return 9;
- *((int4byte *) buf->bufptr) = htonl(intp[i]);
- buf->bufptr += 4;
- }
-
- buf->gettingFirstUntypedArg = 0;
- return 0;
-}
-
-int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
- CheckOverflow(buf, 4);
- if (CheckTypeTag(buf, 'i')) return 9;
-
- *((int4byte *) buf->bufptr) = htonl(arg);
- buf->bufptr += 4;
-
- buf->gettingFirstUntypedArg = 0;
- return 0;
-}
-
-int OSC_writeStringArg(OSCbuf *buf, char *arg) {
- int len;
-
- if (CheckTypeTag(buf, 's')) return 9;
-
- len = OSC_effectiveStringLength(arg);
-
- if (buf->gettingFirstUntypedArg && arg[0] == ',') {
- /* This un-type-tagged message starts with a string
- that starts with a comma, so we have to escape it
- (with a double comma) so it won't look like a type
- tag string. */
-
- CheckOverflow(buf, len+4); /* Too conservative */
- buf->bufptr +=
- OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
-
- } else {
- CheckOverflow(buf, len);
- buf->bufptr += OSC_padString(buf->bufptr, arg);
- }
-
- buf->gettingFirstUntypedArg = 0;
- return 0;
-
-}
-
-/* String utilities */
-
-#define STRING_ALIGN_PAD 4
-int OSC_effectiveStringLength(char *string) {
- int len = strlen(string) + 1; /* We need space for the null char. */
-
- /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
- if ((len % STRING_ALIGN_PAD) != 0) {
- len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
- }
- return len;
-}
-
-static int OSC_padString(char *dest, char *str) {
- int i;
-
- for (i = 0; str[i] != '\0'; i++) {
- dest[i] = str[i];
- }
-
- return OSC_WritePadding(dest, i);
-}
-
-static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) {
- int i;
-
- dest[0] = ',';
- for (i = 0; str[i] != '\0'; i++) {
- dest[i+1] = str[i];
- }
-
- return OSC_WritePadding(dest, i+1);
-}
-
-static int OSC_WritePadding(char *dest, int i) {
- dest[i] = '\0';
- i++;
-
- for (; (i % STRING_ALIGN_PAD) != 0; i++) {
- dest[i] = '\0';
- }
-
- return i;
-}
-
+/* +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03 +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 +*/ + + +/* sendOSC.c + + Matt Wright, 6/3/97 + based on sendOSC.c, which was based on a version by Adrian Freed + + Text-based OpenSoundControl client. User can enter messages via command + line arguments or standard input. + + Version 0.1: "play" feature + Version 0.2: Message type tags. + + pd version branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/sendOSC/sendOSC.c + ------------- + -- added bundle stuff to send. jdl 20020416 + -- tweaks for Win32 www.zeggz.com/raf 13-April-2002 + -- ost_at_test.at + i22_at_test.at, 2000-2002 + modified to compile as pd externel +*/ + +#define MAX_ARGS 2000 +#define SC_BUFFER_SIZE 64000 + +#include "m_pd.h" +#include "OSC-client.h" + +#include <string.h> +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> + +#ifdef WIN32 +#include <winsock2.h> +#include <io.h> +#include <errno.h> +#include <fcntl.h> +#include <winsock2.h> +#include <ctype.h> +#include <signal.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <rpc/rpc.h> +#include <sys/times.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <netdb.h> +#endif + +#ifdef __APPLE__ + #include <string.h> +#endif + +#define UNIXDG_PATH "/tmp/htm" +#define UNIXDG_TMP "/tmp/htm.XXXXXX" + + + +OSCTimeTag OSCTT_Immediately(void) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + + +OSCTimeTag OSCTT_CurrentTime(void) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + + +typedef int bool; + +typedef struct +{ + float srate; + + struct sockaddr_in serv_addr; /* udp socket */ + #ifndef WIN32 + struct sockaddr_un userv_addr; /* UNIX socket */ + #endif + int sockfd; /* socket file descriptor */ + int index, len,uservlen; + void *addr; + int id; +} desc; + + +/* open a socket for HTM communication to given host on given portnumber */ +/* if host is 0 then UNIX protocol is used (i.e. local communication */ +void *OpenHTMSocket(char *host, int portnumber) +{ + struct sockaddr_in cl_addr; + #ifndef WIN32 + int sockfd; + struct sockaddr_un ucl_addr; + #else + unsigned int sockfd; + #endif + + desc *o; + int oval = 1; + o = malloc(sizeof(*o)); + if(!o) return 0; + + #ifndef WIN32 + + if(!host) + { + char *mktemp(char *); + int clilen; + o->len = sizeof(ucl_addr); + /* + * Fill in the structure "userv_addr" with the address of the + * server that we want to send to. + */ + + bzero((char *) &o->userv_addr, sizeof(o->userv_addr)); + o->userv_addr.sun_family = AF_UNIX; + strcpy(o->userv_addr.sun_path, UNIXDG_PATH); + sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber); + o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path); + o->addr = &(o->userv_addr); + /* + * Open a socket (a UNIX domain datagram socket). + */ + + if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0) + { + /* + * Bind a local address for us. + * In the UNIX domain we have to choose our own name (that + * should be unique). We'll use mktemp() to create a unique + * pathname, based on our process id. + */ + + bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */ + ucl_addr.sun_family = AF_UNIX; + strcpy(ucl_addr.sun_path, UNIXDG_TMP); + + mktemp(ucl_addr.sun_path); + clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path); + + if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0) + { + perror("client: can't bind local address"); + close(sockfd); + sockfd = -1; + } + } + else + perror("unable to make socket\n"); + + }else + + #endif + + { + /* + * Fill in the structure "serv_addr" with the address of the + * server that we want to send to. + */ + o->len = sizeof(cl_addr); + + #ifdef WIN32 + ZeroMemory((char *)&o->serv_addr, sizeof(o->serv_addr)); + #else + bzero((char *)&o->serv_addr, sizeof(o->serv_addr)); + #endif + + o->serv_addr.sin_family = AF_INET; + + /* MW 6/6/96: Call gethostbyname() instead of inet_addr(), + so that host can be either an Internet host name (e.g., + "les") or an Internet address in standard dot notation + (e.g., "128.32.122.13") */ + { + struct hostent *hostsEntry; + unsigned long address; + + hostsEntry = gethostbyname(host); + if (hostsEntry == NULL) { + fprintf(stderr, "Couldn't decipher host name \"%s\"\n", host); + #ifndef WIN32 + herror(NULL); + #endif + return 0; + } + address = *((unsigned long *) hostsEntry->h_addr_list[0]); + o->serv_addr.sin_addr.s_addr = address; + } + + /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */ + + /* End MW changes */ + + /* + * Open a socket (a UDP domain datagram socket). + */ + + + #ifdef WIN32 + o->serv_addr.sin_port = htons((USHORT)portnumber); + o->addr = &(o->serv_addr); + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) { + ZeroMemory((char *)&cl_addr, sizeof(cl_addr)); + cl_addr.sin_family = AF_INET; + cl_addr.sin_addr.s_addr = htonl(INADDR_ANY); + cl_addr.sin_port = htons(0); + + // enable broadcast: jdl ~2003 + if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) { + perror("setsockopt"); + } + + if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) { + perror("could not bind\n"); + closesocket(sockfd); + sockfd = -1; + } + } + else { perror("unable to make socket\n");} + #else + o->serv_addr.sin_port = htons(portnumber); + o->addr = &(o->serv_addr); + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { + bzero((char *)&cl_addr, sizeof(cl_addr)); + cl_addr.sin_family = AF_INET; + cl_addr.sin_addr.s_addr = htonl(INADDR_ANY); + cl_addr.sin_port = htons(0); + + // enable broadcast: jdl ~2003 + if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) { + perror("setsockopt"); + } + + if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) { + perror("could not bind\n"); + close(sockfd); + sockfd = -1; + } + } + else { perror("unable to make socket\n");} + #endif + } + #ifdef WIN32 + if(sockfd == INVALID_SOCKET) { + #else + if(sockfd < 0) { + #endif + free(o); + o = 0; + } + else + o->sockfd = sockfd; + return o; +} + +static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b) +{ + int rcount; + if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count) + { + printf("sockfd %d count %d rcount %dlength %d\n", sockfd,count,rcount,length); + return FALSE; + } + return TRUE; +} + +bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer) +{ + desc *o = (desc *)htmsendhandle; + return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer); +} +void CloseHTMSocket(void *htmsendhandle) +{ + desc *o = (desc *)htmsendhandle; + #ifdef WIN32 + if(SOCKET_ERROR == closesocket(o->sockfd)) { + perror("CloseHTMSocket::closesocket failed\n"); + return; + } + #else + if(close(o->sockfd) == -1) + { + perror("CloseHTMSocket::closesocket failed"); + return; + } + #endif + + free(o); +} + + +/////////////////////// +// from sendOSC + +typedef struct { + //enum {INT, FLOAT, STRING} type; + enum {INT_osc, FLOAT_osc, STRING_osc} type; + union { + int i; + float f; + char *s; + } datum; +} typedArg; + +void CommandLineMode(int argc, char *argv[], void *htmsocket); +OSCTimeTag ParseTimeTag(char *s); +void ParseInteractiveLine(OSCbuf *buf, char *mesg); +typedArg ParseToken(char *token); +int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args); +void SendBuffer(void *htmsocket, OSCbuf *buf); +void SendData(void *htmsocket, int size, char *data); +/* defined in OSC-system-dependent.c now */ + +//static void *htmsocket; +static int exitStatus = 0; +static int useTypeTags = 0; + +static char bufferForOSCbuf[SC_BUFFER_SIZE]; + + +///////// +// end from sendOSC + +static t_class *sendOSC_class; + +typedef struct _sendOSC +{ + t_object x_obj; + int x_protocol; // UDP/TCP (udp only atm) + t_int x_typetags; // typetag flag + void *x_htmsocket; // sending socket + int x_bundle; // bundle open flag + OSCbuf x_oscbuf[1]; // OSCbuffer + t_outlet *x_bdpthout;// bundle-depth floatoutlet +} t_sendOSC; + +static void *sendOSC_new(t_floatarg udpflag) +{ + t_sendOSC *x = (t_sendOSC *)pd_new(sendOSC_class); + outlet_new(&x->x_obj, &s_float); + x->x_htmsocket = 0; // {{raf}} + // set udp + x->x_protocol = SOCK_STREAM; + // set typetags to 1 by default + x->x_typetags = 1; + // bunlde is closed + x->x_bundle = 0; + OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf); + x->x_bdpthout = outlet_new(&x->x_obj, 0); // outlet_float(); + //x->x_oscbuf = + return (x); +} + + +void sendOSC_openbundle(t_sendOSC *x) +{ + if (x->x_oscbuf->bundleDepth + 1 >= MAX_BUNDLE_NESTING || + OSC_openBundle(x->x_oscbuf, OSCTT_Immediately())) + { + post("Problem opening bundle: %s\n", OSC_errorMessage); + return; + } + x->x_bundle = 1; + outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth); +} + +static void sendOSC_closebundle(t_sendOSC *x) +{ + if (OSC_closeBundle(x->x_oscbuf)) { + post("Problem closing bundle: %s\n", OSC_errorMessage); + return; + } + outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth); + // in bundle mode we send when bundle is closed? + if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) { + // post("x_oscbuf: something inside me?"); + if (x->x_htmsocket) { + SendBuffer(x->x_htmsocket, x->x_oscbuf); + } else { + post("sendOSC: not connected"); + } + OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf); + x->x_bundle = 0; + return; + } + // post("x_oscbuf: something went wrong"); +} + +static void sendOSC_settypetags(t_sendOSC *x, t_float *f) + { + x->x_typetags = (int)f; + post("sendOSC.c: setting typetags %d",x->x_typetags); + } + + +static void sendOSC_connect(t_sendOSC *x, t_symbol *hostname, + t_floatarg fportno) +{ + int portno = fportno; + /* create a socket */ + + // make sure handle is available + if(x->x_htmsocket == 0) { + // + x->x_htmsocket = OpenHTMSocket(hostname->s_name, portno); + if (!x->x_htmsocket) + post("Couldn't open socket: "); + else { + post("connected to port %s:%d (hSock=%d)", hostname->s_name, portno, x->x_htmsocket); + outlet_float(x->x_obj.ob_outlet, 1); + } + } + else + perror("call to sendOSC_connect() against UNavailable socket handle"); +} + +void sendOSC_disconnect(t_sendOSC *x) +{ + if (x->x_htmsocket) + { + post("disconnecting htmsock (hSock=%d)...", x->x_htmsocket); + CloseHTMSocket(x->x_htmsocket); + x->x_htmsocket = 0; // {{raf}} semi-quasi-semaphorize this + outlet_float(x->x_obj.ob_outlet, 0); + } + else { + perror("call to sendOSC_disconnect() against unused socket handle"); + } +} + +void sendOSC_senduntyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv) +{ + char* targv[MAXPDARG]; + char tmparg[MAXPDSTRING]; + char* tmp = tmparg; + //char testarg[MAXPDSTRING]; + int c; + + post("sendOSC: use typetags 0/1 message and plain send method so send untypetagged..."); + return; + + //atom_string(argv,testarg, MAXPDSTRING); + for (c=0;c<argc;c++) { + atom_string(argv+c,tmp, 80); + targv[c] = tmp; + tmp += strlen(tmp)+1; + } + + // this sock needs to be larger than 0, not >= .. + if (x->x_htmsocket) + { + CommandLineMode(argc, targv, x->x_htmsocket); + // post("test %d", c); + } + else { + post("sendOSC: not connected"); + } +} + +////////////////////////////////////////////////////////////////////// +// this is the real and only sending routine now, for both typed and +// undtyped mode. + +static void sendOSC_sendtyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv) +{ + char* targv[MAX_ARGS]; + char tmparg[MAXPDSTRING]; + char* tmp = tmparg; + int c; + + char *messageName; + char *token; + typedArg args[MAX_ARGS]; + int i,j; + int numArgs = 0; + + messageName = ""; +#ifdef DEBUG + post ("sendOSC: messageName: %s", messageName); +#endif + + + + for (c=0;c<argc;c++) { + atom_string(argv+c,tmp, 80); + +#ifdef DEBUG + // post ("sendOSC: %d, %s",c, tmp); +#endif + + targv[c] = tmp; + tmp += strlen(tmp)+1; + +#ifdef DEBUG + // post ("sendOSC: %d, %s",c, targv[c]); +#endif + } + + // this sock needs to be larger than 0, not >= .. + if (x->x_htmsocket > 0) + { +#ifdef DEBUG + post ("sendOSC: type tags? %d", useTypeTags); +#endif + + messageName = strtok(targv[0], ","); + j = 1; + for (i = j; i < argc; i++) { + token = strtok(targv[i],","); + args[i-j] = ParseToken(token); +#ifdef DEBUG + printf("cell-cont: %s\n", targv[i]); + printf(" type-id: %d\n", args[i-j]); +#endif + numArgs = i; + } + + + if(WriteMessage(x->x_oscbuf, messageName, numArgs, args)) { + post("sendOSC: usage error, write-msg failed: %s", OSC_errorMessage); + return; + } + + if(!x->x_bundle) { + SendBuffer(x->x_htmsocket, x->x_oscbuf); + OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf); + } + + //CommandLineMode(argc, targv, x->x_htmsocket); + //useTypeTags = 0; + } + else { + post("sendOSC: not connected"); + } +} + +void sendOSC_send(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv) +{ + if(!argc) { + post("not sending empty message."); + return; + } + if(x->x_typetags) { + useTypeTags = 1; + sendOSC_sendtyped(x,s,argc,argv); + useTypeTags = 0; + } else { + sendOSC_sendtyped(x,s,argc,argv); + } +} + +static void sendOSC_free(t_sendOSC *x) +{ + sendOSC_disconnect(x); +} + +#ifdef WIN32 + OSC_API void sendOSC_setup(void) { +#else + void sendOSC_setup(void) { +#endif + sendOSC_class = class_new(gensym("sendOSC"), (t_newmethod)sendOSC_new, + (t_method)sendOSC_free, + sizeof(t_sendOSC), 0, A_DEFFLOAT, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_connect, + gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_disconnect, + gensym("disconnect"), 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_settypetags, + gensym("typetags"), + A_FLOAT, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_send, + gensym("send"), + A_GIMME, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_send, + gensym("senduntyped"), + A_GIMME, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_send, + gensym("sendtyped"), + A_GIMME, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_openbundle, + gensym("["), + 0, 0); + class_addmethod(sendOSC_class, (t_method)sendOSC_closebundle, + gensym("]"), + 0, 0); + class_sethelpsymbol(sendOSC_class, gensym("sendOSC-help.pd")); +} + + + + + +/* Exit status codes: + 0: successful + 2: Message(s) dropped because of buffer overflow + 3: Socket error + 4: Usage error + 5: Internal error +*/ + +void CommandLineMode(int argc, char *argv[], void *htmsocket) { + char *messageName; + char *token; + typedArg args[MAX_ARGS]; + int i,j, numArgs; + OSCbuf buf[1]; + + OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); + + if (argc > 1) { + post("argc (%d) > 1", argc); + } + + // ParseInteractiveLine(buf, argv); + messageName = strtok(argv[0], ","); + + j = 1; + for (i = j; i < argc; i++) { + token = strtok(argv[i],","); + args[i-j] = ParseToken(token); +#ifdef DEBUG + printf("cell-cont: %s\n", argv[i]); + printf(" type-id: %d\n", args[i-j]); +#endif + numArgs = i; + } + + if(WriteMessage(buf, messageName, numArgs, args)) { + post("sendOSC: usage error. write-msg failed: %s", OSC_errorMessage); + return; + } + + SendBuffer(htmsocket, buf); +} + +#define MAXMESG 2048 + +void InteractiveMode(void *htmsocket) { + char mesg[MAXMESG]; + OSCbuf buf[1]; + int bundleDepth = 0; /* At first, we haven't seen "[". */ + + OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); + + while (fgets(mesg, MAXMESG, stdin) != NULL) { + if (mesg[0] == '\n') { + if (bundleDepth > 0) { + /* Ignore blank lines inside a group. */ + } else { + /* blank line => repeat previous send */ + SendBuffer(htmsocket, buf); + } + continue; + } + + if (bundleDepth == 0) { + OSC_resetBuffer(buf); + } + + if (mesg[0] == '[') { + OSCTimeTag tt = ParseTimeTag(mesg+1); + if (OSC_openBundle(buf, tt)) { + post("Problem opening bundle: %s\n", OSC_errorMessage); + OSC_resetBuffer(buf); + bundleDepth = 0; + continue; + } + bundleDepth++; + } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') { + if (bundleDepth == 0) { + post("Unexpected ']': not currently in a bundle.\n"); + } else { + if (OSC_closeBundle(buf)) { + post("Problem closing bundle: %s\n", OSC_errorMessage); + OSC_resetBuffer(buf); + bundleDepth = 0; + continue; + } + + bundleDepth--; + if (bundleDepth == 0) { + SendBuffer(htmsocket, buf); + } + } + } else { + ParseInteractiveLine(buf, mesg); + if (bundleDepth != 0) { + /* Don't send anything until we close all bundles */ + } else { + SendBuffer(htmsocket, buf); + } + } + } +} + +OSCTimeTag ParseTimeTag(char *s) { + char *p, *newline; + typedArg arg; + + p = s; + while (isspace(*p)) p++; + if (*p == '\0') return OSCTT_Immediately(); + + if (*p == '+') { + /* Time tag is for some time in the future. It should be a + number of seconds as an int or float */ + + newline = strchr(s, '\n'); + if (newline != NULL) *newline = '\0'; + + p++; /* Skip '+' */ + while (isspace(*p)) p++; + + arg = ParseToken(p); + if (arg.type == STRING_osc) { + post("warning: inscrutable time tag request: %s\n", s); + return OSCTT_Immediately(); + } else if (arg.type == INT_osc) { + return OSCTT_PlusSeconds(OSCTT_CurrentTime(), + (float) arg.datum.i); + } else if (arg.type == FLOAT_osc) { + return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f); + } else { + error("This can't happen!"); + } + } + + if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) { + /* They specified the 8-byte tag in hex */ + OSCTimeTag tt; + if (sscanf(p, "%llx", &tt) != 1) { + post("warning: couldn't parse time tag %s\n", s); + return OSCTT_Immediately(); + } +#ifndef HAS8BYTEINT + if (ntohl(1) != 1) { + /* tt is a struct of seconds and fractional part, + and this machine is little-endian, so sscanf + wrote each half of the time tag in the wrong half + of the struct. */ + int temp; + temp = tt.seconds; + tt.seconds = tt.fraction ; + tt.fraction = temp; + } +#endif + return tt; + } + + post("warning: invalid time tag: %s\n", s); + return OSCTT_Immediately(); +} + + +void ParseInteractiveLine(OSCbuf *buf, char *mesg) { + char *messageName, *token, *p; + typedArg args[MAX_ARGS]; + int thisArg; + + p = mesg; + while (isspace(*p)) p++; + if (*p == '\0') return; + + messageName = p; + + if (strcmp(messageName, "play\n") == 0) { + /* Special kludge feature to save typing */ + typedArg arg; + + if (OSC_openBundle(buf, OSCTT_Immediately())) { + post("Problem opening bundle: %s\n", OSC_errorMessage); + return; + } + + arg.type = INT_osc; + arg.datum.i = 0; + WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg); + + arg.type = FLOAT_osc; + arg.datum.i = 0.0f; + WriteMessage(buf, "/voices/0/tm/goto", 1, &arg); + + if (OSC_closeBundle(buf)) { + post("Problem closing bundle: %s\n", OSC_errorMessage); + } + + return; + } + + while (!isspace(*p) && *p != '\0') p++; + if (isspace(*p)) { + *p = '\0'; + p++; + } + + thisArg = 0; + while (*p != '\0') { + /* flush leading whitespace */ + while (isspace(*p)) p++; + if (*p == '\0') break; + + if (*p == '"') { + /* A string argument: scan for close quotes */ + p++; + args[thisArg].type = STRING_osc; + args[thisArg].datum.s = p; + + while (*p != '"') { + if (*p == '\0') { + post("Unterminated quote mark: ignoring line\n"); + return; + } + p++; + } + *p = '\0'; + p++; + } else { + token = p; + while (!isspace(*p) && (*p != '\0')) p++; + if (isspace(*p)) { + *p = '\0'; + p++; + } + args[thisArg] = ParseToken(token); + } + thisArg++; + if (thisArg >= MAX_ARGS) { + post("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n", + MAX_ARGS); + break; + } + } + + if (WriteMessage(buf, messageName, thisArg, args) != 0) { + post("Problem sending message: %s\n", OSC_errorMessage); + } +} + +typedArg ParseToken(char *token) { + char *p = token; + typedArg returnVal; + + /* It might be an int, a float, or a string */ + + if (*p == '-') p++; + + if (isdigit(*p) || *p == '.') { + while (isdigit(*p)) p++; + if (*p == '\0') { + returnVal.type = INT_osc; + returnVal.datum.i = atoi(token); + return returnVal; + } + if (*p == '.') { + p++; + while (isdigit(*p)) p++; + if (*p == '\0') { + returnVal.type = FLOAT_osc; + returnVal.datum.f = atof(token); + return returnVal; + } + } + } + + returnVal.type = STRING_osc; + returnVal.datum.s = token; + return returnVal; +} + +int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) { + int j, returnVal; + const int wmERROR = -1; + + returnVal = 0; + +#ifdef DEBUG + printf("WriteMessage: %s ", messageName); + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT_osc: + printf("%d ", args[j].datum.i); + break; + + case FLOAT_osc: + printf("%f ", args[j].datum.f); + break; + + case STRING_osc: + printf("%s ", args[j].datum.s); + break; + + default: + error("Unrecognized arg type, (not exiting)"); + return(wmERROR); + } + } + printf("\n"); +#endif + + if (!useTypeTags) { + returnVal = OSC_writeAddress(buf, messageName); + if (returnVal) { + post("Problem writing address: %s\n", OSC_errorMessage); + } + } else { + /* First figure out the type tags */ + char typeTags[MAX_ARGS+2]; + int i; + + typeTags[0] = ','; + + for (i = 0; i < numArgs; ++i) { + switch (args[i].type) { + case INT_osc: + typeTags[i+1] = 'i'; + break; + + case FLOAT_osc: + typeTags[i+1] = 'f'; + break; + + case STRING_osc: + typeTags[i+1] = 's'; + break; + + default: + error("Unrecognized arg type (not exiting)"); + return(wmERROR); + } + } + typeTags[i+1] = '\0'; + + returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags); + if (returnVal) { + post("Problem writing address: %s\n", OSC_errorMessage); + } + } + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT_osc: + if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) { + return returnVal; + } + break; + + case FLOAT_osc: + if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) { + return returnVal; + } + break; + + case STRING_osc: + if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) { + return returnVal; + } + break; + + default: + error("Unrecognized arg type (not exiting)"); + returnVal = wmERROR; + } + } + return returnVal; +} + +void SendBuffer(void *htmsocket, OSCbuf *buf) { +#ifdef DEBUG + printf("Sending buffer...\n"); +#endif + if (OSC_isBufferEmpty(buf)) { + post("SendBuffer() called but buffer empty"); + return; + } + if (!OSC_isBufferDone(buf)) { + error("SendBuffer() called but buffer not ready!, not exiting"); + return; //{{raf}} + } + SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf)); +} + +void SendData(void *htmsocket, int size, char *data) { + if (!SendHTMSocket(htmsocket, size, data)) { + post("SendData::SendHTMSocket()failure -- not connected"); + CloseHTMSocket(htmsocket); + } +} + + + +/* ---------------------- + OSC-client code + + */ + +/* Here are the possible values of the state field: */ + +#define EMPTY 0 /* Nothing written to packet yet */ +#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */ +#define NEED_COUNT 2 /* Just opened a bundle; must write message name or + open another bundle */ +#define GET_ARGS 3 /* Getting arguments to a message. If we see a message + name or a bundle open/close then the current message + will end. */ +#define DONE 4 /* All open bundles have been closed, so can't write + anything else */ + +#ifdef WIN32 + #include <winsock2.h> + #include <io.h> + #include <stdio.h> + #include <errno.h> + #include <fcntl.h> + #include <sys/types.h> + #include <sys/stat.h> +#endif + +#ifdef __APPLE__ + #include <sys/types.h> +#endif + +#ifdef unix + #include <netinet/in.h> + #include <stdio.h> +#endif + + +char *OSC_errorMessage; + +static int OSC_padString(char *dest, char *str); +static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str); +static int OSC_WritePadding(char *dest, int i); +static int CheckTypeTag(OSCbuf *buf, char expectedType); + +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) { + buf->buffer = byteArray; + buf->size = size; + OSC_resetBuffer(buf); +} + +void OSC_resetBuffer(OSCbuf *buf) { + buf->bufptr = buf->buffer; + buf->state = EMPTY; + buf->bundleDepth = 0; + buf->prevCounts[0] = 0; + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; +} + +int OSC_isBufferEmpty(OSCbuf *buf) { + return buf->bufptr == buf->buffer; +} + +int OSC_freeSpaceInBuffer(OSCbuf *buf) { + return buf->size - (buf->bufptr - buf->buffer); +} + +int OSC_isBufferDone(OSCbuf *buf) { + return (buf->state == DONE || buf->state == ONE_MSG_ARGS); +} + +char *OSC_getPacket(OSCbuf *buf) { +#ifdef ERROR_CHECK_GETPACKET + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return buf->buffer; + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return buf->buffer; +#endif +} + +int OSC_packetSize(OSCbuf *buf) { +#ifdef ERROR_CHECK_PACKETSIZE + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return (buf->bufptr - buf->buffer); + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return (buf->bufptr - buf->buffer); +#endif +} + +#define CheckOverflow(buf, bytesNeeded) { if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) {OSC_errorMessage = "buffer overflow"; return 1;}} + +static void PatchMessageSize(OSCbuf *buf) { + int4byte size; + size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; + *(buf->thisMsgSize) = htonl(size); +} + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) { + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "Can't open a bundle in a one-message packet"; + return 3; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't open a new bundle"; + return 4; + } + + if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) { + OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h"; + return 2; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->state == EMPTY) { + /* Need 16 bytes for "#bundle" and time tag */ + CheckOverflow(buf, 16); + } else { + /* This bundle is inside another bundle, so we need to leave + a blank size count for the size of this current bundle. */ + CheckOverflow(buf, 20); + *((int4byte *)buf->bufptr) = 0xaaaaaaaa; + buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr; + + buf->bufptr += 4; + } + + buf->bufptr += OSC_padString(buf->bufptr, "#bundle"); + + + *((OSCTimeTag *) buf->bufptr) = tt; + + if (htonl(1) != 1) { + /* Byte swap the 8-byte integer time tag */ + int4byte *intp = (int4byte *)buf->bufptr; + intp[0] = htonl(intp[0]); + intp[1] = htonl(intp[1]); + +#ifdef HAS8BYTEINT + { /* tt is a 64-bit int so we have to swap the two 32-bit words. + (Otherwise tt is a struct of two 32-bit words, and even though + each word was wrong-endian, they were in the right order + in the struct.) */ + int4byte temp = intp[0]; + intp[0] = intp[1]; + intp[1] = temp; + } +#endif + } + + buf->bufptr += sizeof(OSCTimeTag); + + buf->state = NEED_COUNT; + + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; + return 0; +} + + +int OSC_closeBundle(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close bundle; no bundle is open!"; + return 5; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->bundleDepth == 1) { + /* Closing the last bundle: No bundle size to patch */ + buf->state = DONE; + } else { + /* Closing a sub-bundle: patch bundle size */ + int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4; + *(buf->prevCounts[buf->bundleDepth]) = htonl(size); + buf->state = NEED_COUNT; + } + + --buf->bundleDepth; + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; + return 0; +} + + +int OSC_closeAllBundles(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close all bundles; no bundle is open!"; + return 6; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + while (buf->bundleDepth > 0) { + OSC_closeBundle(buf); + } + buf->typeStringPtr = 0; + return 0; +} + +int OSC_writeAddress(OSCbuf *buf, char *name) { + int4byte paddedLength; + + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "This packet is not a bundle, so you can't write another address"; + return 7; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't write another address"; + return 8; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + paddedLength = OSC_effectiveStringLength(name); + + if (buf->state == EMPTY) { + /* This will be a one-message packet, so no sizes to worry about */ + CheckOverflow(buf, paddedLength); + buf->state = ONE_MSG_ARGS; + } else { + /* GET_ARGS or NEED_COUNT */ + CheckOverflow(buf, 4+paddedLength); + if (buf->state == GET_ARGS) { + /* Close the old message */ + PatchMessageSize(buf); + } + buf->thisMsgSize = (int4byte *)buf->bufptr; + *(buf->thisMsgSize) = 0xbbbbbbbb; + buf->bufptr += 4; + buf->state = GET_ARGS; + } + + /* Now write the name */ + buf->bufptr += OSC_padString(buf->bufptr, name); + buf->typeStringPtr = 0; + buf->gettingFirstUntypedArg = 1; + + return 0; +} + +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) { + int result; + int4byte paddedLength; + + if (CheckTypeTag(buf, '\0')) return 9; + + result = OSC_writeAddress(buf, name); + + if (result) return result; + + paddedLength = OSC_effectiveStringLength(types); + + CheckOverflow(buf, paddedLength); + + buf->typeStringPtr = buf->bufptr + 1; /* skip comma */ + buf->bufptr += OSC_padString(buf->bufptr, types); + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +static int CheckTypeTag(OSCbuf *buf, char expectedType) { + if (buf->typeStringPtr) { + if (*(buf->typeStringPtr) != expectedType) { + if (expectedType == '\0') { + OSC_errorMessage = + "According to the type tag I expected more arguments."; + } else if (*(buf->typeStringPtr) == '\0') { + OSC_errorMessage = + "According to the type tag I didn't expect any more arguments."; + } else { + OSC_errorMessage = + "According to the type tag I expected an argument of a different type."; + printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr); + } + return 9; + } + ++(buf->typeStringPtr); + } + return 0; +} + + +int OSC_writeFloatArg(OSCbuf *buf, float arg) { + int4byte *intp; + //int result; + + CheckOverflow(buf, 4); + + if (CheckTypeTag(buf, 'f')) return 9; + + /* Pretend arg is a long int so we can use htonl() */ + intp = ((int4byte *) &arg); + *((int4byte *) buf->bufptr) = htonl(*intp); + + buf->bufptr += 4; + + buf->gettingFirstUntypedArg = 0; + return 0; +} + + + +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) { + int i; + int4byte *intp; + + CheckOverflow(buf, 4 * numFloats); + + /* Pretend args are long ints so we can use htonl() */ + intp = ((int4byte *) args); + + for (i = 0; i < numFloats; i++) { + if (CheckTypeTag(buf, 'f')) return 9; + *((int4byte *) buf->bufptr) = htonl(intp[i]); + buf->bufptr += 4; + } + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +int OSC_writeIntArg(OSCbuf *buf, int4byte arg) { + CheckOverflow(buf, 4); + if (CheckTypeTag(buf, 'i')) return 9; + + *((int4byte *) buf->bufptr) = htonl(arg); + buf->bufptr += 4; + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +int OSC_writeStringArg(OSCbuf *buf, char *arg) { + int len; + + if (CheckTypeTag(buf, 's')) return 9; + + len = OSC_effectiveStringLength(arg); + + if (buf->gettingFirstUntypedArg && arg[0] == ',') { + /* This un-type-tagged message starts with a string + that starts with a comma, so we have to escape it + (with a double comma) so it won't look like a type + tag string. */ + + CheckOverflow(buf, len+4); /* Too conservative */ + buf->bufptr += + OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg); + + } else { + CheckOverflow(buf, len); + buf->bufptr += OSC_padString(buf->bufptr, arg); + } + + buf->gettingFirstUntypedArg = 0; + return 0; + +} + +/* String utilities */ + +#define STRING_ALIGN_PAD 4 +int OSC_effectiveStringLength(char *string) { + int len = strlen(string) + 1; /* We need space for the null char. */ + + /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */ + if ((len % STRING_ALIGN_PAD) != 0) { + len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD); + } + return len; +} + +static int OSC_padString(char *dest, char *str) { + int i; + + for (i = 0; str[i] != '\0'; i++) { + dest[i] = str[i]; + } + + return OSC_WritePadding(dest, i); +} + +static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) { + int i; + + dest[0] = ','; + for (i = 0; str[i] != '\0'; i++) { + dest[i+1] = str[i]; + } + + return OSC_WritePadding(dest, i+1); +} + +static int OSC_WritePadding(char *dest, int i) { + dest[i] = '\0'; + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + dest[i] = '\0'; + } + + return i; +} + diff --git a/apps/plugins/pdbox/PDa/extra/shell.c b/apps/plugins/pdbox/PDa/extra/shell.c index dd6b0e2..51abc13 100644 --- a/apps/plugins/pdbox/PDa/extra/shell.c +++ b/apps/plugins/pdbox/PDa/extra/shell.c @@ -1,312 +1,312 @@ -/* (C) Guenter Geiger <geiger@epy.co.at> */
-
-#include "m_pd.h"
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <sched.h>
-
-void sys_rmpollfn(int fd);
-void sys_addpollfn(int fd, void* fn, void *ptr);
-
-/* ------------------------ shell ----------------------------- */
-
-#define INBUFSIZE 1024
-
-static t_class *shell_class;
-
-
-static void drop_priority(void)
-{
-#ifdef _POSIX_PRIORITY_SCHEDULING
- struct sched_param par;
- int p1 ,p2, p3;
- par.sched_priority = 0;
- sched_setscheduler(0,SCHED_OTHER,&par);
-#endif
-}
-
-
-typedef struct _shell
-{
- t_object x_obj;
- int x_echo;
- char *sr_inbuf;
- int sr_inhead;
- int sr_intail;
- void* x_binbuf;
- int fdpipe[2];
- int fdinpipe[2];
- int pid;
- int x_del;
- t_outlet* x_done;
- t_clock* x_clock;
-} t_shell;
-
-static int shell_pid;
-
-
-void shell_cleanup(t_shell* x)
-{
- sys_rmpollfn(x->fdpipe[0]);
-
- if (x->fdpipe[0]>0) close(x->fdpipe[0]);
- if (x->fdpipe[1]>0) close(x->fdpipe[1]);
- if (x->fdinpipe[0]>0) close(x->fdinpipe[0]);
- if (x->fdinpipe[1]>0) close(x->fdinpipe[1]);
-
- x->fdpipe[0] = -1;
- x->fdpipe[1] = -1;
- x->fdinpipe[0] = -1;
- x->fdinpipe[1] = -1;
- clock_unset(x->x_clock);
-}
-
-void shell_check(t_shell* x)
-{
- int ret;
- int status;
- ret = waitpid(x->pid,&status,WNOHANG);
- if (ret == x->pid) {
- shell_cleanup(x);
- if (WIFEXITED(status)) {
- outlet_float(x->x_done,WEXITSTATUS(status));
- }
- else outlet_float(x->x_done,0);
- }
- else {
- if (x->x_del < 100) x->x_del+=2; /* increment poll times */
- clock_delay(x->x_clock,x->x_del);
- }
-}
-
-
-void shell_bang(t_shell *x)
-{
- post("bang");
-}
-
-/* snippet from pd's code */
-static void shell_doit(void *z, t_binbuf *b)
-{
- t_shell *x = (t_shell *)z;
- int msg, natom = binbuf_getnatom(b);
- t_atom *at = binbuf_getvec(b);
-
- for (msg = 0; msg < natom;)
- {
- int emsg;
- for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
- && at[emsg].a_type != A_SEMI; emsg++)
- ;
- if (emsg > msg)
- {
- int i;
- for (i = msg; i < emsg; i++)
- if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
- {
- pd_error(x, "netreceive: got dollar sign in message");
- goto nodice;
- }
- if (at[msg].a_type == A_FLOAT)
- {
- if (emsg > msg + 1)
- outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
- else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
- }
- else if (at[msg].a_type == A_SYMBOL)
- outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
- emsg-msg-1, at + msg + 1);
- }
- nodice:
- msg = emsg + 1;
- }
-}
-
-
-void shell_read(t_shell *x, int fd)
-{
- char buf[INBUFSIZE];
- t_binbuf* bbuf = binbuf_new();
- int i;
- int readto =
- (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
- int ret;
-
- ret = read(fd, buf,INBUFSIZE-1);
- buf[ret] = '\0';
-
- for (i=0;i<ret;i++)
- if (buf[i] == '\n') buf[i] = ';';
- if (ret < 0)
- {
- error("shell: pipe read error");
- sys_rmpollfn(fd);
- x->fdpipe[0] = -1;
- close(fd);
- return;
- }
- else if (ret == 0)
- {
- post("EOF on socket %d\n", fd);
- sys_rmpollfn(fd);
- x->fdpipe[0] = -1;
- close(fd);
- return;
- }
- else
- {
- int natom;
- t_atom *at;
- binbuf_text(bbuf, buf, strlen(buf));
-
- natom = binbuf_getnatom(bbuf);
- at = binbuf_getvec(bbuf);
- shell_doit(x,bbuf);
- }
- binbuf_free(bbuf);
-}
-
-
-static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at)
-{
- int i;
- char tmp[MAXPDSTRING];
- int size = 0;
-
- if (x->fdinpipe[0] == -1) return; /* nothing to send to */
-
- for (i=0;i<ac;i++) {
- atom_string(at,tmp+size,MAXPDSTRING - size);
- at++;
- size=strlen(tmp);
- tmp[size++] = ' ';
- }
- tmp[size-1] = '\0';
- post("sending %s",tmp);
- write(x->fdinpipe[0],tmp,strlen(tmp));
-}
-
-static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
-{
- int i;
- char* argv[20];
- t_symbol* sym;
-
- if (!strcmp(s->s_name,"send")) {
- post("send");
- shell_send(x,s,ac,at);
- return;
- }
-
- argv[0] = s->s_name;
-
- if (x->fdpipe[0] != -1) {
- post("shell: old process still running");
- kill(x->pid,SIGKILL);
- shell_cleanup(x);
- }
-
-
- if (pipe(x->fdpipe) < 0) {
- error("unable to create pipe");
- return;
- }
-
- if (pipe(x->fdinpipe) < 0) {
- error("unable to create input pipe");
- return;
- }
-
-
- sys_addpollfn(x->fdpipe[0],shell_read,x);
-
- if (!(x->pid = fork())) {
- int status;
- char* cmd = getbytes(1024);
- char* tcmd = getbytes(1024);
- strcpy(cmd,s->s_name);
-
-#if 0
- for (i=1;i<=ac;i++) {
- argv[i] = getbytes(255);
- atom_string(at,argv[i],255);
-/* post("argument %s",argv[i]); */
- at++;
- }
- argv[i] = 0;
-#endif
- for (i=1;i<=ac;i++) {
- atom_string(at,tcmd,255);
- strcat(cmd," ");
- strcat(cmd,tcmd);
- at++;
- }
-
-
- /* reassign stdout */
- dup2(x->fdpipe[1],1);
- dup2(x->fdinpipe[1],0);
-
- /* drop privileges */
- drop_priority();
- seteuid(getuid()); /* lose setuid priveliges */
-
- post("executing %s",cmd);
- system(cmd);
-// execvp(s->s_name,argv);
- exit(0);
- }
- x->x_del = 4;
- clock_delay(x->x_clock,x->x_del);
-
- if (x->x_echo)
- outlet_anything(x->x_obj.ob_outlet, s, ac, at);
-}
-
-
-
-void shell_free(t_shell* x)
-{
- binbuf_free(x->x_binbuf);
-}
-
-static void *shell_new(void)
-{
- t_shell *x = (t_shell *)pd_new(shell_class);
-
- x->x_echo = 0;
- x->fdpipe[0] = -1;
- x->fdpipe[1] = -1;
- x->fdinpipe[0] = -1;
- x->fdinpipe[1] = -1;
-
- x->sr_inhead = x->sr_intail = 0;
- if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
-
- x->x_binbuf = binbuf_new();
-
- outlet_new(&x->x_obj, &s_list);
- x->x_done = outlet_new(&x->x_obj, &s_bang);
- x->x_clock = clock_new(x, (t_method) shell_check);
- return (x);
-}
-
-void shell_setup(void)
-{
- shell_class = class_new(gensym("shell"), (t_newmethod)shell_new,
- (t_method)shell_free,sizeof(t_shell), 0,0);
- class_addbang(shell_class,shell_bang);
- class_addanything(shell_class, shell_anything);
-}
-
+/* (C) Guenter Geiger <geiger@epy.co.at> */ + +#include "m_pd.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <sched.h> + +void sys_rmpollfn(int fd); +void sys_addpollfn(int fd, void* fn, void *ptr); + +/* ------------------------ shell ----------------------------- */ + +#define INBUFSIZE 1024 + +static t_class *shell_class; + + +static void drop_priority(void) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING + struct sched_param par; + int p1 ,p2, p3; + par.sched_priority = 0; + sched_setscheduler(0,SCHED_OTHER,&par); +#endif +} + + +typedef struct _shell +{ + t_object x_obj; + int x_echo; + char *sr_inbuf; + int sr_inhead; + int sr_intail; + void* x_binbuf; + int fdpipe[2]; + int fdinpipe[2]; + int pid; + int x_del; + t_outlet* x_done; + t_clock* x_clock; +} t_shell; + +static int shell_pid; + + +void shell_cleanup(t_shell* x) +{ + sys_rmpollfn(x->fdpipe[0]); + + if (x->fdpipe[0]>0) close(x->fdpipe[0]); + if (x->fdpipe[1]>0) close(x->fdpipe[1]); + if (x->fdinpipe[0]>0) close(x->fdinpipe[0]); + if (x->fdinpipe[1]>0) close(x->fdinpipe[1]); + + x->fdpipe[0] = -1; + x->fdpipe[1] = -1; + x->fdinpipe[0] = -1; + x->fdinpipe[1] = -1; + clock_unset(x->x_clock); +} + +void shell_check(t_shell* x) +{ + int ret; + int status; + ret = waitpid(x->pid,&status,WNOHANG); + if (ret == x->pid) { + shell_cleanup(x); + if (WIFEXITED(status)) { + outlet_float(x->x_done,WEXITSTATUS(status)); + } + else outlet_float(x->x_done,0); + } + else { + if (x->x_del < 100) x->x_del+=2; /* increment poll times */ + clock_delay(x->x_clock,x->x_del); + } +} + + +void shell_bang(t_shell *x) +{ + post("bang"); +} + +/* snippet from pd's code */ +static void shell_doit(void *z, t_binbuf *b) +{ + t_shell *x = (t_shell *)z; + int msg, natom = binbuf_getnatom(b); + t_atom *at = binbuf_getvec(b); + + for (msg = 0; msg < natom;) + { + int emsg; + for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA + && at[emsg].a_type != A_SEMI; emsg++) + ; + if (emsg > msg) + { + int i; + for (i = msg; i < emsg; i++) + if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM) + { + pd_error(x, "netreceive: got dollar sign in message"); + goto nodice; + } + if (at[msg].a_type == A_FLOAT) + { + if (emsg > msg + 1) + outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg); + else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float); + } + else if (at[msg].a_type == A_SYMBOL) + outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol, + emsg-msg-1, at + msg + 1); + } + nodice: + msg = emsg + 1; + } +} + + +void shell_read(t_shell *x, int fd) +{ + char buf[INBUFSIZE]; + t_binbuf* bbuf = binbuf_new(); + int i; + int readto = + (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); + int ret; + + ret = read(fd, buf,INBUFSIZE-1); + buf[ret] = '\0'; + + for (i=0;i<ret;i++) + if (buf[i] == '\n') buf[i] = ';'; + if (ret < 0) + { + error("shell: pipe read error"); + sys_rmpollfn(fd); + x->fdpipe[0] = -1; + close(fd); + return; + } + else if (ret == 0) + { + post("EOF on socket %d\n", fd); + sys_rmpollfn(fd); + x->fdpipe[0] = -1; + close(fd); + return; + } + else + { + int natom; + t_atom *at; + binbuf_text(bbuf, buf, strlen(buf)); + + natom = binbuf_getnatom(bbuf); + at = binbuf_getvec(bbuf); + shell_doit(x,bbuf); + } + binbuf_free(bbuf); +} + + +static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at) +{ + int i; + char tmp[MAXPDSTRING]; + int size = 0; + + if (x->fdinpipe[0] == -1) return; /* nothing to send to */ + + for (i=0;i<ac;i++) { + atom_string(at,tmp+size,MAXPDSTRING - size); + at++; + size=strlen(tmp); + tmp[size++] = ' '; + } + tmp[size-1] = '\0'; + post("sending %s",tmp); + write(x->fdinpipe[0],tmp,strlen(tmp)); +} + +static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at) +{ + int i; + char* argv[20]; + t_symbol* sym; + + if (!strcmp(s->s_name,"send")) { + post("send"); + shell_send(x,s,ac,at); + return; + } + + argv[0] = s->s_name; + + if (x->fdpipe[0] != -1) { + post("shell: old process still running"); + kill(x->pid,SIGKILL); + shell_cleanup(x); + } + + + if (pipe(x->fdpipe) < 0) { + error("unable to create pipe"); + return; + } + + if (pipe(x->fdinpipe) < 0) { + error("unable to create input pipe"); + return; + } + + + sys_addpollfn(x->fdpipe[0],shell_read,x); + + if (!(x->pid = fork())) { + int status; + char* cmd = getbytes(1024); + char* tcmd = getbytes(1024); + strcpy(cmd,s->s_name); + +#if 0 + for (i=1;i<=ac;i++) { + argv[i] = getbytes(255); + atom_string(at,argv[i],255); +/* post("argument %s",argv[i]); */ + at++; + } + argv[i] = 0; +#endif + for (i=1;i<=ac;i++) { + atom_string(at,tcmd,255); + strcat(cmd," "); + strcat(cmd,tcmd); + at++; + } + + + /* reassign stdout */ + dup2(x->fdpipe[1],1); + dup2(x->fdinpipe[1],0); + + /* drop privileges */ + drop_priority(); + seteuid(getuid()); /* lose setuid priveliges */ + + post("executing %s",cmd); + system(cmd); +// execvp(s->s_name,argv); + exit(0); + } + x->x_del = 4; + clock_delay(x->x_clock,x->x_del); + + if (x->x_echo) + outlet_anything(x->x_obj.ob_outlet, s, ac, at); +} + + + +void shell_free(t_shell* x) +{ + binbuf_free(x->x_binbuf); +} + +static void *shell_new(void) +{ + t_shell *x = (t_shell *)pd_new(shell_class); + + x->x_echo = 0; + x->fdpipe[0] = -1; + x->fdpipe[1] = -1; + x->fdinpipe[0] = -1; + x->fdinpipe[1] = -1; + + x->sr_inhead = x->sr_intail = 0; + if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");; + + x->x_binbuf = binbuf_new(); + + outlet_new(&x->x_obj, &s_list); + x->x_done = outlet_new(&x->x_obj, &s_bang); + x->x_clock = clock_new(x, (t_method) shell_check); + return (x); +} + +void shell_setup(void) +{ + shell_class = class_new(gensym("shell"), (t_newmethod)shell_new, + (t_method)shell_free,sizeof(t_shell), 0,0); + class_addbang(shell_class,shell_bang); + class_addanything(shell_class, shell_anything); +} + |