summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra')
-rw-r--r--apps/plugins/pdbox/PDa/extra/OSC-client.h376
-rw-r--r--apps/plugins/pdbox/PDa/extra/OSC.pd26
-rw-r--r--apps/plugins/pdbox/PDa/extra/OSCroute.c1204
-rw-r--r--apps/plugins/pdbox/PDa/extra/README24
-rw-r--r--apps/plugins/pdbox/PDa/extra/bandpass-help.pd34
-rw-r--r--apps/plugins/pdbox/PDa/extra/bandpass.c172
-rw-r--r--apps/plugins/pdbox/PDa/extra/dumpOSC.c1998
-rw-r--r--apps/plugins/pdbox/PDa/extra/equalizer.c178
-rw-r--r--apps/plugins/pdbox/PDa/extra/fatom.h970
-rw-r--r--apps/plugins/pdbox/PDa/extra/filters.h148
-rw-r--r--apps/plugins/pdbox/PDa/extra/g_canvas.h1204
-rw-r--r--apps/plugins/pdbox/PDa/extra/gcanvas-help.pd16
-rw-r--r--apps/plugins/pdbox/PDa/extra/gcanvas.c758
-rw-r--r--apps/plugins/pdbox/PDa/extra/highpass.c174
-rw-r--r--apps/plugins/pdbox/PDa/extra/highshelf.c180
-rw-r--r--apps/plugins/pdbox/PDa/extra/hlshelf.c452
-rw-r--r--apps/plugins/pdbox/PDa/extra/image.c434
-rw-r--r--apps/plugins/pdbox/PDa/extra/lowpass.c178
-rw-r--r--apps/plugins/pdbox/PDa/extra/lowshelf.c182
-rw-r--r--apps/plugins/pdbox/PDa/extra/m_pd.h1300
-rw-r--r--apps/plugins/pdbox/PDa/extra/makefile66
-rw-r--r--apps/plugins/pdbox/PDa/extra/moog~.c366
-rw-r--r--apps/plugins/pdbox/PDa/extra/notch.c178
-rw-r--r--apps/plugins/pdbox/PDa/extra/s_stuff.h430
-rw-r--r--apps/plugins/pdbox/PDa/extra/sendOSC.c2922
-rw-r--r--apps/plugins/pdbox/PDa/extra/sformat.h110
-rw-r--r--apps/plugins/pdbox/PDa/extra/shell.c624
-rw-r--r--apps/plugins/pdbox/PDa/extra/slider.c106
-rw-r--r--apps/plugins/pdbox/PDa/extra/sliderh.c126
-rw-r--r--apps/plugins/pdbox/PDa/extra/test-clip.pd26
-rw-r--r--apps/plugins/pdbox/PDa/extra/test-vcf.pd36
-rw-r--r--apps/plugins/pdbox/PDa/extra/zerox~.c114
32 files changed, 15112 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/OSC-client.h b/apps/plugins/pdbox/PDa/extra/OSC-client.h
new file mode 100644
index 0000000000..196143f8e7
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/OSC-client.h
@@ -0,0 +1,376 @@
1/*
2Written by Matt Wright, The Center for New Music and Audio Technologies,
3University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
4The Regents of the University of California (Regents).
5
6Permission to use, copy, modify, distribute, and distribute modified versions
7of this software and its documentation without fee and without a signed
8licensing agreement, is hereby granted, provided that the above copyright
9notice, this paragraph and the following two paragraphs appear in all copies,
10modifications, and distributions.
11
12IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
13SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
14OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
15BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
17REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
20HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
21MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22*/
23
24/*
25
26 OSC-client.h: library for constructing OpenSoundControl messages.
27 Derived from SynthControl.h
28 Author: Matt Wright
29 Version 0.1: 6/13/97
30 Version 0.2: 7/21/2000: Support for type-tagged messages
31
32
33 General notes:
34
35 This library abstracts away the data format for the OpenSoundControl
36 protocol. Users of this library can construct OpenSoundControl packets
37 with a function call interface instead of knowing how to lay out the bits.
38
39 All issues of memory allocation are deferred to the user of this library.
40 There are two data structures that the user must allocate. The first
41 is the actual buffer that the message will be written into. This buffer
42 can be any size, but if it's too small there's a possibility that it
43 will become overfull. The other data structure is called an OSCbuf,
44 and it holds all the state used by the library as it's constructing
45 a buffer.
46
47 All procedures that have the possibility of an error condition return int,
48 with 0 indicating no error and nonzero indicating an error. The variable
49 OSC_errorMessage will be set to point to a string containing an error
50 message explaining what the problem is.
51
52*/
53
54
55
56/* The int4byte type has to be a 4-byte integer. You may have to
57 change this to long or something else on your system. */
58#ifdef __MWERKS__
59 /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is
60 always 4 bytes */
61 typedef long int4byte;
62#else
63 typedef int int4byte;
64#endif
65
66/* OSC_timetag.h */
67
68 typedef struct {
69 int seconds;
70 int fraction;
71 } OSCTimeTag;
72
73OSCTimeTag OSCTT_Immediately(void);
74OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset);
75OSCTimeTag OSCTT_CurrentTime(void);
76
77
78
79/* The maximum depth of bundles within bundles within bundles within...
80 This is the size of a static array. If you exceed this limit you'll
81 get an error message. */
82#define MAX_BUNDLE_NESTING 32
83
84
85/* Don't ever manipulate the data in the OSCbuf struct directly. (It's
86 declared here in the header file only so your program will be able to
87 declare variables of type OSCbuf and have the right amount of memory
88 be allocated.) */
89
90typedef struct OSCbuf_struct {
91 char *buffer; /* The buffer to hold the OSC packet */
92 int size; /* Size of the buffer */
93 char *bufptr; /* Current position as we fill the buffer */
94 int state; /* State of partially-constructed message */
95 int4byte *thisMsgSize; /* Pointer to count field before
96 currently-being-written message */
97 int4byte *prevCounts[MAX_BUNDLE_NESTING];
98 /* Pointers to count field before each currently
99 open bundle */
100 int bundleDepth; /* How many sub-sub-bundles are we in now? */
101 char *typeStringPtr; /* This pointer advances through the type
102 tag string as you add arguments. */
103 int gettingFirstUntypedArg; /* nonzero if this message doesn't have
104 a type tag and we're waiting for the 1st arg */
105} OSCbuf;
106
107
108
109/* Initialize the given OSCbuf. The user of this module must pass in the
110 block of memory that this OSCbuf will use for a buffer, and the number of
111 bytes in that block. (It's the user's job to allocate the memory because
112 you do it differently in different systems.) */
113void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray);
114
115
116/* Reset the given OSCbuf. Do this after you send out the contents of
117 the buffer and want to start writing new data into it. */
118void OSC_resetBuffer(OSCbuf *buf);
119
120
121/* Is the buffer empty? (I.e., would it be stupid to send the buffer
122 contents to the synth?) */
123int OSC_isBufferEmpty(OSCbuf *buf);
124
125
126/* How much space is left in the buffer? */
127int OSC_freeSpaceInBuffer(OSCbuf *buf);
128
129/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */
130int OSC_isBufferDone(OSCbuf *buf);
131
132/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone()
133 returns true), call these two procedures to get the OSC packet that's been
134 assembled and its size in bytes. (And then call OSC_resetBuffer() if you
135 want to re-use this OSCbuf for the next packet.) */
136char *OSC_getPacket(OSCbuf *buf);
137int OSC_packetSize(OSCbuf *buf);
138
139
140
141/* Here's the basic model for building up OSC messages in an OSCbuf:
142
143 - Make sure the OSCbuf has been initialized with OSC_initBuffer().
144
145 - To open a bundle, call OSC_openBundle(). You can then write
146 messages or open new bundles within the bundle you opened.
147 Call OSC_closeBundle() to close the bundle. Note that a packet
148 does not have to have a bundle; it can instead consist of just a
149 single message.
150
151
152 - For each message you want to send:
153
154 - Call OSC_writeAddress() with the name of your message. (In
155 addition to writing your message name into the buffer, this
156 procedure will also leave space for the size count of this message.)
157
158 - Alternately, call OSC_writeAddressAndTypes() with the name of
159 your message and with a type string listing the types of all the
160 arguments you will be putting in this message.
161
162 - Now write each of the arguments into the buffer, by calling one of:
163 OSC_writeFloatArg()
164 OSC_writeFloatArgs()
165 OSC_writeIntArg()
166 OSC_writeStringArg()
167
168 - Now your message is complete; you can send out the buffer or you can
169 add another message to it.
170*/
171
172int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt);
173int OSC_closeBundle(OSCbuf *buf);
174int OSC_closeAllBundles(OSCbuf *buf);
175
176int OSC_writeAddress(OSCbuf *buf, char *name);
177int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types);
178int OSC_writeFloatArg(OSCbuf *buf, float arg);
179int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args);
180int OSC_writeIntArg(OSCbuf *buf, int4byte arg);
181int OSC_writeStringArg(OSCbuf *buf, char *arg);
182
183extern char *OSC_errorMessage;
184
185/* How many bytes will be needed in the OSC format to hold the given
186 string? The length of the string, plus the null char, plus any padding
187 needed for 4-byte alignment. */
188int OSC_effectiveStringLength(char *string);
189/*
190Written by Matt Wright, The Center for New Music and Audio Technologies,
191University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
192The Regents of the University of California (Regents).
193
194Permission to use, copy, modify, distribute, and distribute modified versions
195of this software and its documentation without fee and without a signed
196licensing agreement, is hereby granted, provided that the above copyright
197notice, this paragraph and the following two paragraphs appear in all copies,
198modifications, and distributions.
199
200IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
201SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
202OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
203BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
204
205REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
206THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
207PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
208HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
209MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
210*/
211
212/*
213
214 OSC-client.h: library for constructing OpenSoundControl messages.
215 Derived from SynthControl.h
216 Author: Matt Wright
217 Version 0.1: 6/13/97
218 Version 0.2: 7/21/2000: Support for type-tagged messages
219
220
221 General notes:
222
223 This library abstracts away the data format for the OpenSoundControl
224 protocol. Users of this library can construct OpenSoundControl packets
225 with a function call interface instead of knowing how to lay out the bits.
226
227 All issues of memory allocation are deferred to the user of this library.
228 There are two data structures that the user must allocate. The first
229 is the actual buffer that the message will be written into. This buffer
230 can be any size, but if it's too small there's a possibility that it
231 will become overfull. The other data structure is called an OSCbuf,
232 and it holds all the state used by the library as it's constructing
233 a buffer.
234
235 All procedures that have the possibility of an error condition return int,
236 with 0 indicating no error and nonzero indicating an error. The variable
237 OSC_errorMessage will be set to point to a string containing an error
238 message explaining what the problem is.
239
240*/
241
242
243
244/* The int4byte type has to be a 4-byte integer. You may have to
245 change this to long or something else on your system. */
246#ifdef __MWERKS__
247 /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is
248 always 4 bytes */
249 typedef long int4byte;
250#else
251 typedef int int4byte;
252#endif
253
254/* OSC_timetag.h */
255
256 typedef struct {
257 int seconds;
258 int fraction;
259 } OSCTimeTag;
260
261OSCTimeTag OSCTT_Immediately(void);
262OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset);
263OSCTimeTag OSCTT_CurrentTime(void);
264
265
266
267/* The maximum depth of bundles within bundles within bundles within...
268 This is the size of a static array. If you exceed this limit you'll
269 get an error message. */
270#define MAX_BUNDLE_NESTING 32
271
272
273/* Don't ever manipulate the data in the OSCbuf struct directly. (It's
274 declared here in the header file only so your program will be able to
275 declare variables of type OSCbuf and have the right amount of memory
276 be allocated.) */
277
278typedef struct OSCbuf_struct {
279 char *buffer; /* The buffer to hold the OSC packet */
280 int size; /* Size of the buffer */
281 char *bufptr; /* Current position as we fill the buffer */
282 int state; /* State of partially-constructed message */
283 int4byte *thisMsgSize; /* Pointer to count field before
284 currently-being-written message */
285 int4byte *prevCounts[MAX_BUNDLE_NESTING];
286 /* Pointers to count field before each currently
287 open bundle */
288 int bundleDepth; /* How many sub-sub-bundles are we in now? */
289 char *typeStringPtr; /* This pointer advances through the type
290 tag string as you add arguments. */
291 int gettingFirstUntypedArg; /* nonzero if this message doesn't have
292 a type tag and we're waiting for the 1st arg */
293} OSCbuf;
294
295
296
297/* Initialize the given OSCbuf. The user of this module must pass in the
298 block of memory that this OSCbuf will use for a buffer, and the number of
299 bytes in that block. (It's the user's job to allocate the memory because
300 you do it differently in different systems.) */
301void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray);
302
303
304/* Reset the given OSCbuf. Do this after you send out the contents of
305 the buffer and want to start writing new data into it. */
306void OSC_resetBuffer(OSCbuf *buf);
307
308
309/* Is the buffer empty? (I.e., would it be stupid to send the buffer
310 contents to the synth?) */
311int OSC_isBufferEmpty(OSCbuf *buf);
312
313
314/* How much space is left in the buffer? */
315int OSC_freeSpaceInBuffer(OSCbuf *buf);
316
317/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */
318int OSC_isBufferDone(OSCbuf *buf);
319
320/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone()
321 returns true), call these two procedures to get the OSC packet that's been
322 assembled and its size in bytes. (And then call OSC_resetBuffer() if you
323 want to re-use this OSCbuf for the next packet.) */
324char *OSC_getPacket(OSCbuf *buf);
325int OSC_packetSize(OSCbuf *buf);
326
327
328
329/* Here's the basic model for building up OSC messages in an OSCbuf:
330
331 - Make sure the OSCbuf has been initialized with OSC_initBuffer().
332
333 - To open a bundle, call OSC_openBundle(). You can then write
334 messages or open new bundles within the bundle you opened.
335 Call OSC_closeBundle() to close the bundle. Note that a packet
336 does not have to have a bundle; it can instead consist of just a
337 single message.
338
339
340 - For each message you want to send:
341
342 - Call OSC_writeAddress() with the name of your message. (In
343 addition to writing your message name into the buffer, this
344 procedure will also leave space for the size count of this message.)
345
346 - Alternately, call OSC_writeAddressAndTypes() with the name of
347 your message and with a type string listing the types of all the
348 arguments you will be putting in this message.
349
350 - Now write each of the arguments into the buffer, by calling one of:
351 OSC_writeFloatArg()
352 OSC_writeFloatArgs()
353 OSC_writeIntArg()
354 OSC_writeStringArg()
355
356 - Now your message is complete; you can send out the buffer or you can
357 add another message to it.
358*/
359
360int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt);
361int OSC_closeBundle(OSCbuf *buf);
362int OSC_closeAllBundles(OSCbuf *buf);
363
364int OSC_writeAddress(OSCbuf *buf, char *name);
365int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types);
366int OSC_writeFloatArg(OSCbuf *buf, float arg);
367int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args);
368int OSC_writeIntArg(OSCbuf *buf, int4byte arg);
369int OSC_writeStringArg(OSCbuf *buf, char *arg);
370
371extern char *OSC_errorMessage;
372
373/* How many bytes will be needed in the OSC format to hold the given
374 string? The length of the string, plus the null char, plus any padding
375 needed for 4-byte alignment. */
376int OSC_effectiveStringLength(char *string);
diff --git a/apps/plugins/pdbox/PDa/extra/OSC.pd b/apps/plugins/pdbox/PDa/extra/OSC.pd
new file mode 100644
index 0000000000..8873f308da
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/OSC.pd
@@ -0,0 +1,26 @@
1#N canvas 0 0 240 300 10;
2#X obj 32 185 dumpOSC 5550;
3#X obj 32 217 OSCroute /hello;
4#X obj 32 239 print;
5#X obj 133 238 print;
6#X obj 26 87 sendOSC;
7#X msg 50 43 connect localhost 5550;
8#X msg 21 13 send /hello PDa;
9#X connect 0 0 1 0;
10#X connect 1 0 2 0;
11#X connect 1 1 3 0;
12#X connect 5 0 4 0;
13#X connect 6 0 4 0;
14#N canvas 0 0 240 300 10;
15#X obj 32 185 dumpOSC 5550;
16#X obj 32 217 OSCroute /hello;
17#X obj 32 239 print;
18#X obj 133 238 print;
19#X obj 26 87 sendOSC;
20#X msg 50 43 connect localhost 5550;
21#X msg 21 13 send /hello PDa;
22#X connect 0 0 1 0;
23#X connect 1 0 2 0;
24#X connect 1 1 3 0;
25#X connect 5 0 4 0;
26#X connect 6 0 4 0;
diff --git a/apps/plugins/pdbox/PDa/extra/OSCroute.c b/apps/plugins/pdbox/PDa/extra/OSCroute.c
new file mode 100644
index 0000000000..437d34dc68
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/OSCroute.c
@@ -0,0 +1,1204 @@
1/*
2Written by Adrian Freed, The Center for New Music and Audio Technologies,
3University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04
4The Regents of the University of California (Regents).
5
6Permission to use, copy, modify, distribute, and distribute modified versions
7of this software and its documentation without fee and without a signed
8licensing agreement, is hereby granted, provided that the above copyright
9notice, this paragraph and the following two paragraphs appear in all copies,
10modifications, and distributions.
11
12IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
13SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
14OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
15BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
17REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
20HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
21MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22
23
24The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
25*/
26
27 /* OSC-route.c
28 Max object for OSC-style dispatching
29
30 To-do:
31
32 Match a pattern against a pattern?
33 Declare outlet types / distinguish leaf nodes from other children
34 More sophisticated (2-pass?) allmessages scheme
35 set message?
36
37
38 pd
39 -------------
40 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
41
42
43 */
44
45#ifdef WIN32
46 #include <stdlib.h>
47 #include <string.h>
48#endif
49#ifdef __APPLE__
50 #include <stdio.h>
51#endif
52#ifdef UNIX
53 #include <stdio.h>
54#endif
55
56/* structure definition of your object */
57
58#define MAX_NUM 20
59#define OSC_ROUTE_VERSION "1.05"
60#define OSCWarning(x...) post(x)
61
62/* the required include files */
63#include "m_pd.h"
64
65
66#ifndef TRUE
67typedef int Boolean;
68#define TRUE 1
69#define FALSE 0
70#endif
71
72
73/* Fixed byte width types */
74typedef int int4; /* 4 byte int */
75
76Boolean PatternMatch (const char *pattern, const char *test);
77
78
79
80/* Version 1.04: Allows #1 thru #9 as typed-in arguments
81 Version 1.05: Allows "list" messages as well as "message" messages.
82*/
83
84static t_class *OSCroute_class;
85
86typedef struct _OSCroute
87{
88 t_object x_obj; // required header
89 t_int x_num; // Number of address prefixes we store
90 t_int x_complainmode; // Do we print a message if no match?
91 t_int x_sendmode; // use pd internal sends instead of outlets
92 char *x_prefixes[MAX_NUM];
93 void *x_outlets[MAX_NUM+1];
94} t_OSCroute;
95
96t_symbol *ps_list, *ps_complain, *ps_emptySymbol;
97
98/* prototypes */
99
100void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
101void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
102void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
103/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */
104void *OSCroute_new(t_symbol *s, int argc, t_atom *argv);
105void OSCroute_version (t_OSCroute *x);
106/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */
107/* char *dstString); */
108void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
109
110static char *NextSlashOrNull(char *p);
111static void StrCopyUntilSlash(char *target, const char *source);
112
113
114// free
115static void OSCroute_free(t_OSCroute *x)
116{
117 // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
118}
119
120/* initialization routine */
121
122// setup
123#ifdef WIN32
124 OSC_API void OSCroute_setup(void) {
125#else
126void OSCroute_setup(void) {
127#endif
128 OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new,
129 (t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0);
130 class_addlist(OSCroute_class, OSCroute_list);
131 class_addanything(OSCroute_class, OSCroute_anything);
132 class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0);
133 class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd"));
134
135 /*
136 class_addmethod(OSCroute_class, (t_method)OSCroute_connect,
137 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
138 class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect,
139 gensym("disconnect"), 0);
140 class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"),
141 A_GIMME, 0);
142 */
143/* ps_list = gensym("list"); */
144/* ps_complain = gensym("complain"); */
145 ps_emptySymbol = gensym("");
146
147 post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf.");
148 post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved.");
149}
150
151
152
153/* instance creation routine */
154
155void *OSCroute_new(t_symbol *s, int argc, t_atom *argv)
156{
157
158 t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize
159
160 int i; //{{raf}} n not used
161
162 // EnterCallback();
163
164 if (argc > MAX_NUM) {
165 post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM);
166 // ExitCallback();
167 return 0;
168 }
169
170 x->x_complainmode = 0;
171 x->x_num = 0;
172 for (i = 0; i < argc; ++i) {
173 if (argv[i].a_type == A_SYMBOL) {
174 if (argv[i].a_w.w_symbol->s_name[0] == '/') {
175 /* Now that's a nice prefix */
176 x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
177 ++(x->x_num);
178 } else if (argv[i].a_w.w_symbol->s_name[0] == '#' &&
179 argv[i].a_w.w_symbol->s_name[1] >= '1' &&
180 argv[i].a_w.w_symbol->s_name[1] <= '9') {
181 /* The Max programmer is trying to make a patch that will be
182 a subpatch with arguments. We have to make an outlet for this
183 argument. */
184 x->x_prefixes[i] = "dummy";
185 ++(x->x_num);
186 } else {
187 /* Maybe this is an option we support */
188
189/* if (argv[i].a_w.w_sym == ps_complain) { */
190/* x->x_complainmode = 1; */
191/* } else { */
192/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */
193/* } */
194
195 }
196
197 // no LONG
198
199/* } else if (argv[i].a_type == A_FLOAD) { */
200/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */
201/* char *string = getbytes(12); */
202/* // I can't be bothered to plug this 12 byte memory leak */
203/* if (string == 0) { */
204/* post("* OSC-route: out of memory!"); */
205/* // ExitCallback(); */
206/* return 0; */
207/* } */
208/* sprintf(string, "%d", argv[i].a_w.w_long); */
209/* x->x_prefixes[i] = string; */
210/* ++(x->x_num); */
211
212 } else if (argv[i].a_type == A_FLOAT) {
213 post("* OSC-route: float arguments are not OK.");
214 // ExitCallback();
215 return 0;
216 } else {
217 post("* OSC-route: unrecognized argument type!");
218 // ExitCallback();
219 return 0;
220 }
221 }
222
223
224 /* Have to create the outlets in reverse order */
225 /* well, not in pd ? */
226 // for (i = x->x_num-1; i >= 0; --i) {
227 // for (i = 0; i <= x->x_num-1; i++) {
228 for (i = 0; i <= x->x_num; i++) {
229 // x->x_outlets[i] = listout(x);
230 x->x_outlets[i] = outlet_new(&x->x_obj, &s_list);
231 }
232
233 // ExitCallback();
234 return (x);
235}
236
237
238void OSCroute_version (t_OSCroute *x) {
239 // EnterCallback();
240 post("OSCroute Version " OSC_ROUTE_VERSION
241 ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__);
242 // ExitCallback();
243}
244
245/* I don't know why these aren't defined in some Max #include file. */
246#define ASSIST_INLET 1
247#define ASSIST_OUTLET 2
248
249void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg,
250 char *dstString) {
251 // EnterCallback();
252
253 if (msg==ASSIST_INLET) {
254 sprintf(dstString, "Incoming OSC messages");
255 } else if (msg==ASSIST_OUTLET) {
256 if (arg < 0 || arg >= x->x_num) {
257 post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg);
258 } else {
259 sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]);
260 }
261 } else {
262 post("* OSCroute_assist: unrecognized message %ld", msg);
263 }
264
265 // ExitCallback();
266}
267
268void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
269 // EnterCallback();
270 if (argc > 0 && argv[0].a_type == A_SYMBOL) {
271 /* Ignore the fact that this is a "list" */
272 OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1);
273 } else {
274 // post("* OSC-route: invalid list beginning with a number");
275 // output on unmatched outlet jdl 20020908
276 if (argv[0].a_type == A_FLOAT) {
277 outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float);
278 } else {
279 post("* OSC-route: unrecognized atom type!");
280 }
281 }
282 // ExitCallback();
283}
284
285
286void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
287 // EnterCallback();
288 OSCroute_doanything(x, s, argc, argv);
289 // ExitCallback();
290}
291
292
293
294
295void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
296 char *pattern, *nextSlash;
297 int i;
298 int matchedAnything;
299 // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc);
300
301 pattern = s->s_name;
302 if (pattern[0] != '/') {
303 post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name);
304 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
305 return;
306 }
307
308 matchedAnything = 0;
309
310 nextSlash = NextSlashOrNull(pattern+1);
311 if (*nextSlash == '\0') {
312 /* last level of the address, so we'll output the argument list */
313
314
315#ifdef NULL_IS_DIFFERENT_FROM_BANG
316 if (argc==0) {
317 post("* OSC-route: why are you matching one level pattern %s with no args?",
318 pattern);
319 return;
320 }
321#endif
322
323 for (i = 0; i < x->x_num; ++i) {
324 if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) {
325 ++matchedAnything;
326
327 // I hate stupid Max lists with a special first element
328 if (argc == 0) {
329 outlet_bang(x->x_outlets[i]);
330 } else if (argv[0].a_type == A_SYMBOL) {
331 // Promote the symbol that was argv[0] to the special symbol
332 outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
333 } else if (argc > 1) {
334 // Multiple arguments starting with a number, so naturally we have
335 // to use a special function to output this "list", since it's what
336 // Max originally meant by "list".
337 outlet_list(x->x_outlets[i], 0L, argc, argv);
338 } else {
339 // There was only one argument, and it was a number, so we output it
340 // not as a list
341/* if (argv[0].a_type == A_LONG) { */
342
343/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */
344 // } else
345 if (argv[0].a_type == A_FLOAT) {
346
347 outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
348 } else {
349 post("* OSC-route: unrecognized atom type!");
350 }
351 }
352 }
353 }
354 } else {
355 /* There's more address after this part, so our output list will begin with
356 the next slash. */
357 t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
358 char patternBegin[1000];
359
360
361 /* Get the first level of the incoming pattern to match against all our prefixes */
362 StrCopyUntilSlash(patternBegin, pattern+1);
363
364 for (i = 0; i < x->x_num; ++i) {
365 if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) {
366 ++matchedAnything;
367 if (restOfPattern == 0) {
368 restOfPattern = gensym(nextSlash);
369 }
370 outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
371 }
372 }
373 }
374
375 if (x->x_complainmode) {
376 if (!matchedAnything) {
377 post("* OSC-route: pattern %s did not match any prefixes", pattern);
378 }
379 }
380
381 // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
382 if (!matchedAnything) {
383 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
384 }
385
386
387}
388
389static char *NextSlashOrNull(char *p) {
390 while (*p != '/' && *p != '\0') {
391 p++;
392 }
393 return p;
394}
395
396static void StrCopyUntilSlash(char *target, const char *source) {
397 while (*source != '/' && *source != '\0') {
398 *target = *source;
399 ++target;
400 ++source;
401 }
402 *target = 0;
403}
404
405static int MyStrCopy(char *target, const char *source) {
406 int i = 0;
407 while (*source != '\0') {
408 *target = *source;
409 ++target;
410 ++source;
411 ++i;
412 }
413 *target = 0;
414 return i;
415}
416
417
418
419void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
420 int i;
421 t_symbol *prefixSymbol = 0;
422 char prefixBuf[1000];
423 char *endOfPrefix;
424 t_atom a[1];
425
426 if (argc >= 1 && argv[0].a_type == A_SYMBOL) {
427 prefixSymbol = argv[0].a_w.w_symbol;
428 endOfPrefix = prefixBuf + MyStrCopy(prefixBuf,
429 prefixSymbol->s_name);
430 } else {
431 prefixSymbol = ps_emptySymbol;
432 prefixBuf[0] = '\0';
433 endOfPrefix = prefixBuf;
434 }
435
436
437 for (i = 0; i < x->x_num; ++i) {
438 post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]);
439 MyStrCopy(endOfPrefix, x->x_prefixes[i]);
440 SETSYMBOL(a, gensym(prefixBuf));
441 outlet_anything(x->x_outlets[i], s, 1, a);
442 }
443}
444
445
446/* --------------------------------------------------- */
447
448
449
450static const char *theWholePattern; /* Just for warning messages */
451
452static Boolean MatchBrackets (const char *pattern, const char *test);
453static Boolean MatchList (const char *pattern, const char *test);
454
455Boolean PatternMatch (const char * pattern, const char * test) {
456 theWholePattern = pattern;
457
458 if (pattern == 0 || pattern[0] == 0) {
459 return test[0] == 0;
460 }
461
462 if (test[0] == 0) {
463 if (pattern[0] == '*')
464 return PatternMatch (pattern+1,test);
465 else
466 return FALSE;
467 }
468
469 switch (pattern[0]) {
470 case 0 : return test[0] == 0;
471 case '?' : return PatternMatch (pattern + 1, test + 1);
472 case '*' :
473 if (PatternMatch (pattern+1, test)) {
474 return TRUE;
475 } else {
476 return PatternMatch (pattern, test+1);
477 }
478 case ']' :
479 case '}' :
480 OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
481 return FALSE;
482 case '[' :
483 return MatchBrackets (pattern,test);
484 case '{' :
485 return MatchList (pattern,test);
486 case '\\' :
487 if (pattern[1] == 0) {
488 return test[0] == 0;
489 } else if (pattern[1] == test[0]) {
490 return PatternMatch (pattern+2,test+1);
491 } else {
492 return FALSE;
493 }
494 default :
495 if (pattern[0] == test[0]) {
496 return PatternMatch (pattern+1,test+1);
497 } else {
498 return FALSE;
499 }
500 }
501}
502
503
504/* we know that pattern[0] == '[' and test[0] != 0 */
505
506static Boolean MatchBrackets (const char *pattern, const char *test) {
507 Boolean result;
508 Boolean negated = FALSE;
509 const char *p = pattern;
510
511 if (pattern[1] == 0) {
512 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
513 return FALSE;
514 }
515
516 if (pattern[1] == '!') {
517 negated = TRUE;
518 p++;
519 }
520
521 while (*p != ']') {
522 if (*p == 0) {
523 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
524 return FALSE;
525 }
526 if (p[1] == '-' && p[2] != 0) {
527 if (test[0] >= p[0] && test[0] <= p[2]) {
528 result = !negated;
529 goto advance;
530 }
531 }
532 if (p[0] == test[0]) {
533 result = !negated;
534 goto advance;
535 }
536 p++;
537 }
538
539 result = negated;
540
541advance:
542
543 if (!result)
544 return FALSE;
545
546 while (*p != ']') {
547 if (*p == 0) {
548 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
549 return FALSE;
550 }
551 p++;
552 }
553
554 return PatternMatch (p+1,test+1);
555}
556
557static Boolean MatchList (const char *pattern, const char *test) {
558
559 const char *restOfPattern, *tp = test;
560
561
562 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
563 if (*restOfPattern == 0) {
564 OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern);
565 return FALSE;
566 }
567 }
568
569 restOfPattern++; /* skip close curly brace */
570
571
572 pattern++; /* skip open curly brace */
573
574 while (1) {
575
576 if (*pattern == ',') {
577 if (PatternMatch (restOfPattern, tp)) {
578 return TRUE;
579 } else {
580 tp = test;
581 ++pattern;
582 }
583 } else if (*pattern == '}') {
584 return PatternMatch (restOfPattern, tp);
585 } else if (*pattern == *tp) {
586 ++pattern;
587 ++tp;
588 } else {
589 tp = test;
590 while (*pattern != ',' && *pattern != '}') {
591 pattern++;
592 }
593 if (*pattern == ',') {
594 pattern++;
595 }
596 }
597 }
598
599}
600
601
602
603/*
604Written by Adrian Freed, The Center for New Music and Audio Technologies,
605University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04
606The Regents of the University of California (Regents).
607
608Permission to use, copy, modify, distribute, and distribute modified versions
609of this software and its documentation without fee and without a signed
610licensing agreement, is hereby granted, provided that the above copyright
611notice, this paragraph and the following two paragraphs appear in all copies,
612modifications, and distributions.
613
614IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
615SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
616OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
617BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
618
619REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
620THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
621PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
622HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
623MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
624
625
626The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
627*/
628
629 /* OSC-route.c
630 Max object for OSC-style dispatching
631
632 To-do:
633
634 Match a pattern against a pattern?
635 Declare outlet types / distinguish leaf nodes from other children
636 More sophisticated (2-pass?) allmessages scheme
637 set message?
638
639
640 pd
641 -------------
642 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
643
644
645 */
646
647#ifdef WIN32
648 #include <stdlib.h>
649 #include <string.h>
650#endif
651#ifdef __APPLE__
652 #include <stdio.h>
653#endif
654#ifdef UNIX
655 #include <stdio.h>
656#endif
657
658/* structure definition of your object */
659
660#define MAX_NUM 20
661#define OSC_ROUTE_VERSION "1.05"
662#define OSCWarning(x...) post(x)
663
664/* the required include files */
665#include "m_pd.h"
666
667
668#ifndef TRUE
669typedef int Boolean;
670#define TRUE 1
671#define FALSE 0
672#endif
673
674
675/* Fixed byte width types */
676typedef int int4; /* 4 byte int */
677
678Boolean PatternMatch (const char *pattern, const char *test);
679
680
681
682/* Version 1.04: Allows #1 thru #9 as typed-in arguments
683 Version 1.05: Allows "list" messages as well as "message" messages.
684*/
685
686static t_class *OSCroute_class;
687
688typedef struct _OSCroute
689{
690 t_object x_obj; // required header
691 t_int x_num; // Number of address prefixes we store
692 t_int x_complainmode; // Do we print a message if no match?
693 t_int x_sendmode; // use pd internal sends instead of outlets
694 char *x_prefixes[MAX_NUM];
695 void *x_outlets[MAX_NUM+1];
696} t_OSCroute;
697
698t_symbol *ps_list, *ps_complain, *ps_emptySymbol;
699
700/* prototypes */
701
702void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
703void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
704void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
705/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */
706void *OSCroute_new(t_symbol *s, int argc, t_atom *argv);
707void OSCroute_version (t_OSCroute *x);
708/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */
709/* char *dstString); */
710void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
711
712static char *NextSlashOrNull(char *p);
713static void StrCopyUntilSlash(char *target, const char *source);
714
715
716// free
717static void OSCroute_free(t_OSCroute *x)
718{
719 // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
720}
721
722/* initialization routine */
723
724// setup
725#ifdef WIN32
726 OSC_API void OSCroute_setup(void) {
727#else
728void OSCroute_setup(void) {
729#endif
730 OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new,
731 (t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0);
732 class_addlist(OSCroute_class, OSCroute_list);
733 class_addanything(OSCroute_class, OSCroute_anything);
734 class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0);
735 class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd"));
736
737 /*
738 class_addmethod(OSCroute_class, (t_method)OSCroute_connect,
739 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
740 class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect,
741 gensym("disconnect"), 0);
742 class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"),
743 A_GIMME, 0);
744 */
745/* ps_list = gensym("list"); */
746/* ps_complain = gensym("complain"); */
747 ps_emptySymbol = gensym("");
748
749 post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf.");
750 post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved.");
751}
752
753
754
755/* instance creation routine */
756
757void *OSCroute_new(t_symbol *s, int argc, t_atom *argv)
758{
759
760 t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize
761
762 int i; //{{raf}} n not used
763
764 // EnterCallback();
765
766 if (argc > MAX_NUM) {
767 post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM);
768 // ExitCallback();
769 return 0;
770 }
771
772 x->x_complainmode = 0;
773 x->x_num = 0;
774 for (i = 0; i < argc; ++i) {
775 if (argv[i].a_type == A_SYMBOL) {
776 if (argv[i].a_w.w_symbol->s_name[0] == '/') {
777 /* Now that's a nice prefix */
778 x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
779 ++(x->x_num);
780 } else if (argv[i].a_w.w_symbol->s_name[0] == '#' &&
781 argv[i].a_w.w_symbol->s_name[1] >= '1' &&
782 argv[i].a_w.w_symbol->s_name[1] <= '9') {
783 /* The Max programmer is trying to make a patch that will be
784 a subpatch with arguments. We have to make an outlet for this
785 argument. */
786 x->x_prefixes[i] = "dummy";
787 ++(x->x_num);
788 } else {
789 /* Maybe this is an option we support */
790
791/* if (argv[i].a_w.w_sym == ps_complain) { */
792/* x->x_complainmode = 1; */
793/* } else { */
794/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */
795/* } */
796
797 }
798
799 // no LONG
800
801/* } else if (argv[i].a_type == A_FLOAD) { */
802/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */
803/* char *string = getbytes(12); */
804/* // I can't be bothered to plug this 12 byte memory leak */
805/* if (string == 0) { */
806/* post("* OSC-route: out of memory!"); */
807/* // ExitCallback(); */
808/* return 0; */
809/* } */
810/* sprintf(string, "%d", argv[i].a_w.w_long); */
811/* x->x_prefixes[i] = string; */
812/* ++(x->x_num); */
813
814 } else if (argv[i].a_type == A_FLOAT) {
815 post("* OSC-route: float arguments are not OK.");
816 // ExitCallback();
817 return 0;
818 } else {
819 post("* OSC-route: unrecognized argument type!");
820 // ExitCallback();
821 return 0;
822 }
823 }
824
825
826 /* Have to create the outlets in reverse order */
827 /* well, not in pd ? */
828 // for (i = x->x_num-1; i >= 0; --i) {
829 // for (i = 0; i <= x->x_num-1; i++) {
830 for (i = 0; i <= x->x_num; i++) {
831 // x->x_outlets[i] = listout(x);
832 x->x_outlets[i] = outlet_new(&x->x_obj, &s_list);
833 }
834
835 // ExitCallback();
836 return (x);
837}
838
839
840void OSCroute_version (t_OSCroute *x) {
841 // EnterCallback();
842 post("OSCroute Version " OSC_ROUTE_VERSION
843 ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__);
844 // ExitCallback();
845}
846
847/* I don't know why these aren't defined in some Max #include file. */
848#define ASSIST_INLET 1
849#define ASSIST_OUTLET 2
850
851void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg,
852 char *dstString) {
853 // EnterCallback();
854
855 if (msg==ASSIST_INLET) {
856 sprintf(dstString, "Incoming OSC messages");
857 } else if (msg==ASSIST_OUTLET) {
858 if (arg < 0 || arg >= x->x_num) {
859 post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg);
860 } else {
861 sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]);
862 }
863 } else {
864 post("* OSCroute_assist: unrecognized message %ld", msg);
865 }
866
867 // ExitCallback();
868}
869
870void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
871 // EnterCallback();
872 if (argc > 0 && argv[0].a_type == A_SYMBOL) {
873 /* Ignore the fact that this is a "list" */
874 OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1);
875 } else {
876 // post("* OSC-route: invalid list beginning with a number");
877 // output on unmatched outlet jdl 20020908
878 if (argv[0].a_type == A_FLOAT) {
879 outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float);
880 } else {
881 post("* OSC-route: unrecognized atom type!");
882 }
883 }
884 // ExitCallback();
885}
886
887
888void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
889 // EnterCallback();
890 OSCroute_doanything(x, s, argc, argv);
891 // ExitCallback();
892}
893
894
895
896
897void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
898 char *pattern, *nextSlash;
899 int i;
900 int matchedAnything;
901 // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc);
902
903 pattern = s->s_name;
904 if (pattern[0] != '/') {
905 post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name);
906 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
907 return;
908 }
909
910 matchedAnything = 0;
911
912 nextSlash = NextSlashOrNull(pattern+1);
913 if (*nextSlash == '\0') {
914 /* last level of the address, so we'll output the argument list */
915
916
917#ifdef NULL_IS_DIFFERENT_FROM_BANG
918 if (argc==0) {
919 post("* OSC-route: why are you matching one level pattern %s with no args?",
920 pattern);
921 return;
922 }
923#endif
924
925 for (i = 0; i < x->x_num; ++i) {
926 if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) {
927 ++matchedAnything;
928
929 // I hate stupid Max lists with a special first element
930 if (argc == 0) {
931 outlet_bang(x->x_outlets[i]);
932 } else if (argv[0].a_type == A_SYMBOL) {
933 // Promote the symbol that was argv[0] to the special symbol
934 outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
935 } else if (argc > 1) {
936 // Multiple arguments starting with a number, so naturally we have
937 // to use a special function to output this "list", since it's what
938 // Max originally meant by "list".
939 outlet_list(x->x_outlets[i], 0L, argc, argv);
940 } else {
941 // There was only one argument, and it was a number, so we output it
942 // not as a list
943/* if (argv[0].a_type == A_LONG) { */
944
945/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */
946 // } else
947 if (argv[0].a_type == A_FLOAT) {
948
949 outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
950 } else {
951 post("* OSC-route: unrecognized atom type!");
952 }
953 }
954 }
955 }
956 } else {
957 /* There's more address after this part, so our output list will begin with
958 the next slash. */
959 t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
960 char patternBegin[1000];
961
962
963 /* Get the first level of the incoming pattern to match against all our prefixes */
964 StrCopyUntilSlash(patternBegin, pattern+1);
965
966 for (i = 0; i < x->x_num; ++i) {
967 if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) {
968 ++matchedAnything;
969 if (restOfPattern == 0) {
970 restOfPattern = gensym(nextSlash);
971 }
972 outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
973 }
974 }
975 }
976
977 if (x->x_complainmode) {
978 if (!matchedAnything) {
979 post("* OSC-route: pattern %s did not match any prefixes", pattern);
980 }
981 }
982
983 // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
984 if (!matchedAnything) {
985 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
986 }
987
988
989}
990
991static char *NextSlashOrNull(char *p) {
992 while (*p != '/' && *p != '\0') {
993 p++;
994 }
995 return p;
996}
997
998static void StrCopyUntilSlash(char *target, const char *source) {
999 while (*source != '/' && *source != '\0') {
1000 *target = *source;
1001 ++target;
1002 ++source;
1003 }
1004 *target = 0;
1005}
1006
1007static int MyStrCopy(char *target, const char *source) {
1008 int i = 0;
1009 while (*source != '\0') {
1010 *target = *source;
1011 ++target;
1012 ++source;
1013 ++i;
1014 }
1015 *target = 0;
1016 return i;
1017}
1018
1019
1020
1021void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
1022 int i;
1023 t_symbol *prefixSymbol = 0;
1024 char prefixBuf[1000];
1025 char *endOfPrefix;
1026 t_atom a[1];
1027
1028 if (argc >= 1 && argv[0].a_type == A_SYMBOL) {
1029 prefixSymbol = argv[0].a_w.w_symbol;
1030 endOfPrefix = prefixBuf + MyStrCopy(prefixBuf,
1031 prefixSymbol->s_name);
1032 } else {
1033 prefixSymbol = ps_emptySymbol;
1034 prefixBuf[0] = '\0';
1035 endOfPrefix = prefixBuf;
1036 }
1037
1038
1039 for (i = 0; i < x->x_num; ++i) {
1040 post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]);
1041 MyStrCopy(endOfPrefix, x->x_prefixes[i]);
1042 SETSYMBOL(a, gensym(prefixBuf));
1043 outlet_anything(x->x_outlets[i], s, 1, a);
1044 }
1045}
1046
1047
1048/* --------------------------------------------------- */
1049
1050
1051
1052static const char *theWholePattern; /* Just for warning messages */
1053
1054static Boolean MatchBrackets (const char *pattern, const char *test);
1055static Boolean MatchList (const char *pattern, const char *test);
1056
1057Boolean PatternMatch (const char * pattern, const char * test) {
1058 theWholePattern = pattern;
1059
1060 if (pattern == 0 || pattern[0] == 0) {
1061 return test[0] == 0;
1062 }
1063
1064 if (test[0] == 0) {
1065 if (pattern[0] == '*')
1066 return PatternMatch (pattern+1,test);
1067 else
1068 return FALSE;
1069 }
1070
1071 switch (pattern[0]) {
1072 case 0 : return test[0] == 0;
1073 case '?' : return PatternMatch (pattern + 1, test + 1);
1074 case '*' :
1075 if (PatternMatch (pattern+1, test)) {
1076 return TRUE;
1077 } else {
1078 return PatternMatch (pattern, test+1);
1079 }
1080 case ']' :
1081 case '}' :
1082 OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
1083 return FALSE;
1084 case '[' :
1085 return MatchBrackets (pattern,test);
1086 case '{' :
1087 return MatchList (pattern,test);
1088 case '\\' :
1089 if (pattern[1] == 0) {
1090 return test[0] == 0;
1091 } else if (pattern[1] == test[0]) {
1092 return PatternMatch (pattern+2,test+1);
1093 } else {
1094 return FALSE;
1095 }
1096 default :
1097 if (pattern[0] == test[0]) {
1098 return PatternMatch (pattern+1,test+1);
1099 } else {
1100 return FALSE;
1101 }
1102 }
1103}
1104
1105
1106/* we know that pattern[0] == '[' and test[0] != 0 */
1107
1108static Boolean MatchBrackets (const char *pattern, const char *test) {
1109 Boolean result;
1110 Boolean negated = FALSE;
1111 const char *p = pattern;
1112
1113 if (pattern[1] == 0) {
1114 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
1115 return FALSE;
1116 }
1117
1118 if (pattern[1] == '!') {
1119 negated = TRUE;
1120 p++;
1121 }
1122
1123 while (*p != ']') {
1124 if (*p == 0) {
1125 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
1126 return FALSE;
1127 }
1128 if (p[1] == '-' && p[2] != 0) {
1129 if (test[0] >= p[0] && test[0] <= p[2]) {
1130 result = !negated;
1131 goto advance;
1132 }
1133 }
1134 if (p[0] == test[0]) {
1135 result = !negated;
1136 goto advance;
1137 }
1138 p++;
1139 }
1140
1141 result = negated;
1142
1143advance:
1144
1145 if (!result)
1146 return FALSE;
1147
1148 while (*p != ']') {
1149 if (*p == 0) {
1150 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
1151 return FALSE;
1152 }
1153 p++;
1154 }
1155
1156 return PatternMatch (p+1,test+1);
1157}
1158
1159static Boolean MatchList (const char *pattern, const char *test) {
1160
1161 const char *restOfPattern, *tp = test;
1162
1163
1164 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
1165 if (*restOfPattern == 0) {
1166 OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern);
1167 return FALSE;
1168 }
1169 }
1170
1171 restOfPattern++; /* skip close curly brace */
1172
1173
1174 pattern++; /* skip open curly brace */
1175
1176 while (1) {
1177
1178 if (*pattern == ',') {
1179 if (PatternMatch (restOfPattern, tp)) {
1180 return TRUE;
1181 } else {
1182 tp = test;
1183 ++pattern;
1184 }
1185 } else if (*pattern == '}') {
1186 return PatternMatch (restOfPattern, tp);
1187 } else if (*pattern == *tp) {
1188 ++pattern;
1189 ++tp;
1190 } else {
1191 tp = test;
1192 while (*pattern != ',' && *pattern != '}') {
1193 pattern++;
1194 }
1195 if (*pattern == ',') {
1196 pattern++;
1197 }
1198 }
1199 }
1200
1201}
1202
1203
1204
diff --git a/apps/plugins/pdbox/PDa/extra/README b/apps/plugins/pdbox/PDa/extra/README
new file mode 100644
index 0000000000..6e0b4a1e67
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/README
@@ -0,0 +1,24 @@
1PDa - externals
2===============
3
4This is a collection of selected externals for PDa. The externals are
5all copyright by their authors, check out the copyright notice in
6each of the files.
7
8I have changed some of the files a bit, so the bugs are most likely my
9fault. Send feedback and wishes to
10
11geiger <AT> xdv dot org
12
13PDa - externals
14===============
15
16This is a collection of selected externals for PDa. The externals are
17all copyright by their authors, check out the copyright notice in
18each of the files.
19
20I have changed some of the files a bit, so the bugs are most likely my
21fault. Send feedback and wishes to
22
23geiger <AT> xdv dot org
24
diff --git a/apps/plugins/pdbox/PDa/extra/bandpass-help.pd b/apps/plugins/pdbox/PDa/extra/bandpass-help.pd
new file mode 100644
index 0000000000..65d41eafad
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/bandpass-help.pd
@@ -0,0 +1,34 @@
1#N canvas 428 285 240 300 8;
2#X obj 24 78 noise~;
3#X obj 15 215 dac~;
4#X obj 24 167 biquad~;
5#X floatatom 67 76 5 0 0 0 - - -;
6#X floatatom 83 111 5 0 0 0 - - -;
7#X obj 67 138 bandpass 600 10;
8#X text 77 97 bandwidth: 100 = 1 octave;
9#X text 67 58 frequency;
10#X text 8 11 Calculation of biquad coefficients;
11#X text 7 21 ==================================;
12#X connect 0 0 2 0;
13#X connect 2 0 1 0;
14#X connect 2 0 1 1;
15#X connect 3 0 5 0;
16#X connect 4 0 5 1;
17#X connect 5 0 2 0;
18#N canvas 428 285 240 300 8;
19#X obj 24 78 noise~;
20#X obj 15 215 dac~;
21#X obj 24 167 biquad~;
22#X floatatom 67 76 5 0 0 0 - - -;
23#X floatatom 83 111 5 0 0 0 - - -;
24#X obj 67 138 bandpass 600 10;
25#X text 77 97 bandwidth: 100 = 1 octave;
26#X text 67 58 frequency;
27#X text 8 11 Calculation of biquad coefficients;
28#X text 7 21 ==================================;
29#X connect 0 0 2 0;
30#X connect 2 0 1 0;
31#X connect 2 0 1 1;
32#X connect 3 0 5 0;
33#X connect 4 0 5 1;
34#X connect 5 0 2 0;
diff --git a/apps/plugins/pdbox/PDa/extra/bandpass.c b/apps/plugins/pdbox/PDa/extra/bandpass.c
new file mode 100644
index 0000000000..6de56d6174
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/bandpass.c
@@ -0,0 +1,172 @@
1
2/* (C) Guenter Geiger <geiger@epy.co.at> */
3
4
5/*
6
7 These filter coefficients computations are taken from
8 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
9
10 written by Robert Bristow-Johnson
11
12*/
13
14#include "m_pd.h"
15#ifdef NT
16#pragma warning( disable : 4244 )
17#pragma warning( disable : 4305 )
18#endif
19#include <math.h>
20#include "filters.h"
21
22/* ------------------- bandpass ----------------------------*/
23
24static t_class *bandpass_class;
25
26void bandpass_bang(t_rbjfilter *x)
27{
28 t_atom at[5];
29 t_float omega = e_omega(x->x_freq,x->x_rate);
30 t_float alpha = e_alpha(x->x_bw* 0.01,omega);
31 t_float b1 = 0.;
32 t_float b0 = alpha;
33 t_float b2 = -alpha;
34 t_float a0 = 1 + alpha;
35 t_float a1 = -2.*cos(omega);
36 t_float a2 = 1 - alpha;
37
38/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
39
40 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
41 post("bandpass: filter unstable -> resetting");
42 a0=1.;a1=0.;a2=0.;
43 b0=1.;b1=0.;b2=0.;
44 }
45
46 SETFLOAT(at,-a1/a0);
47 SETFLOAT(at+1,-a2/a0);
48 SETFLOAT(at+2,b0/a0);
49 SETFLOAT(at+3,b1/a0);
50 SETFLOAT(at+4,b2/a0);
51
52 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
53}
54
55
56void bandpass_float(t_rbjfilter *x,t_floatarg f)
57{
58 x->x_freq = f;
59 bandpass_bang(x);
60}
61
62
63static void *bandpass_new(t_floatarg f,t_floatarg bw)
64{
65 t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class);
66
67 x->x_rate = 44100.0;
68 outlet_new(&x->x_obj,&s_float);
69/* floatinlet_new(&x->x_obj, &x->x_gain); */
70 floatinlet_new(&x->x_obj, &x->x_bw);
71 if (f > 0.) x->x_freq = f;
72 if (bw > 0.) x->x_bw = bw;
73 return (x);
74}
75
76
77void bandpass_setup(void)
78{
79 bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0,
80 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
81 class_addbang(bandpass_class,bandpass_bang);
82 class_addfloat(bandpass_class,bandpass_float);
83}
84
85
86
87
88/* (C) Guenter Geiger <geiger@epy.co.at> */
89
90
91/*
92
93 These filter coefficients computations are taken from
94 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
95
96 written by Robert Bristow-Johnson
97
98*/
99
100#include "m_pd.h"
101#ifdef NT
102#pragma warning( disable : 4244 )
103#pragma warning( disable : 4305 )
104#endif
105#include <math.h>
106#include "filters.h"
107
108/* ------------------- bandpass ----------------------------*/
109
110static t_class *bandpass_class;
111
112void bandpass_bang(t_rbjfilter *x)
113{
114 t_atom at[5];
115 t_float omega = e_omega(x->x_freq,x->x_rate);
116 t_float alpha = e_alpha(x->x_bw* 0.01,omega);
117 t_float b1 = 0.;
118 t_float b0 = alpha;
119 t_float b2 = -alpha;
120 t_float a0 = 1 + alpha;
121 t_float a1 = -2.*cos(omega);
122 t_float a2 = 1 - alpha;
123
124/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
125
126 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
127 post("bandpass: filter unstable -> resetting");
128 a0=1.;a1=0.;a2=0.;
129 b0=1.;b1=0.;b2=0.;
130 }
131
132 SETFLOAT(at,-a1/a0);
133 SETFLOAT(at+1,-a2/a0);
134 SETFLOAT(at+2,b0/a0);
135 SETFLOAT(at+3,b1/a0);
136 SETFLOAT(at+4,b2/a0);
137
138 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
139}
140
141
142void bandpass_float(t_rbjfilter *x,t_floatarg f)
143{
144 x->x_freq = f;
145 bandpass_bang(x);
146}
147
148
149static void *bandpass_new(t_floatarg f,t_floatarg bw)
150{
151 t_rbjfilter *x = (t_rbjfilter *)pd_new(bandpass_class);
152
153 x->x_rate = 44100.0;
154 outlet_new(&x->x_obj,&s_float);
155/* floatinlet_new(&x->x_obj, &x->x_gain); */
156 floatinlet_new(&x->x_obj, &x->x_bw);
157 if (f > 0.) x->x_freq = f;
158 if (bw > 0.) x->x_bw = bw;
159 return (x);
160}
161
162
163void bandpass_setup(void)
164{
165 bandpass_class = class_new(gensym("bandpass"), (t_newmethod)bandpass_new, 0,
166 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
167 class_addbang(bandpass_class,bandpass_bang);
168 class_addfloat(bandpass_class,bandpass_float);
169}
170
171
172
diff --git a/apps/plugins/pdbox/PDa/extra/dumpOSC.c b/apps/plugins/pdbox/PDa/extra/dumpOSC.c
new file mode 100644
index 0000000000..37767c2b03
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/dumpOSC.c
@@ -0,0 +1,1998 @@
1/*
2Written by Matt Wright and Adrian Freed, The Center for New Music and
3Audio Technologies, University of California, Berkeley. Copyright (c)
41992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of
5California (Regents).
6
7Permission to use, copy, modify, distribute, and distribute modified versions
8of this software and its documentation without fee and without a signed
9licensing agreement, is hereby granted, provided that the above copyright
10notice, this paragraph and the following two paragraphs appear in all copies,
11modifications, and distributions.
12
13IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
14SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
15OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
16BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17
18REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
21HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
22MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23
24
25The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
26*/
27
28
29 /*
30
31 dumpOSC.c
32 server that displays OpenSoundControl messages sent to it
33 for debugging client udp and UNIX protocol
34
35 by Matt Wright, 6/3/97
36 modified from dumpSC.c, by Matt Wright and Adrian Freed
37
38 version 0.2: Added "-silent" option a.k.a. "-quiet"
39
40 version 0.3: Incorporated patches from Nicola Bernardini to make
41 things Linux-friendly. Also added ntohl() in the right places
42 to support little-endian architectures.
43
44
45
46 compile:
47 cc -o dumpOSC dumpOSC.c
48
49 to-do:
50
51 More robustness in saying exactly what's wrong with ill-formed
52 messages. (If they don't make sense, show exactly what was
53 received.)
54
55 Time-based features: print time-received for each packet
56
57 Clean up to separate OSC parsing code from socket/select stuff
58
59 pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c
60 -------------
61 -- added pd functions
62 -- socket is made differently than original via pd mechanisms
63 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
64 -- the OSX changes from cnmat didnt make it here yet but this compiles
65 on OSX anyway.
66
67*/
68
69#if HAVE_CONFIG_H
70#include <config.h>
71#endif
72
73#include "m_pd.h"
74//#include "m_imp.h"
75#include "s_stuff.h"
76
77/* declarations */
78
79// typedef void (*t_fdpollfn)(void *ptr, int fd);
80void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
81
82
83#if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__)
84
85#ifdef WIN32
86 #include "OSC-common.h"
87 #include <winsock2.h>
88 #include <string.h>
89 #include <stdlib.h>
90 #include <fcntl.h>
91 #include <sys/types.h>
92 #include <sys/stat.h>
93 #include <ctype.h>
94 #include <signal.h>
95#else
96 #include <stdio.h>
97 #include <string.h>
98 #include <stdlib.h>
99 #include <unistd.h>
100 #include <fcntl.h>
101 #include <sys/types.h>
102 #include <sys/stat.h>
103 #include <netinet/in.h>
104 #include <rpc/rpc.h>
105 #include <sys/socket.h>
106 #include <sys/un.h>
107 #include <sys/times.h>
108 #include <sys/param.h>
109 #include <sys/time.h>
110 #include <sys/ioctl.h>
111 #include <ctype.h>
112 #include <arpa/inet.h>
113 #include <netdb.h>
114 #include <pwd.h>
115 #include <signal.h>
116 #include <grp.h>
117 #include <sys/file.h>
118 //#include <sys/prctl.h>
119
120 #ifdef NEED_SCHEDCTL_AND_LOCK
121 #include <sys/schedctl.h>
122 #include <sys/lock.h>
123 #endif
124#endif
125
126
127char *htm_error_string;
128typedef int Boolean;
129typedef void *OBJ;
130
131typedef struct ClientAddressStruct {
132 struct sockaddr_in cl_addr;
133 int clilen;
134 int sockfd;
135} *ClientAddr;
136
137typedef unsigned long long osc_time_t;
138
139Boolean ShowBytes = FALSE;
140Boolean Silent = FALSE;
141
142/* Declarations */
143#ifndef WIN32
144static int unixinitudp(int chan);
145#endif
146
147static int initudp(int chan);
148static void closeudp(int sockfd);
149Boolean ClientReply(int packetsize, void *packet, int socketfd,
150 void *clientaddresspointer, int clientaddressbufferlength);
151void sgi_CleanExit(void);
152Boolean sgi_HaveToQuit(void);
153int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy);
154static void catch_sigint();
155static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ;
156char *DataAfterAlignedString(char *string, char *boundary) ;
157Boolean IsNiceString(char *string, char *boundary) ;
158void complain(char *s, ...);
159
160#define MAXMESG 32768
161static char mbuf[MAXMESG];
162
163/* ----------------------------- dumpOSC ------------------------- */
164
165#define MAXOUTAT 50
166
167static t_class *dumpOSC_class;
168
169typedef struct _dumpOSC
170{
171 t_object x_obj;
172 t_outlet *x_msgout;
173 t_outlet *x_connectout;
174 t_atom x_outat[MAXOUTAT];
175 int x_outatc;
176 t_binbuf *x_b;
177 int x_connectsocket;
178 int x_nconnections;
179 int x_udp;
180 struct sockaddr_in x_server;
181 int x_clilen;
182} t_dumpOSC;
183
184void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr);
185Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd);
186static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr);
187static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n);
188static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma);
189
190static void dumpOSC_read(t_dumpOSC *x, int sockfd) {
191 int clilen = x->x_clilen;
192 int n;
193 struct ClientAddressStruct ras;
194 ClientAddr ra = &ras;
195
196 //catchupflag= FALSE;
197
198/* if (ShowBytes) { */
199/* int i; */
200/* printf("%d byte message:\n", n); */
201/* for (i = 0; i < n; ++i) { */
202/* printf(" %x (%c)\t", m[i], m[i]); */
203/* if (i%4 == 3) printf("\n"); */
204/* } */
205/* printf("\n"); */
206/* } */
207
208 // return catchupflag;
209 //struct sockaddr_in x->x_server;
210 //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0)
211 // while((
212
213 #ifdef WIN32
214 if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0)
215 #else
216 if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0)
217 #endif
218 {
219 //int r;
220 ras.cl_addr = *((struct sockaddr_in *) &x->x_server);
221 ras.clilen = x->x_clilen;
222 ras.sockfd = x->x_connectsocket;
223
224 #ifdef DEBUG
225 printf("dumpOSC_read: received UDP packet of length %d\n", n);
226 #endif
227
228 if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd))
229 {
230 dumpOSC_ParsePacket(x, mbuf, n, ra);
231 }
232 //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd);
233 //post ("%d", r);
234 //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
235 // emsg-msg-1, at + msg + 1);
236 // outlet_list(x->x_msgout, 0, n, mbuf);
237 //if( sgi_HaveToQuit()) goto out;
238 //if(r>0) goto back;
239 //clilen = maxclilen;
240 }
241}
242
243static void *dumpOSC_new(t_symbol *compatflag,
244 t_floatarg fportno) {
245 t_dumpOSC *x;
246 struct sockaddr_in server;
247 int clilen=sizeof(server);
248 int sockfd;
249 int portno=fportno;
250 int udp = 1;
251
252 //x->x_b = binbuf_new();
253 //x->x_outat = binbuf_getvec(x->x_b);
254
255 //{{raf}} pointer not valid yet...moving this down
256 //x->x_outatc = 0; {{raf}}
257
258 /* create a socket */
259 if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1)
260 {
261 sys_sockerror("socket");
262 return (0);
263 }
264
265 server.sin_family = AF_INET;
266 server.sin_addr.s_addr = INADDR_ANY;
267 /* assign server port number */
268 server.sin_port = htons((u_short)portno);
269 /* name the socket */
270 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
271 {
272 sys_sockerror("bind");
273 sys_closesocket(sockfd);
274 return (0);
275 }
276
277 x = (t_dumpOSC *)pd_new(dumpOSC_class);
278 x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid)
279
280 x->x_msgout = outlet_new(&x->x_obj, &s_anything);
281
282 // if (udp) /* datagram protocol */
283 {
284
285 sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x);
286 x->x_connectout = 0;
287 }
288 // else /* streaming protocol */
289 /* { */
290 /* if (listen(sockfd, 5) < 0) */
291 /* { */
292 /* sys_sockerror("listen"); */
293 /* sys_closesocket(sockfd); */
294 /* sockfd = -1; */
295 /* } */
296 /* else */
297 /* { */
298 /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */
299 /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */
300 /* } */
301 /* } */
302
303 x->x_connectsocket = sockfd;
304 x->x_server = server;
305 x->x_clilen = clilen;
306 x->x_nconnections = 0;
307 x->x_udp = udp;
308
309 return (x);
310}
311
312static void dumpOSC_free(t_dumpOSC *x)
313{
314 /* LATER make me clean up open connections */
315 if (x->x_connectsocket >= 0)
316 {
317 sys_rmpollfn(x->x_connectsocket);
318 sys_closesocket(x->x_connectsocket);
319 }
320}
321
322#ifdef WIN32
323OSC_API void dumpOSC_setup(void)
324#else
325void dumpOSC_setup(void)
326#endif
327{
328 dumpOSC_class = class_new(gensym("dumpOSC"),
329 (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free,
330 sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT,
331 A_DEFSYM, 0);
332 class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd"));
333}
334
335
336#ifndef WIN32
337 #define UNIXDG_PATH "/tmp/htm"
338 #define UNIXDG_TMP "/tmp/htm.XXXXXX"
339 static int unixinitudp(int chan)
340 {
341 struct sockaddr_un serv_addr;
342 int sockfd;
343
344 if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
345 return sockfd;
346
347 bzero((char *)&serv_addr, sizeof(serv_addr));
348 serv_addr.sun_family = AF_UNIX;
349 strcpy(serv_addr.sun_path, UNIXDG_PATH);
350 sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan);
351 unlink(serv_addr.sun_path);
352 if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0)
353 {
354 perror("unable to bind\n");
355 return -1;
356 }
357
358 fcntl(sockfd, F_SETFL, FNDELAY);
359 return sockfd;
360 }
361#endif // #ifndef WIN32
362
363
364
365static int initudp(int chan)
366{
367
368#ifdef WIN32
369 struct sockaddr_in serv_addr;
370 unsigned int sockfd;
371 ULONG nonBlocking = (ULONG) TRUE;
372
373 if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) {
374 ZeroMemory((char *)&serv_addr, sizeof(serv_addr));
375 serv_addr.sin_family = AF_INET;
376 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
377 serv_addr.sin_port = htons(chan);
378 if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) {
379 // set for non-blocking mode
380 if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) {
381 perror("unable to set non-blocking\n");
382 return -1;
383 }
384 }
385 else { perror("unable to bind\n"); return -1; }
386 }
387 return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd);
388#else
389 struct sockaddr_in serv_addr;
390 int sockfd;
391
392 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
393 return sockfd;
394
395 bzero((char *)&serv_addr, sizeof(serv_addr));
396 serv_addr.sin_family = AF_INET;
397 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
398 serv_addr.sin_port = htons(chan);
399
400 if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
401 {
402 perror("unable to bind\n");
403 return -1;
404 }
405
406 fcntl(sockfd, F_SETFL, FNDELAY);
407 return sockfd;
408#endif
409}
410
411
412
413
414
415
416
417
418static void closeudp(int sockfd) {
419 #ifdef WIN32
420 closesocket(sockfd);
421 #else
422 close(sockfd);
423 #endif
424}
425
426static Boolean catchupflag=FALSE;
427Boolean ClientReply(int packetsize, void *packet, int socketfd,
428 void *clientaddresspointer, int clientaddressbufferlength)
429{
430 if(!clientaddresspointer) return FALSE;
431 catchupflag= TRUE;
432 return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength);
433}
434
435static Boolean exitflag= FALSE;
436void sgi_CleanExit(void) {
437 exitflag = TRUE;
438}
439
440Boolean sgi_HaveToQuit(void) {
441 return exitflag;
442}
443
444
445/* file descriptor poll table */
446static int npolldevs =0;
447typedef struct polldev
448{
449 int fd;
450 void (*callbackfunction)(int , void *);
451 void *dummy;
452} polldev;
453#define TABMAX 8
454static polldev polldevs[TABMAX];
455
456
457/* Register a device (referred to by a file descriptor that the caller
458 should have already successfully obtained from a system call) to be
459 polled as real-time constraints allowed.
460
461 When a select(2) call indicates activity on the file descriptor, the
462 callback function is called with the file descripter as first
463 argument and the given dummy argument (presumably a pointer to the
464 instance variables associated with the device).
465*/
466int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy)
467{
468 if(npolldevs<TABMAX)
469 {
470 polldevs[npolldevs].fd = fd;
471 polldevs[npolldevs].callbackfunction = callbackfunction;
472 polldevs[npolldevs].dummy = dummy;
473 }
474 else return -1;
475 return npolldevs++;
476}
477
478static int caught_sigint;
479
480static void catch_sigint() {
481 caught_sigint = 1;
482}
483static int sockfd, usockfd;
484
485
486void PrintClientAddr(ClientAddr CA) {
487 unsigned long addr = CA->cl_addr.sin_addr.s_addr;
488 printf("Client address %p:\n", CA);
489 printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd);
490 printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family,
491 CA->cl_addr.sin_port);
492 printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr));
493
494 printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n",
495 CA->cl_addr.sin_zero[0],
496 CA->cl_addr.sin_zero[1],
497 CA->cl_addr.sin_zero[2],
498 CA->cl_addr.sin_zero[3],
499 CA->cl_addr.sin_zero[4],
500 CA->cl_addr.sin_zero[5],
501 CA->cl_addr.sin_zero[6],
502 CA->cl_addr.sin_zero[7]);
503
504 printf("\n");
505}
506
507//*******************
508
509void WriteTime(char* dst, osc_time_t osctime)
510{
511 *(int32_t*)dst = htonl((int32_t)(osctime >> 32));
512 *(int32_t*)(dst+4) = htonl((int32_t)osctime);
513}
514
515void WriteMode(char* dst)
516{
517 *(int32_t*)dst = htonl(0);
518}
519
520osc_time_t ReadTime(const char* src)
521{
522 osc_time_t osctime = ntohl(*(int32_t*)src);
523 return (osctime << 32) + ntohl(*(int32_t*)(src+4));
524}
525
526double TimeToSeconds(osc_time_t osctime)
527{
528 return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */;
529}
530
531int timeRound(double x)
532{
533 return x >= 0.0 ? x+0.5 : x-0.5;
534}
535/*
536void WriteLogicalTime(char* dst)
537{
538 static double startTime = -1.0;
539 double sTime;
540
541 // Initialisierung der Startzeit.
542 // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren.
543 // Knnte wahrscheinlich auch 0.0 sein.
544 if (startTime < 0.0) {
545 startTime = clock_getlogicaltime();
546 }
547
548 sTime = clock_gettimesince(startTime) * 0.001;
549 *(int32_t*)dst = hton'K l((int32_t)sTime);
550 *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime));
551}
552*/
553
554void WriteLogicalTime(char* dst)
555{
556 double sTime = clock_gettimesince(19230720) / 1000.0;
557 double tau = sTime - timeRound(sTime);
558
559 //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau);
560
561 *(int32_t*)dst = htonl((int32_t)(sTime));
562 *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau));
563}
564
565Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd)
566{
567 if((n == 24) && (strcmp(buf, "#time") == 0))
568 {
569 osc_time_t t0, t1, t2;
570 double dt0, dt1, dt2;
571
572 WriteMode(buf+6);
573
574 t0 = ReadTime(buf+8);
575
576 WriteLogicalTime(buf+16);
577 t1 = ReadTime(buf+16); // reverse
578 dt0 = TimeToSeconds(t0); // client time
579 dt1 = TimeToSeconds(t1); // server time
580
581 // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1);
582
583 sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght);
584 return TRUE;
585 }
586 else
587 {
588 return FALSE;
589 }
590}
591
592//**********************
593
594void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) {
595 // t_dumpOSC *x;
596 int size, messageLen, i;
597 char *messageName;
598 char *args;
599
600 //#ifdef PRINTADDRS
601 #ifdef DEBUG
602 //PrintClientAddr(returnAddr);
603 #endif
604
605
606 if ((n%4) != 0) {
607 complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n);
608 return;
609 }
610
611 if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) {
612 /* This is a bundle message. */
613 #ifdef DEBUG
614 printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n");
615 #endif
616
617 if (n < 16) {
618 complain("Bundle message too small (%d bytes) for time tag", n);
619 return;
620 }
621
622 /* Print the time tag */
623 #ifdef DEBUG
624 printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12))));
625 #endif
626
627 /* Note: if we wanted to actually use the time tag as a little-endian
628 64-bit int, we'd have to word-swap the two 32-bit halves of it */
629
630 i = 16; /* Skip "#group\0" and time tag */
631
632 while(i<n) {
633 size = ntohl(*((int *) (buf + i)));
634 if ((size % 4) != 0) {
635 complain("Bad size count %d in bundle (not a multiple of 4)", size);
636 return;
637 }
638 if ((size + i + 4) > n) {
639 complain("Bad size count %d in bundle (only %d bytes left in entire bundle)",
640 size, n-i-4);
641 return;
642 }
643
644 /* Recursively handle element of bundle */
645 dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr);
646 i += 4 + size;
647 }
648
649 if (i != n) {
650 complain("This can't happen");
651 }
652 #ifdef DEBUG
653 printf("]\n");
654 #endif
655
656 }
657 else if ((n == 24) && (strcmp(buf, "#time") == 0))
658 {
659 complain("Time message: %s\n :).\n", htm_error_string);
660 return;
661
662 }
663 else
664 {
665 /* This is not a bundle message */
666
667 messageName = buf;
668 args = DataAfterAlignedString(messageName, buf+n);
669 if (args == 0) {
670 complain("Bad message name string: %s\nDropping entire message.\n",
671 htm_error_string);
672 return;
673 }
674 messageLen = args-messageName;
675 dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr);
676 }
677}
678
679#define SMALLEST_POSITIVE_FLOAT 0.000001f
680
681static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) {
682 char *chars = v;
683 t_atom at;
684 //t_atom myargv[50];
685
686 int myargc = x->x_outatc;
687 t_atom* mya = x->x_outat;
688 int myi;
689
690#ifdef DEBUG
691 printf("%s ", address);
692#endif
693
694 // ztoln+cvt from envgen.c, ggee-0.18 ..
695 // outlet_anything's 'symbol' gets set to address
696 // so we dont need to append address to the atomlist
697 /*
698 SETSYMBOL(mya,gensym(address));myargc++;
699 x->x_outatc = myargc;
700 */
701
702 if (n != 0) {
703 if (chars[0] == ',') {
704 if (chars[1] != ',') {
705 /* This message begins with a type-tag string */
706 dumpOSC_PrintTypeTaggedArgs(x, v, n);
707 } else {
708 /* Double comma means an escaped real comma, not a type string */
709 dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1);
710 }
711 } else {
712 dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0);
713 }
714 }
715
716 outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat);
717 x->x_outatc = 0;
718#ifdef DEBUG
719 printf("\n");
720#endif
721 fflush(stdout); /* Added for Sami 5/21/98 */
722}
723
724static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) {
725 char *typeTags, *thisType;
726 char *p;
727
728 int myargc = x->x_outatc;
729 t_atom* mya = x->x_outat;
730 int myi;
731
732 typeTags = v;
733
734 if (!IsNiceString(typeTags, typeTags+n)) {
735 /* No null-termination, so maybe it wasn't a type tag
736 string after all */
737 dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0);
738 return;
739 }
740
741 p = DataAfterAlignedString(typeTags, typeTags+n);
742
743
744 for (thisType = typeTags + 1; *thisType != 0; ++thisType) {
745 switch (*thisType) {
746 case 'i': case 'r': case 'm': case 'c':
747#ifdef DEBUG
748 //post("integer: %d", ntohl(*((int *) p)));
749#endif
750 /* Martin Peach fix for negative floats:
751 * was: SETFLOAT(mya+myargc,ntohl(*((int *) p)));
752 * now is:
753 */
754 SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p)));
755 myargc++;
756
757 p += 4;
758 break;
759
760 case 'f': {
761 int i = ntohl(*((int *) p));
762 float *floatp = ((float *) (&i));
763#ifdef DEBUG
764 post("float: %f", *floatp);
765#endif
766 SETFLOAT(mya+myargc,*floatp);
767 myargc++;
768
769 p += 4;
770 }
771 break;
772
773 case 'h': case 't':
774#ifdef DEBUG
775 printf("[A 64-bit int] ");
776#endif
777 post("[A 64-bit int] not implemented");
778
779 p += 8;
780 break;
781
782 case 'd':
783#ifdef DEBUG
784 printf("[A 64-bit float] ");
785#endif
786 post("[A 64-bit float] not implemented");
787
788 p += 8;
789 break;
790
791 case 's': case 'S':
792 if (!IsNiceString(p, typeTags+n)) {
793 post("Type tag said this arg is a string but it's not!\n");
794 return;
795 } else {
796#ifdef DEBUG
797 post("string: \"%s\"", p);
798#endif
799 SETSYMBOL(mya+myargc,gensym(p));
800 myargc++;
801 //outlet_list(x->x_msgout, 0,sizeof(p), p);
802 //outlet_anything(x->x_msgout, 0, sizeof(p), p);
803 p = DataAfterAlignedString(p, typeTags+n);
804 // append to output vector ..
805 }
806 break;
807
808 case 'T':
809#ifdef DEBUG
810 printf("[True] ");
811#endif
812 SETFLOAT(mya+myargc,1.);
813 myargc++;
814 break;
815 case 'F':
816#ifdef DEBUG
817 printf("[False] ");
818#endif
819 SETFLOAT(mya+myargc,0.);
820 myargc++;
821 break;
822 case 'N':
823#ifdef DEBUG
824 printf("[Nil]");
825#endif
826 post("sendOSC: [Nil] not implemented");
827 break;
828 case 'I':
829#ifdef DEBUG
830 printf("[Infinitum]");
831#endif
832 post("sendOSC: [Infinitum] not implemented");
833 break;
834
835 default:
836 post("sendOSC: [Unrecognized type tag %c]", *thisType);
837 // return;
838 }
839 }
840 x->x_outatc = myargc;
841}
842
843static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) {
844 int i, thisi;
845 float thisf;
846 int *ints;
847 char *chars;
848 char *string, *nextString;
849
850 int myargc= x->x_outatc;
851 t_atom* mya = x->x_outat;
852 int myi;
853
854
855 /* Go through the arguments 32 bits at a time */
856 ints = v;
857 chars = v;
858
859 for (i = 0; i<n/4; ) {
860 string = &chars[i*4];
861 thisi = ntohl(ints[i]);
862 /* Reinterpret the (potentially byte-reversed) thisi as a float */
863 thisf = *(((float *) (&thisi)));
864
865 if (thisi >= -1000 && thisi <= 1000000) {
866#ifdef DEBUG
867 printf("%d ", thisi);
868#endif
869 // append to output vector ..
870 SETFLOAT(mya+myargc,(t_float) (thisi));
871 myargc++;
872 // outlet_float(x->x_msgout, thisi);
873 i++;
874 } else if (thisf >= -1000.f && thisf <= 1000000.f &&
875 (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) {
876#ifdef DEBUG
877 printf("%f ", thisf);
878#endif
879 // append to output vector ..
880 SETFLOAT(mya+myargc,thisf);
881 myargc++;
882 //outlet_float(x->x_msgout, thisf);
883 i++;
884 } else if (IsNiceString(string, chars+n)) {
885 nextString = DataAfterAlignedString(string, chars+n);
886#ifdef DEBUG
887 printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string);
888#endif
889 // append to output vector ..
890 SETSYMBOL(mya+myargc,gensym(string));
891 myargc++;
892 //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string));
893 i += (nextString-string) / 4;
894 } else {
895 // unhandled .. ;)
896#ifdef DEBUG
897 printf("0x%x xx", ints[i]);
898#endif
899 i++;
900 }
901 x->x_outatc = myargc;
902 }
903}
904
905
906#define STRING_ALIGN_PAD 4
907
908char *DataAfterAlignedString(char *string, char *boundary)
909{
910 /* The argument is a block of data beginning with a string. The
911 string has (presumably) been padded with extra null characters
912 so that the overall length is a multiple of STRING_ALIGN_PAD
913 bytes. Return a pointer to the next byte after the null
914 byte(s). The boundary argument points to the character after
915 the last valid character in the buffer---if the string hasn't
916 ended by there, something's wrong.
917
918 If the data looks wrong, return 0, and set htm_error_string */
919
920 int i;
921
922 if ((boundary - string) %4 != 0) {
923 fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n");
924 return 0;
925 }
926
927 for (i = 0; string[i] != '\0'; i++) {
928 if (string + i >= boundary) {
929 htm_error_string = "DataAfterAlignedString: Unreasonably long string";
930 return 0;
931 }
932 }
933
934 /* Now string[i] is the first null character */
935 i++;
936
937 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
938 if (string + i >= boundary) {
939 htm_error_string = "DataAfterAlignedString: Unreasonably long string";
940 return 0;
941 }
942 if (string[i] != '\0') {
943 htm_error_string = "DataAfterAlignedString: Incorrectly padded string.";
944 return 0;
945 }
946 }
947
948 return string+i;
949}
950
951Boolean IsNiceString(char *string, char *boundary)
952{
953 /* Arguments same as DataAfterAlignedString(). Is the given "string"
954 really a string? I.e., is it a sequence of isprint() characters
955 terminated with 1-4 null characters to align on a 4-byte boundary? */
956
957 int i;
958
959 if ((boundary - string) %4 != 0) {
960 fprintf(stderr, "Internal error: IsNiceString: bad boundary\n");
961 return 0;
962 }
963
964 for (i = 0; string[i] != '\0'; i++) {
965 if (!isprint(string[i])) return FALSE;
966 if (string + i >= boundary) return FALSE;
967 }
968
969 /* If we made it this far, it's a null-terminated sequence of printing characters
970 in the given boundary. Now we just make sure it's null padded... */
971
972 /* Now string[i] is the first null character */
973 i++;
974 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
975 if (string[i] != '\0') return FALSE;
976 }
977
978 return TRUE;
979}
980
981
982
983
984
985
986
987
988
989#include <stdarg.h>
990void complain(char *s, ...) {
991 va_list ap;
992 va_start(ap, s);
993 fprintf(stderr, "*** ERROR: ");
994 vfprintf(stderr, s, ap);
995 fprintf(stderr, "\n");
996 va_end(ap);
997}
998
999#endif /* __sgi or LINUX or WIN32 */
1000/*
1001Written by Matt Wright and Adrian Freed, The Center for New Music and
1002Audio Technologies, University of California, Berkeley. Copyright (c)
10031992,93,94,95,96,97,98,99,2000,01,02,03,04 The Regents of the University of
1004California (Regents).
1005
1006Permission to use, copy, modify, distribute, and distribute modified versions
1007of this software and its documentation without fee and without a signed
1008licensing agreement, is hereby granted, provided that the above copyright
1009notice, this paragraph and the following two paragraphs appear in all copies,
1010modifications, and distributions.
1011
1012IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
1013SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
1014OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
1015BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1016
1017REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1018THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1019PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
1020HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
1021MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1022
1023
1024The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
1025*/
1026
1027
1028 /*
1029
1030 dumpOSC.c
1031 server that displays OpenSoundControl messages sent to it
1032 for debugging client udp and UNIX protocol
1033
1034 by Matt Wright, 6/3/97
1035 modified from dumpSC.c, by Matt Wright and Adrian Freed
1036
1037 version 0.2: Added "-silent" option a.k.a. "-quiet"
1038
1039 version 0.3: Incorporated patches from Nicola Bernardini to make
1040 things Linux-friendly. Also added ntohl() in the right places
1041 to support little-endian architectures.
1042
1043
1044
1045 compile:
1046 cc -o dumpOSC dumpOSC.c
1047
1048 to-do:
1049
1050 More robustness in saying exactly what's wrong with ill-formed
1051 messages. (If they don't make sense, show exactly what was
1052 received.)
1053
1054 Time-based features: print time-received for each packet
1055
1056 Clean up to separate OSC parsing code from socket/select stuff
1057
1058 pd: branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/dumpOSC/dumpOSC.c
1059 -------------
1060 -- added pd functions
1061 -- socket is made differently than original via pd mechanisms
1062 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
1063 -- the OSX changes from cnmat didnt make it here yet but this compiles
1064 on OSX anyway.
1065
1066*/
1067
1068#if HAVE_CONFIG_H
1069#include <config.h>
1070#endif
1071
1072#include "m_pd.h"
1073//#include "m_imp.h"
1074#include "s_stuff.h"
1075
1076/* declarations */
1077
1078// typedef void (*t_fdpollfn)(void *ptr, int fd);
1079void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
1080
1081
1082#if defined(__sgi) || defined(__linux) || defined(WIN32) || defined(__APPLE__)
1083
1084#ifdef WIN32
1085 #include "OSC-common.h"
1086 #include <winsock2.h>
1087 #include <string.h>
1088 #include <stdlib.h>
1089 #include <fcntl.h>
1090 #include <sys/types.h>
1091 #include <sys/stat.h>
1092 #include <ctype.h>
1093 #include <signal.h>
1094#else
1095 #include <stdio.h>
1096 #include <string.h>
1097 #include <stdlib.h>
1098 #include <unistd.h>
1099 #include <fcntl.h>
1100 #include <sys/types.h>
1101 #include <sys/stat.h>
1102 #include <netinet/in.h>
1103 #include <rpc/rpc.h>
1104 #include <sys/socket.h>
1105 #include <sys/un.h>
1106 #include <sys/times.h>
1107 #include <sys/param.h>
1108 #include <sys/time.h>
1109 #include <sys/ioctl.h>
1110 #include <ctype.h>
1111 #include <arpa/inet.h>
1112 #include <netdb.h>
1113 #include <pwd.h>
1114 #include <signal.h>
1115 #include <grp.h>
1116 #include <sys/file.h>
1117 //#include <sys/prctl.h>
1118
1119 #ifdef NEED_SCHEDCTL_AND_LOCK
1120 #include <sys/schedctl.h>
1121 #include <sys/lock.h>
1122 #endif
1123#endif
1124
1125
1126char *htm_error_string;
1127typedef int Boolean;
1128typedef void *OBJ;
1129
1130typedef struct ClientAddressStruct {
1131 struct sockaddr_in cl_addr;
1132 int clilen;
1133 int sockfd;
1134} *ClientAddr;
1135
1136typedef unsigned long long osc_time_t;
1137
1138Boolean ShowBytes = FALSE;
1139Boolean Silent = FALSE;
1140
1141/* Declarations */
1142#ifndef WIN32
1143static int unixinitudp(int chan);
1144#endif
1145
1146static int initudp(int chan);
1147static void closeudp(int sockfd);
1148Boolean ClientReply(int packetsize, void *packet, int socketfd,
1149 void *clientaddresspointer, int clientaddressbufferlength);
1150void sgi_CleanExit(void);
1151Boolean sgi_HaveToQuit(void);
1152int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy);
1153static void catch_sigint();
1154static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ;
1155char *DataAfterAlignedString(char *string, char *boundary) ;
1156Boolean IsNiceString(char *string, char *boundary) ;
1157void complain(char *s, ...);
1158
1159#define MAXMESG 32768
1160static char mbuf[MAXMESG];
1161
1162/* ----------------------------- dumpOSC ------------------------- */
1163
1164#define MAXOUTAT 50
1165
1166static t_class *dumpOSC_class;
1167
1168typedef struct _dumpOSC
1169{
1170 t_object x_obj;
1171 t_outlet *x_msgout;
1172 t_outlet *x_connectout;
1173 t_atom x_outat[MAXOUTAT];
1174 int x_outatc;
1175 t_binbuf *x_b;
1176 int x_connectsocket;
1177 int x_nconnections;
1178 int x_udp;
1179 struct sockaddr_in x_server;
1180 int x_clilen;
1181} t_dumpOSC;
1182
1183void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr);
1184Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd);
1185static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr);
1186static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n);
1187static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma);
1188
1189static void dumpOSC_read(t_dumpOSC *x, int sockfd) {
1190 int clilen = x->x_clilen;
1191 int n;
1192 struct ClientAddressStruct ras;
1193 ClientAddr ra = &ras;
1194
1195 //catchupflag= FALSE;
1196
1197/* if (ShowBytes) { */
1198/* int i; */
1199/* printf("%d byte message:\n", n); */
1200/* for (i = 0; i < n; ++i) { */
1201/* printf(" %x (%c)\t", m[i], m[i]); */
1202/* if (i%4 == 3) printf("\n"); */
1203/* } */
1204/* printf("\n"); */
1205/* } */
1206
1207 // return catchupflag;
1208 //struct sockaddr_in x->x_server;
1209 //while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &cl_addr, &clilen)) >0)
1210 // while((
1211
1212 #ifdef WIN32
1213 if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (SOCKADDR*)&x->x_server, &clilen)) >0)
1214 #else
1215 if ((n = recvfrom(sockfd, mbuf, MAXMESG, 0, (struct sockaddr *)&x->x_server, &clilen)) >0)
1216 #endif
1217 {
1218 //int r;
1219 ras.cl_addr = *((struct sockaddr_in *) &x->x_server);
1220 ras.clilen = x->x_clilen;
1221 ras.sockfd = x->x_connectsocket;
1222
1223 #ifdef DEBUG
1224 printf("dumpOSC_read: received UDP packet of length %d\n", n);
1225 #endif
1226
1227 if(!dumpOSC_SendReply(mbuf, n, &x->x_server, clilen, sockfd))
1228 {
1229 dumpOSC_ParsePacket(x, mbuf, n, ra);
1230 }
1231 //r = Synthmessage(mbuf, n, &x->x_server, clilen, sockfd);
1232 //post ("%d", r);
1233 //outlet_anything(x->x_msgout, at[msg].a_w.w_symbol,
1234 // emsg-msg-1, at + msg + 1);
1235 // outlet_list(x->x_msgout, 0, n, mbuf);
1236 //if( sgi_HaveToQuit()) goto out;
1237 //if(r>0) goto back;
1238 //clilen = maxclilen;
1239 }
1240}
1241
1242static void *dumpOSC_new(t_symbol *compatflag,
1243 t_floatarg fportno) {
1244 t_dumpOSC *x;
1245 struct sockaddr_in server;
1246 int clilen=sizeof(server);
1247 int sockfd;
1248 int portno=fportno;
1249 int udp = 1;
1250
1251 //x->x_b = binbuf_new();
1252 //x->x_outat = binbuf_getvec(x->x_b);
1253
1254 //{{raf}} pointer not valid yet...moving this down
1255 //x->x_outatc = 0; {{raf}}
1256
1257 /* create a socket */
1258 if ((sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0)) == -1)
1259 {
1260 sys_sockerror("socket");
1261 return (0);
1262 }
1263
1264 server.sin_family = AF_INET;
1265 server.sin_addr.s_addr = INADDR_ANY;
1266 /* assign server port number */
1267 server.sin_port = htons((u_short)portno);
1268 /* name the socket */
1269 if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
1270 {
1271 sys_sockerror("bind");
1272 sys_closesocket(sockfd);
1273 return (0);
1274 }
1275
1276 x = (t_dumpOSC *)pd_new(dumpOSC_class);
1277 x->x_outatc = 0; // {{raf}} now pointer is valid (less invalid)
1278
1279 x->x_msgout = outlet_new(&x->x_obj, &s_anything);
1280
1281 // if (udp) /* datagram protocol */
1282 {
1283
1284 sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_read, x);
1285 x->x_connectout = 0;
1286 }
1287 // else /* streaming protocol */
1288 /* { */
1289 /* if (listen(sockfd, 5) < 0) */
1290 /* { */
1291 /* sys_sockerror("listen"); */
1292 /* sys_closesocket(sockfd); */
1293 /* sockfd = -1; */
1294 /* } */
1295 /* else */
1296 /* { */
1297 /* sys_addpollfn(sockfd, (t_fdpollfn)dumpOSC_connectpoll, x); */
1298 /* x->x_connectout = outlet_new(&x->x_obj, &s_float); */
1299 /* } */
1300 /* } */
1301
1302 x->x_connectsocket = sockfd;
1303 x->x_server = server;
1304 x->x_clilen = clilen;
1305 x->x_nconnections = 0;
1306 x->x_udp = udp;
1307
1308 return (x);
1309}
1310
1311static void dumpOSC_free(t_dumpOSC *x)
1312{
1313 /* LATER make me clean up open connections */
1314 if (x->x_connectsocket >= 0)
1315 {
1316 sys_rmpollfn(x->x_connectsocket);
1317 sys_closesocket(x->x_connectsocket);
1318 }
1319}
1320
1321#ifdef WIN32
1322OSC_API void dumpOSC_setup(void)
1323#else
1324void dumpOSC_setup(void)
1325#endif
1326{
1327 dumpOSC_class = class_new(gensym("dumpOSC"),
1328 (t_newmethod)dumpOSC_new, (t_method)dumpOSC_free,
1329 sizeof(t_dumpOSC), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT,
1330 A_DEFSYM, 0);
1331 class_sethelpsymbol(dumpOSC_class, gensym("dumpOSC-help.pd"));
1332}
1333
1334
1335#ifndef WIN32
1336 #define UNIXDG_PATH "/tmp/htm"
1337 #define UNIXDG_TMP "/tmp/htm.XXXXXX"
1338 static int unixinitudp(int chan)
1339 {
1340 struct sockaddr_un serv_addr;
1341 int sockfd;
1342
1343 if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
1344 return sockfd;
1345
1346 bzero((char *)&serv_addr, sizeof(serv_addr));
1347 serv_addr.sun_family = AF_UNIX;
1348 strcpy(serv_addr.sun_path, UNIXDG_PATH);
1349 sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan);
1350 unlink(serv_addr.sun_path);
1351 if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0)
1352 {
1353 perror("unable to bind\n");
1354 return -1;
1355 }
1356
1357 fcntl(sockfd, F_SETFL, FNDELAY);
1358 return sockfd;
1359 }
1360#endif // #ifndef WIN32
1361
1362
1363
1364static int initudp(int chan)
1365{
1366
1367#ifdef WIN32
1368 struct sockaddr_in serv_addr;
1369 unsigned int sockfd;
1370 ULONG nonBlocking = (ULONG) TRUE;
1371
1372 if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET ) {
1373 ZeroMemory((char *)&serv_addr, sizeof(serv_addr));
1374 serv_addr.sin_family = AF_INET;
1375 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1376 serv_addr.sin_port = htons(chan);
1377 if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) {
1378 // set for non-blocking mode
1379 if(ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) {
1380 perror("unable to set non-blocking\n");
1381 return -1;
1382 }
1383 }
1384 else { perror("unable to bind\n"); return -1; }
1385 }
1386 return (sockfd == INVALID_SOCKET ? -1 : (int)sockfd);
1387#else
1388 struct sockaddr_in serv_addr;
1389 int sockfd;
1390
1391 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1392 return sockfd;
1393
1394 bzero((char *)&serv_addr, sizeof(serv_addr));
1395 serv_addr.sin_family = AF_INET;
1396 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1397 serv_addr.sin_port = htons(chan);
1398
1399 if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
1400 {
1401 perror("unable to bind\n");
1402 return -1;
1403 }
1404
1405 fcntl(sockfd, F_SETFL, FNDELAY);
1406 return sockfd;
1407#endif
1408}
1409
1410
1411
1412
1413
1414
1415
1416
1417static void closeudp(int sockfd) {
1418 #ifdef WIN32
1419 closesocket(sockfd);
1420 #else
1421 close(sockfd);
1422 #endif
1423}
1424
1425static Boolean catchupflag=FALSE;
1426Boolean ClientReply(int packetsize, void *packet, int socketfd,
1427 void *clientaddresspointer, int clientaddressbufferlength)
1428{
1429 if(!clientaddresspointer) return FALSE;
1430 catchupflag= TRUE;
1431 return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength);
1432}
1433
1434static Boolean exitflag= FALSE;
1435void sgi_CleanExit(void) {
1436 exitflag = TRUE;
1437}
1438
1439Boolean sgi_HaveToQuit(void) {
1440 return exitflag;
1441}
1442
1443
1444/* file descriptor poll table */
1445static int npolldevs =0;
1446typedef struct polldev
1447{
1448 int fd;
1449 void (*callbackfunction)(int , void *);
1450 void *dummy;
1451} polldev;
1452#define TABMAX 8
1453static polldev polldevs[TABMAX];
1454
1455
1456/* Register a device (referred to by a file descriptor that the caller
1457 should have already successfully obtained from a system call) to be
1458 polled as real-time constraints allowed.
1459
1460 When a select(2) call indicates activity on the file descriptor, the
1461 callback function is called with the file descripter as first
1462 argument and the given dummy argument (presumably a pointer to the
1463 instance variables associated with the device).
1464*/
1465int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy)
1466{
1467 if(npolldevs<TABMAX)
1468 {
1469 polldevs[npolldevs].fd = fd;
1470 polldevs[npolldevs].callbackfunction = callbackfunction;
1471 polldevs[npolldevs].dummy = dummy;
1472 }
1473 else return -1;
1474 return npolldevs++;
1475}
1476
1477static int caught_sigint;
1478
1479static void catch_sigint() {
1480 caught_sigint = 1;
1481}
1482static int sockfd, usockfd;
1483
1484
1485void PrintClientAddr(ClientAddr CA) {
1486 unsigned long addr = CA->cl_addr.sin_addr.s_addr;
1487 printf("Client address %p:\n", CA);
1488 printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd);
1489 printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family,
1490 CA->cl_addr.sin_port);
1491 printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr));
1492
1493 printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n",
1494 CA->cl_addr.sin_zero[0],
1495 CA->cl_addr.sin_zero[1],
1496 CA->cl_addr.sin_zero[2],
1497 CA->cl_addr.sin_zero[3],
1498 CA->cl_addr.sin_zero[4],
1499 CA->cl_addr.sin_zero[5],
1500 CA->cl_addr.sin_zero[6],
1501 CA->cl_addr.sin_zero[7]);
1502
1503 printf("\n");
1504}
1505
1506//*******************
1507
1508void WriteTime(char* dst, osc_time_t osctime)
1509{
1510 *(int32_t*)dst = htonl((int32_t)(osctime >> 32));
1511 *(int32_t*)(dst+4) = htonl((int32_t)osctime);
1512}
1513
1514void WriteMode(char* dst)
1515{
1516 *(int32_t*)dst = htonl(0);
1517}
1518
1519osc_time_t ReadTime(const char* src)
1520{
1521 osc_time_t osctime = ntohl(*(int32_t*)src);
1522 return (osctime << 32) + ntohl(*(int32_t*)(src+4));
1523}
1524
1525double TimeToSeconds(osc_time_t osctime)
1526{
1527 return (double)osctime * 2.3283064365386962890625e-10 /* 1/2^32 */;
1528}
1529
1530int timeRound(double x)
1531{
1532 return x >= 0.0 ? x+0.5 : x-0.5;
1533}
1534/*
1535void WriteLogicalTime(char* dst)
1536{
1537 static double startTime = -1.0;
1538 double sTime;
1539
1540 // Initialisierung der Startzeit.
1541 // Knnte effizienter (ohne 'if') auch irgendwo vorher passieren.
1542 // Knnte wahrscheinlich auch 0.0 sein.
1543 if (startTime < 0.0) {
1544 startTime = clock_getlogicaltime();
1545 }
1546
1547 sTime = clock_gettimesince(startTime) * 0.001;
1548 *(int32_t*)dst = hton'K l((int32_t)sTime);
1549 *(int32_t*)(dst+4) = htonl((int32_t)(4294967296.0 * sTime));
1550}
1551*/
1552
1553void WriteLogicalTime(char* dst)
1554{
1555 double sTime = clock_gettimesince(19230720) / 1000.0;
1556 double tau = sTime - timeRound(sTime);
1557
1558 //fprintf(stderr, "sSec = %f tau = %f\n", sTime, tau);
1559
1560 *(int32_t*)dst = htonl((int32_t)(sTime));
1561 *(int32_t*)(dst+4) = htonl((int32_t)(4294967296 * tau));
1562}
1563
1564Boolean dumpOSC_SendReply(char *buf, int n, void *clientDesc, int clientDescLenght, int fd)
1565{
1566 if((n == 24) && (strcmp(buf, "#time") == 0))
1567 {
1568 osc_time_t t0, t1, t2;
1569 double dt0, dt1, dt2;
1570
1571 WriteMode(buf+6);
1572
1573 t0 = ReadTime(buf+8);
1574
1575 WriteLogicalTime(buf+16);
1576 t1 = ReadTime(buf+16); // reverse
1577 dt0 = TimeToSeconds(t0); // client time
1578 dt1 = TimeToSeconds(t1); // server time
1579
1580 // fprintf(stderr, "%f\t%f\t%f\n", dt0, dt1, dt0 - dt1);
1581
1582 sendto(fd, buf, n, 0, (struct sockaddr *)clientDesc, clientDescLenght);
1583 return TRUE;
1584 }
1585 else
1586 {
1587 return FALSE;
1588 }
1589}
1590
1591//**********************
1592
1593void dumpOSC_ParsePacket(t_dumpOSC *x, char *buf, int n, ClientAddr returnAddr) {
1594 // t_dumpOSC *x;
1595 int size, messageLen, i;
1596 char *messageName;
1597 char *args;
1598
1599 //#ifdef PRINTADDRS
1600 #ifdef DEBUG
1601 //PrintClientAddr(returnAddr);
1602 #endif
1603
1604
1605 if ((n%4) != 0) {
1606 complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", n);
1607 return;
1608 }
1609
1610 if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) {
1611 /* This is a bundle message. */
1612 #ifdef DEBUG
1613 printf("dumpOSC_ParsePacket: bundle msg: bundles not yet supported\n");
1614 #endif
1615
1616 if (n < 16) {
1617 complain("Bundle message too small (%d bytes) for time tag", n);
1618 return;
1619 }
1620
1621 /* Print the time tag */
1622 #ifdef DEBUG
1623 printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), ntohl(*((unsigned long *)(buf+12))));
1624 #endif
1625
1626 /* Note: if we wanted to actually use the time tag as a little-endian
1627 64-bit int, we'd have to word-swap the two 32-bit halves of it */
1628
1629 i = 16; /* Skip "#group\0" and time tag */
1630
1631 while(i<n) {
1632 size = ntohl(*((int *) (buf + i)));
1633 if ((size % 4) != 0) {
1634 complain("Bad size count %d in bundle (not a multiple of 4)", size);
1635 return;
1636 }
1637 if ((size + i + 4) > n) {
1638 complain("Bad size count %d in bundle (only %d bytes left in entire bundle)",
1639 size, n-i-4);
1640 return;
1641 }
1642
1643 /* Recursively handle element of bundle */
1644 dumpOSC_ParsePacket(x, buf+i+4, size, returnAddr);
1645 i += 4 + size;
1646 }
1647
1648 if (i != n) {
1649 complain("This can't happen");
1650 }
1651 #ifdef DEBUG
1652 printf("]\n");
1653 #endif
1654
1655 }
1656 else if ((n == 24) && (strcmp(buf, "#time") == 0))
1657 {
1658 complain("Time message: %s\n :).\n", htm_error_string);
1659 return;
1660
1661 }
1662 else
1663 {
1664 /* This is not a bundle message */
1665
1666 messageName = buf;
1667 args = DataAfterAlignedString(messageName, buf+n);
1668 if (args == 0) {
1669 complain("Bad message name string: %s\nDropping entire message.\n",
1670 htm_error_string);
1671 return;
1672 }
1673 messageLen = args-messageName;
1674 dumpOSC_Smessage(x, messageName, (void *)args, n-messageLen, returnAddr);
1675 }
1676}
1677
1678#define SMALLEST_POSITIVE_FLOAT 0.000001f
1679
1680static void dumpOSC_Smessage(t_dumpOSC *x, char *address, void *v, int n, ClientAddr returnAddr) {
1681 char *chars = v;
1682 t_atom at;
1683 //t_atom myargv[50];
1684
1685 int myargc = x->x_outatc;
1686 t_atom* mya = x->x_outat;
1687 int myi;
1688
1689#ifdef DEBUG
1690 printf("%s ", address);
1691#endif
1692
1693 // ztoln+cvt from envgen.c, ggee-0.18 ..
1694 // outlet_anything's 'symbol' gets set to address
1695 // so we dont need to append address to the atomlist
1696 /*
1697 SETSYMBOL(mya,gensym(address));myargc++;
1698 x->x_outatc = myargc;
1699 */
1700
1701 if (n != 0) {
1702 if (chars[0] == ',') {
1703 if (chars[1] != ',') {
1704 /* This message begins with a type-tag string */
1705 dumpOSC_PrintTypeTaggedArgs(x, v, n);
1706 } else {
1707 /* Double comma means an escaped real comma, not a type string */
1708 dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1);
1709 }
1710 } else {
1711 dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0);
1712 }
1713 }
1714
1715 outlet_anything(x->x_msgout,gensym(address),x->x_outatc,(t_atom*)&x->x_outat);
1716 x->x_outatc = 0;
1717#ifdef DEBUG
1718 printf("\n");
1719#endif
1720 fflush(stdout); /* Added for Sami 5/21/98 */
1721}
1722
1723static void dumpOSC_PrintTypeTaggedArgs(t_dumpOSC *x, void *v, int n) {
1724 char *typeTags, *thisType;
1725 char *p;
1726
1727 int myargc = x->x_outatc;
1728 t_atom* mya = x->x_outat;
1729 int myi;
1730
1731 typeTags = v;
1732
1733 if (!IsNiceString(typeTags, typeTags+n)) {
1734 /* No null-termination, so maybe it wasn't a type tag
1735 string after all */
1736 dumpOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0);
1737 return;
1738 }
1739
1740 p = DataAfterAlignedString(typeTags, typeTags+n);
1741
1742
1743 for (thisType = typeTags + 1; *thisType != 0; ++thisType) {
1744 switch (*thisType) {
1745 case 'i': case 'r': case 'm': case 'c':
1746#ifdef DEBUG
1747 //post("integer: %d", ntohl(*((int *) p)));
1748#endif
1749 /* Martin Peach fix for negative floats:
1750 * was: SETFLOAT(mya+myargc,ntohl(*((int *) p)));
1751 * now is:
1752 */
1753 SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p)));
1754 myargc++;
1755
1756 p += 4;
1757 break;
1758
1759 case 'f': {
1760 int i = ntohl(*((int *) p));
1761 float *floatp = ((float *) (&i));
1762#ifdef DEBUG
1763 post("float: %f", *floatp);
1764#endif
1765 SETFLOAT(mya+myargc,*floatp);
1766 myargc++;
1767
1768 p += 4;
1769 }
1770 break;
1771
1772 case 'h': case 't':
1773#ifdef DEBUG
1774 printf("[A 64-bit int] ");
1775#endif
1776 post("[A 64-bit int] not implemented");
1777
1778 p += 8;
1779 break;
1780
1781 case 'd':
1782#ifdef DEBUG
1783 printf("[A 64-bit float] ");
1784#endif
1785 post("[A 64-bit float] not implemented");
1786
1787 p += 8;
1788 break;
1789
1790 case 's': case 'S':
1791 if (!IsNiceString(p, typeTags+n)) {
1792 post("Type tag said this arg is a string but it's not!\n");
1793 return;
1794 } else {
1795#ifdef DEBUG
1796 post("string: \"%s\"", p);
1797#endif
1798 SETSYMBOL(mya+myargc,gensym(p));
1799 myargc++;
1800 //outlet_list(x->x_msgout, 0,sizeof(p), p);
1801 //outlet_anything(x->x_msgout, 0, sizeof(p), p);
1802 p = DataAfterAlignedString(p, typeTags+n);
1803 // append to output vector ..
1804 }
1805 break;
1806
1807 case 'T':
1808#ifdef DEBUG
1809 printf("[True] ");
1810#endif
1811 SETFLOAT(mya+myargc,1.);
1812 myargc++;
1813 break;
1814 case 'F':
1815#ifdef DEBUG
1816 printf("[False] ");
1817#endif
1818 SETFLOAT(mya+myargc,0.);
1819 myargc++;
1820 break;
1821 case 'N':
1822#ifdef DEBUG
1823 printf("[Nil]");
1824#endif
1825 post("sendOSC: [Nil] not implemented");
1826 break;
1827 case 'I':
1828#ifdef DEBUG
1829 printf("[Infinitum]");
1830#endif
1831 post("sendOSC: [Infinitum] not implemented");
1832 break;
1833
1834 default:
1835 post("sendOSC: [Unrecognized type tag %c]", *thisType);
1836 // return;
1837 }
1838 }
1839 x->x_outatc = myargc;
1840}
1841
1842static void dumpOSC_PrintHeuristicallyTypeGuessedArgs(t_dumpOSC *x, void *v, int n, int skipComma) {
1843 int i, thisi;
1844 float thisf;
1845 int *ints;
1846 char *chars;
1847 char *string, *nextString;
1848
1849 int myargc= x->x_outatc;
1850 t_atom* mya = x->x_outat;
1851 int myi;
1852
1853
1854 /* Go through the arguments 32 bits at a time */
1855 ints = v;
1856 chars = v;
1857
1858 for (i = 0; i<n/4; ) {
1859 string = &chars[i*4];
1860 thisi = ntohl(ints[i]);
1861 /* Reinterpret the (potentially byte-reversed) thisi as a float */
1862 thisf = *(((float *) (&thisi)));
1863
1864 if (thisi >= -1000 && thisi <= 1000000) {
1865#ifdef DEBUG
1866 printf("%d ", thisi);
1867#endif
1868 // append to output vector ..
1869 SETFLOAT(mya+myargc,(t_float) (thisi));
1870 myargc++;
1871 // outlet_float(x->x_msgout, thisi);
1872 i++;
1873 } else if (thisf >= -1000.f && thisf <= 1000000.f &&
1874 (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) {
1875#ifdef DEBUG
1876 printf("%f ", thisf);
1877#endif
1878 // append to output vector ..
1879 SETFLOAT(mya+myargc,thisf);
1880 myargc++;
1881 //outlet_float(x->x_msgout, thisf);
1882 i++;
1883 } else if (IsNiceString(string, chars+n)) {
1884 nextString = DataAfterAlignedString(string, chars+n);
1885#ifdef DEBUG
1886 printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string);
1887#endif
1888 // append to output vector ..
1889 SETSYMBOL(mya+myargc,gensym(string));
1890 myargc++;
1891 //outlet_symbol(x->x_msgout, gensym((i == 0 && skipComma) ? string +1 : string));
1892 i += (nextString-string) / 4;
1893 } else {
1894 // unhandled .. ;)
1895#ifdef DEBUG
1896 printf("0x%x xx", ints[i]);
1897#endif
1898 i++;
1899 }
1900 x->x_outatc = myargc;
1901 }
1902}
1903
1904
1905#define STRING_ALIGN_PAD 4
1906
1907char *DataAfterAlignedString(char *string, char *boundary)
1908{
1909 /* The argument is a block of data beginning with a string. The
1910 string has (presumably) been padded with extra null characters
1911 so that the overall length is a multiple of STRING_ALIGN_PAD
1912 bytes. Return a pointer to the next byte after the null
1913 byte(s). The boundary argument points to the character after
1914 the last valid character in the buffer---if the string hasn't
1915 ended by there, something's wrong.
1916
1917 If the data looks wrong, return 0, and set htm_error_string */
1918
1919 int i;
1920
1921 if ((boundary - string) %4 != 0) {
1922 fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n");
1923 return 0;
1924 }
1925
1926 for (i = 0; string[i] != '\0'; i++) {
1927 if (string + i >= boundary) {
1928 htm_error_string = "DataAfterAlignedString: Unreasonably long string";
1929 return 0;
1930 }
1931 }
1932
1933 /* Now string[i] is the first null character */
1934 i++;
1935
1936 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
1937 if (string + i >= boundary) {
1938 htm_error_string = "DataAfterAlignedString: Unreasonably long string";
1939 return 0;
1940 }
1941 if (string[i] != '\0') {
1942 htm_error_string = "DataAfterAlignedString: Incorrectly padded string.";
1943 return 0;
1944 }
1945 }
1946
1947 return string+i;
1948}
1949
1950Boolean IsNiceString(char *string, char *boundary)
1951{
1952 /* Arguments same as DataAfterAlignedString(). Is the given "string"
1953 really a string? I.e., is it a sequence of isprint() characters
1954 terminated with 1-4 null characters to align on a 4-byte boundary? */
1955
1956 int i;
1957
1958 if ((boundary - string) %4 != 0) {
1959 fprintf(stderr, "Internal error: IsNiceString: bad boundary\n");
1960 return 0;
1961 }
1962
1963 for (i = 0; string[i] != '\0'; i++) {
1964 if (!isprint(string[i])) return FALSE;
1965 if (string + i >= boundary) return FALSE;
1966 }
1967
1968 /* If we made it this far, it's a null-terminated sequence of printing characters
1969 in the given boundary. Now we just make sure it's null padded... */
1970
1971 /* Now string[i] is the first null character */
1972 i++;
1973 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
1974 if (string[i] != '\0') return FALSE;
1975 }
1976
1977 return TRUE;
1978}
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988#include <stdarg.h>
1989void complain(char *s, ...) {
1990 va_list ap;
1991 va_start(ap, s);
1992 fprintf(stderr, "*** ERROR: ");
1993 vfprintf(stderr, s, ap);
1994 fprintf(stderr, "\n");
1995 va_end(ap);
1996}
1997
1998#endif /* __sgi or LINUX or WIN32 */
diff --git a/apps/plugins/pdbox/PDa/extra/equalizer.c b/apps/plugins/pdbox/PDa/extra/equalizer.c
new file mode 100644
index 0000000000..1d21c4087c
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/equalizer.c
@@ -0,0 +1,178 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4/*
5
6 These filter coefficients computations are taken from
7 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
8
9 written by Robert Bristow-Johnson
10
11*/
12
13#include "m_pd.h"
14#ifdef NT
15#pragma warning( disable : 4244 )
16#pragma warning( disable : 4305 )
17#endif
18#include <math.h>
19#include "filters.h"
20
21
22
23/* ------------------- equ ----------------------------*/
24static t_class *equ_class;
25
26void equ_bang(t_rbjfilter *x)
27{
28 t_atom at[5];
29 t_float omega = e_omega(x->x_freq,x->x_rate);
30 t_float alpha = e_alpha(x->x_bw*0.01,omega);
31 t_float b0 = 1 + alpha*e_A(x->x_gain);
32 t_float b1 = -2.*cos(omega);
33 t_float b2 = 1 - alpha*e_A(x->x_gain);
34 t_float a0 = 1 + alpha/e_A(x->x_gain);
35 t_float a1 = -2.*cos(omega);
36 t_float a2 = 1 - alpha/e_A(x->x_gain);
37
38/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/
39
40 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
41 post("equ: filter unstable -> resetting");
42 a0=1.;a1=0.;a2=0.;
43 b0=1.;b1=0.;b2=0.;
44 }
45
46 SETFLOAT(at,-a1/a0);
47 SETFLOAT(at+1,-a2/a0);
48 SETFLOAT(at+2,b0/a0);
49 SETFLOAT(at+3,b1/a0);
50 SETFLOAT(at+4,b2/a0);
51
52 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
53}
54
55
56void equ_float(t_rbjfilter *x,t_floatarg f)
57{
58 x->x_freq = f;
59 equ_bang(x);
60}
61
62
63static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw)
64{
65 t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class);
66
67 x->x_rate = 44100.0;
68 outlet_new(&x->x_obj,&s_float);
69 floatinlet_new(&x->x_obj, &x->x_gain);
70 floatinlet_new(&x->x_obj, &x->x_bw);
71 if (f > 0.) x->x_freq = f;
72 if (bw > 0.) x->x_bw = bw;
73 if (g != 0.) x->x_gain = g;
74 return (x);
75}
76
77
78void equalizer_setup(void)
79{
80 equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0,
81 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
82 class_addbang(equ_class,equ_bang);
83 class_addfloat(equ_class,equ_float);
84}
85
86
87
88
89
90/* (C) Guenter Geiger <geiger@epy.co.at> */
91
92
93/*
94
95 These filter coefficients computations are taken from
96 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
97
98 written by Robert Bristow-Johnson
99
100*/
101
102#include "m_pd.h"
103#ifdef NT
104#pragma warning( disable : 4244 )
105#pragma warning( disable : 4305 )
106#endif
107#include <math.h>
108#include "filters.h"
109
110
111
112/* ------------------- equ ----------------------------*/
113static t_class *equ_class;
114
115void equ_bang(t_rbjfilter *x)
116{
117 t_atom at[5];
118 t_float omega = e_omega(x->x_freq,x->x_rate);
119 t_float alpha = e_alpha(x->x_bw*0.01,omega);
120 t_float b0 = 1 + alpha*e_A(x->x_gain);
121 t_float b1 = -2.*cos(omega);
122 t_float b2 = 1 - alpha*e_A(x->x_gain);
123 t_float a0 = 1 + alpha/e_A(x->x_gain);
124 t_float a1 = -2.*cos(omega);
125 t_float a2 = 1 - alpha/e_A(x->x_gain);
126
127/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/
128
129 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
130 post("equ: filter unstable -> resetting");
131 a0=1.;a1=0.;a2=0.;
132 b0=1.;b1=0.;b2=0.;
133 }
134
135 SETFLOAT(at,-a1/a0);
136 SETFLOAT(at+1,-a2/a0);
137 SETFLOAT(at+2,b0/a0);
138 SETFLOAT(at+3,b1/a0);
139 SETFLOAT(at+4,b2/a0);
140
141 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
142}
143
144
145void equ_float(t_rbjfilter *x,t_floatarg f)
146{
147 x->x_freq = f;
148 equ_bang(x);
149}
150
151
152static void *equ_new(t_floatarg f,t_floatarg g,t_floatarg bw)
153{
154 t_rbjfilter *x = (t_rbjfilter *)pd_new(equ_class);
155
156 x->x_rate = 44100.0;
157 outlet_new(&x->x_obj,&s_float);
158 floatinlet_new(&x->x_obj, &x->x_gain);
159 floatinlet_new(&x->x_obj, &x->x_bw);
160 if (f > 0.) x->x_freq = f;
161 if (bw > 0.) x->x_bw = bw;
162 if (g != 0.) x->x_gain = g;
163 return (x);
164}
165
166
167void equalizer_setup(void)
168{
169 equ_class = class_new(gensym("equalizer"), (t_newmethod)equ_new, 0,
170 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
171 class_addbang(equ_class,equ_bang);
172 class_addfloat(equ_class,equ_float);
173}
174
175
176
177
178
diff --git a/apps/plugins/pdbox/PDa/extra/fatom.h b/apps/plugins/pdbox/PDa/extra/fatom.h
new file mode 100644
index 0000000000..abaf9b91c1
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/fatom.h
@@ -0,0 +1,970 @@
1/* ------------------------ fatom ----------------------------- */
2
3#define x_val a_pos.a_w.w_float
4#define DEBUG(x)
5
6#include <string.h>
7#include <stdio.h>
8
9typedef struct _fatom
10{
11 t_object x_obj;
12 t_atom a_pos; /* the value of the fatom */
13
14 t_symbol* x_send;
15 t_symbol* x_receive;
16 t_glist * x_glist; /* value of the current canvas, intialized in _new */
17 int x_rect_width; /* width of the widget */
18 int x_rect_height; /* height of the widget */
19 t_symbol* x_sym; /* symbol for receiving callbacks from GUI */
20 t_symbol* x_type; /* type of fatom (vslider, hslider, checkbutton) */
21
22 t_symbol* x_text; /* associated widget text */
23 int x_max; /* maximum value of a_pos (x_val) */
24 int x_min; /* minimum value of a_pos (x_val) */
25 int x_width; /* width of widget (e.g x_rect_height + 15 for hslider, x_rect_width + 15 for slider) */
26 t_symbol* x_color;
27 t_symbol* x_bgcolor;
28} t_fatom;
29
30/* widget helper functions */
31
32
33
34
35static void draw_inlets(t_fatom *x, t_glist *glist, int firsttime, int nin, int nout)
36{
37 int n = nin;
38 int nplus, i;
39 nplus = (n == 1 ? 1 : n-1);
40 DEBUG(post("draw inlet");)
41 for (i = 0; i < n; i++)
42 {
43 int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
44 if (firsttime)
45 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n",
46 glist_getcanvas(glist),
47 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1,
48 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height,
49 x, i);
50 else
51 sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
52 glist_getcanvas(glist), x, i,
53 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1,
54 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height);
55 }
56 n = nout;
57 nplus = (n == 1 ? 1 : n-1);
58 for (i = 0; i < n; i++)
59 {
60 int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
61 if (firsttime)
62 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
63 glist_getcanvas(glist),
64 onset, text_ypix(&x->x_obj, glist),
65 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1,
66 x, i);
67 else
68 sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
69 glist_getcanvas(glist), x, i,
70 onset, text_ypix(&x->x_obj, glist),
71 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1);
72
73 }
74 DEBUG(post("draw inlet end");)
75}
76
77
78static void draw_handle(t_fatom *x, t_glist *glist, int firsttime) {
79 int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2);
80
81 if (firsttime)
82 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n",
83 glist_getcanvas(glist),
84 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
85 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4,
86 x);
87 else
88 sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n",
89 glist_getcanvas(glist), x,
90 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
91 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4);
92}
93
94static void create_widget(t_fatom *x, t_glist *glist)
95{
96 t_canvas *canvas=glist_getcanvas(glist);
97
98 if (!strcmp(x->x_type->s_name,"vslider")) {
99 x->x_rect_width = x->x_width+15;
100 x->x_rect_height = x->x_max-x->x_min+26;
101
102 sys_vgui("scale .x%x.c.s%x \
103 -sliderlength 10 \
104 -showvalue 0 \
105 -length %d \
106 -resolution 0.01 \
107 -repeatinterval 20 \
108 -from %d -to %d \
109 -width %d \
110 -bg %s \
111 -activebackground %s \
112 -troughcolor %s \
113 -command fatom_cb%x\n",canvas,x,
114 x->x_max-x->x_min+14,
115 x->x_max,
116 x->x_min,
117 x->x_width,
118 x->x_color->s_name,
119 x->x_color->s_name,
120 x->x_bgcolor->s_name,
121 x);
122 } else if (!strcmp(x->x_type->s_name,"hslider")) {
123 x->x_rect_width = x->x_max-x->x_min + 24;
124 x->x_rect_height = x->x_width + 15;
125 sys_vgui("scale .x%x.c.s%x \
126 -sliderlength 10 \
127 -showvalue 0 \
128 -length %d \
129 -resolution 0.01 \
130 -orient horizontal \
131 -repeatinterval 20 \
132 -from %d -to %d \
133 -width %d \
134 -bg %s \
135 -activebackground %s \
136 -troughcolor %s \
137 -command fatom_cb%x\n",canvas,x,
138 x->x_max-x->x_min+14,
139 x->x_min,
140 x->x_max,
141 x->x_width,
142 x->x_color->s_name,
143 x->x_color->s_name,
144 x->x_bgcolor->s_name,
145 x);
146 } else if (!strcmp(x->x_type->s_name,"checkbutton")) {
147 x->x_rect_width = 32;
148 x->x_rect_height = 28;
149 sys_vgui("checkbutton .x%x.c.s%x \
150 -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -text \"%s\" \
151 -bg %s \
152 -activebackground %s \
153 \n",canvas,x,x,x,x,
154 x->x_text->s_name,
155 x->x_color->s_name,
156 x->x_bgcolor->s_name);
157 } else if (!strcmp(x->x_type->s_name,"hradio")) {
158 int i;
159 x->x_rect_width = 8*20;
160 x->x_rect_height = 25;
161 for (i=0;i<8;i++) {
162 sys_vgui("radiobutton .x%x.c.s%x%d \
163 -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i);
164 }
165 /* TODO pack them */
166 } else if (!strcmp(x->x_type->s_name,"vradio")) {
167 int i;
168 x->x_rect_width = 30;
169 x->x_rect_height = 20*8+5;
170 for (i=0;i<8;i++) {
171 sys_vgui("radiobutton .x%x.c.s%x%d \
172 -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i);
173 }
174 /* TODO pack them */
175 } else {
176 x->x_rect_width = 32;
177 x->x_rect_height = 140;
178 sys_vgui("scale .x%x.c.s%x \
179 -sliderlength 10 \
180 -showvalue 0 \
181 -length 131 \
182 -from 127 -to 0 \
183 -command fatom_cb%x\n",canvas,x,x);
184 }
185
186 /* set the start value */
187 if (!strcmp(x->x_type->s_name,"checkbutton")) {
188 if (x->x_val)
189 sys_vgui(".x%x.c.s%x select\n",canvas,x,x->x_val);
190 else
191 sys_vgui(".x%x.c.s%x deselect\n",canvas,x,x->x_val);
192 } else
193 sys_vgui(".x%x.c.s%x set %f\n",canvas,x,x->x_val);
194
195}
196
197
198
199
200
201static void fatom_drawme(t_fatom *x, t_glist *glist, int firsttime)
202{
203 t_canvas *canvas=glist_getcanvas(glist);// x->x_glist;//glist_getcanvas(glist);
204 DEBUG(post("drawme %d",firsttime);)
205 if (firsttime) {
206 DEBUG(post("glist %x canvas %x",x->x_glist,canvas));
207 create_widget(x,glist);
208 x->x_glist = canvas;
209 sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x -tags %xS\n",
210 canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2,x->x_glist,x,x);
211
212 }
213 else {
214 sys_vgui(".x%x.c coords %xS \
215%d %d\n",
216 canvas, x,
217 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2);
218 }
219 draw_inlets(x, glist, firsttime, 1,1);
220 // draw_handle(x, glist, firsttime);
221
222}
223
224
225static void fatom_erase(t_fatom* x,t_glist* glist)
226{
227 int n;
228
229 DEBUG(post("erase");)
230 sys_vgui("destroy .x%x.c.s%x\n",glist_getcanvas(glist),x);
231
232 sys_vgui(".x%x.c delete %xS\n",glist_getcanvas(glist), x);
233
234 /* inlets and outlets */
235
236 sys_vgui(".x%x.c delete %xi%d\n",glist_getcanvas(glist),x,0);
237 sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,0);
238 sys_vgui(".x%x.c delete %xhandle\n",glist_getcanvas(glist),x,0);
239}
240
241
242
243/* ------------------------ fatom widgetbehaviour----------------------------- */
244
245
246static void fatom_getrect(t_gobj *z, t_glist *owner,
247 int *xp1, int *yp1, int *xp2, int *yp2)
248{
249 int width, height;
250 t_fatom* s = (t_fatom*)z;
251
252 width = s->x_rect_width;
253 height = s->x_rect_height;
254 *xp1 = text_xpix(&s->x_obj, owner);
255 *yp1 = text_ypix(&s->x_obj, owner);
256 *xp2 = text_xpix(&s->x_obj, owner) + width;
257 *yp2 = text_ypix(&s->x_obj, owner) + height;
258}
259
260static void fatom_displace(t_gobj *z, t_glist *glist,
261 int dx, int dy)
262{
263 t_fatom *x = (t_fatom *)z;
264 DEBUG(post("displace");)
265 x->x_obj.te_xpix += dx;
266 x->x_obj.te_ypix += dy;
267 if (glist_isvisible(glist))
268 {
269 sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n",
270 glist_getcanvas(glist), x,
271 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
272 text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height);
273
274 fatom_drawme(x, glist, 0);
275 canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
276 }
277 DEBUG(post("displace end");)
278}
279
280static void fatom_select(t_gobj *z, t_glist *glist, int state)
281{
282 t_fatom *x = (t_fatom *)z;
283 if (state) {
284 sys_vgui(".x%x.c create rectangle \
285%d %d %d %d -tags %xSEL -outline blue\n",
286 glist_getcanvas(glist),
287 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
288 text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height,
289 x);
290 }
291 else {
292 sys_vgui(".x%x.c delete %xSEL\n",
293 glist_getcanvas(glist), x);
294 }
295
296
297
298}
299
300
301static void fatom_activate(t_gobj *z, t_glist *glist, int state)
302{
303/* t_text *x = (t_text *)z;
304 t_rtext *y = glist_findrtext(glist, x);
305 if (z->g_pd != gatom_class) rtext_activate(y, state);*/
306}
307
308static void fatom_delete(t_gobj *z, t_glist *glist)
309{
310 t_text *x = (t_text *)z;
311 canvas_deletelinesfor(glist_getcanvas(glist), x);
312}
313
314
315static void fatom_vis(t_gobj *z, t_glist *glist, int vis)
316{
317 t_fatom* s = (t_fatom*)z;
318 t_rtext *y;
319 DEBUG(post("vis: %d",vis);)
320 if (vis) {
321#ifdef PD_MINOR_VERSION
322 y = (t_rtext *) rtext_new(glist, (t_text *)z);
323#else
324 y = (t_rtext *) rtext_new(glist, (t_text *)z,0,0);
325#endif
326 fatom_drawme(s, glist, 1);
327 }
328 else {
329 y = glist_findrtext(glist, (t_text *)z);
330 fatom_erase(s,glist);
331 rtext_free(y);
332 }
333}
334
335static void fatom_save(t_gobj *z, t_binbuf *b);
336
337t_widgetbehavior fatom_widgetbehavior;
338
339
340
341
342static void fatom_size(t_fatom* x,t_floatarg w,t_floatarg h) {
343 x->x_rect_width = w;
344 x->x_rect_height = h;
345}
346
347static void fatom_color(t_fatom* x,t_symbol* col)
348{
349
350}
351
352
353static void fatom_f(t_fatom* x,t_floatarg f)
354{
355 x->x_val = f;
356 if (x->x_send == &s_)
357 outlet_float(x->x_obj.ob_outlet,f);
358 else
359 if (x->x_send->s_thing) pd_float(x->x_send->s_thing,f);
360}
361
362
363static void fatom_float(t_fatom* x,t_floatarg f)
364{
365 if (glist_isvisible(x->x_glist)) {
366 if (!strcmp(x->x_type->s_name,"checkbutton")) {
367 if (x->x_val)
368 sys_vgui(".x%x.c.s%x select\n",x->x_glist,x,f);
369 else
370 sys_vgui(".x%x.c.s%x deselect\n",x->x_glist,x,f);
371 } else
372 sys_vgui(".x%x.c.s%x set %f\n",x->x_glist,x,f);
373 }
374 fatom_f(x,f);
375}
376
377
378static void fatom_bang(t_fatom* x,t_floatarg f)
379{
380 outlet_float(x->x_obj.ob_outlet,x->x_val);
381}
382
383
384static void fatom_properties(t_gobj *z, t_glist *owner)
385{
386 post("N/I");
387}
388
389
390static void fatom_save(t_gobj *z, t_binbuf *b)
391{
392
393 t_fatom *x = (t_fatom *)z;
394
395 binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"),
396 x->x_obj.te_xpix, x->x_obj.te_ypix ,
397 gensym("fatom"),x->x_type);
398 binbuf_addv(b, ";");
399}
400
401
402static void *fatom_new(t_fatom* x,int argc,t_atom* argv)
403{
404 char buf[256];
405 int n = 0;
406 x->x_glist = canvas_getcurrent();
407
408 x->x_text = gensym("");
409 x->x_max = 127;
410 x->x_min = 0;
411 x->x_width = 15;
412 x->x_color = gensym("grey");
413 x->x_bgcolor = gensym("grey");
414 x->x_send = &s_;
415
416 while (argc) {
417 if (argv->a_type == A_FLOAT) {
418 if (n==0) x->x_max = atom_getfloat(argv);
419 if (n==1) x->x_min = atom_getfloat(argv);
420 if (n==2) x->x_width = atom_getfloat(argv);
421 }
422
423 if (argv->a_type == A_SYMBOL) {
424 post("%d: symbol value %s",n,atom_getsymbol(argv)->s_name);
425 if (n==3) x->x_send = atom_getsymbol(argv);
426 if (n==4) x->x_color = atom_getsymbol(argv);
427 if (n==5) x->x_bgcolor = atom_getsymbol(argv);
428 }
429 argv++;
430 argc--;
431 n++;
432 }
433
434 /* bind to a symbol for slider callback (later make this based on the
435 filepath ??) */
436
437 sprintf(buf,"fatom%x",(t_int)x);
438 x->x_sym = gensym(buf);
439 pd_bind(&x->x_obj.ob_pd, x->x_sym);
440
441 /* pipe startup code to tk */
442
443 sys_vgui("proc fatom_cb%x {v} {\n pd [concat fatom%x f $v \\;]\n }\n",x,x);
444
445 outlet_new(&x->x_obj, &s_float);
446 return (x);
447}
448
449static void fatom_setup_common(t_class* class)
450{
451
452 fatom_widgetbehavior.w_getrectfn = fatom_getrect;
453 fatom_widgetbehavior.w_displacefn = fatom_displace;
454 fatom_widgetbehavior.w_selectfn = fatom_select;
455 fatom_widgetbehavior.w_activatefn = fatom_activate;
456 fatom_widgetbehavior.w_deletefn = fatom_delete;
457 fatom_widgetbehavior.w_visfn = fatom_vis;
458#if PD_MINOR_VERSION < 37
459 fatom_widgetbehavior.w_savefn = fatom_save;
460 fatom_widgetbehavior.w_propertiesfn = NULL;
461#endif
462 fatom_widgetbehavior.w_clickfn = NULL;
463
464 class_addfloat(class, (t_method)fatom_float);
465 class_addbang(class, (t_method)fatom_bang);
466 class_addmethod(class, (t_method)fatom_f, gensym("f"),
467 A_FLOAT, 0);
468
469/*
470 class_addmethod(class, (t_method)fatom_size, gensym("size"),
471 A_FLOAT, A_FLOAT, 0);
472
473 class_addmethod(class, (t_method)fatom_color, gensym("color"),
474 A_SYMBOL, 0);
475*/
476/*
477 class_addmethod(class, (t_method)fatom_open, gensym("open"),
478 A_SYMBOL, 0);
479*/
480
481 class_setwidget(class,&fatom_widgetbehavior);
482#if PD_MINOR_VERSION >= 37
483 class_setsavefn(class,&fatom_save);
484#endif
485}
486/* ------------------------ fatom ----------------------------- */
487
488#define x_val a_pos.a_w.w_float
489#define DEBUG(x)
490
491#include <string.h>
492#include <stdio.h>
493
494typedef struct _fatom
495{
496 t_object x_obj;
497 t_atom a_pos; /* the value of the fatom */
498
499 t_symbol* x_send;
500 t_symbol* x_receive;
501 t_glist * x_glist; /* value of the current canvas, intialized in _new */
502 int x_rect_width; /* width of the widget */
503 int x_rect_height; /* height of the widget */
504 t_symbol* x_sym; /* symbol for receiving callbacks from GUI */
505 t_symbol* x_type; /* type of fatom (vslider, hslider, checkbutton) */
506
507 t_symbol* x_text; /* associated widget text */
508 int x_max; /* maximum value of a_pos (x_val) */
509 int x_min; /* minimum value of a_pos (x_val) */
510 int x_width; /* width of widget (e.g x_rect_height + 15 for hslider, x_rect_width + 15 for slider) */
511 t_symbol* x_color;
512 t_symbol* x_bgcolor;
513} t_fatom;
514
515/* widget helper functions */
516
517
518
519
520static void draw_inlets(t_fatom *x, t_glist *glist, int firsttime, int nin, int nout)
521{
522 int n = nin;
523 int nplus, i;
524 nplus = (n == 1 ? 1 : n-1);
525 DEBUG(post("draw inlet");)
526 for (i = 0; i < n; i++)
527 {
528 int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
529 if (firsttime)
530 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n",
531 glist_getcanvas(glist),
532 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1,
533 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height,
534 x, i);
535 else
536 sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
537 glist_getcanvas(glist), x, i,
538 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 1,
539 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height);
540 }
541 n = nout;
542 nplus = (n == 1 ? 1 : n-1);
543 for (i = 0; i < n; i++)
544 {
545 int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
546 if (firsttime)
547 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
548 glist_getcanvas(glist),
549 onset, text_ypix(&x->x_obj, glist),
550 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1,
551 x, i);
552 else
553 sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
554 glist_getcanvas(glist), x, i,
555 onset, text_ypix(&x->x_obj, glist),
556 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + 1);
557
558 }
559 DEBUG(post("draw inlet end");)
560}
561
562
563static void draw_handle(t_fatom *x, t_glist *glist, int firsttime) {
564 int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH+2);
565
566 if (firsttime)
567 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xhandle\n",
568 glist_getcanvas(glist),
569 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
570 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4,
571 x);
572 else
573 sys_vgui(".x%x.c coords %xhandle %d %d %d %d\n",
574 glist_getcanvas(glist), x,
575 onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
576 onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-4);
577}
578
579static void create_widget(t_fatom *x, t_glist *glist)
580{
581 t_canvas *canvas=glist_getcanvas(glist);
582
583 if (!strcmp(x->x_type->s_name,"vslider")) {
584 x->x_rect_width = x->x_width+15;
585 x->x_rect_height = x->x_max-x->x_min+26;
586
587 sys_vgui("scale .x%x.c.s%x \
588 -sliderlength 10 \
589 -showvalue 0 \
590 -length %d \
591 -resolution 0.01 \
592 -repeatinterval 20 \
593 -from %d -to %d \
594 -width %d \
595 -bg %s \
596 -activebackground %s \
597 -troughcolor %s \
598 -command fatom_cb%x\n",canvas,x,
599 x->x_max-x->x_min+14,
600 x->x_max,
601 x->x_min,
602 x->x_width,
603 x->x_color->s_name,
604 x->x_color->s_name,
605 x->x_bgcolor->s_name,
606 x);
607 } else if (!strcmp(x->x_type->s_name,"hslider")) {
608 x->x_rect_width = x->x_max-x->x_min + 24;
609 x->x_rect_height = x->x_width + 15;
610 sys_vgui("scale .x%x.c.s%x \
611 -sliderlength 10 \
612 -showvalue 0 \
613 -length %d \
614 -resolution 0.01 \
615 -orient horizontal \
616 -repeatinterval 20 \
617 -from %d -to %d \
618 -width %d \
619 -bg %s \
620 -activebackground %s \
621 -troughcolor %s \
622 -command fatom_cb%x\n",canvas,x,
623 x->x_max-x->x_min+14,
624 x->x_min,
625 x->x_max,
626 x->x_width,
627 x->x_color->s_name,
628 x->x_color->s_name,
629 x->x_bgcolor->s_name,
630 x);
631 } else if (!strcmp(x->x_type->s_name,"checkbutton")) {
632 x->x_rect_width = 32;
633 x->x_rect_height = 28;
634 sys_vgui("checkbutton .x%x.c.s%x \
635 -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -text \"%s\" \
636 -bg %s \
637 -activebackground %s \
638 \n",canvas,x,x,x,x,
639 x->x_text->s_name,
640 x->x_color->s_name,
641 x->x_bgcolor->s_name);
642 } else if (!strcmp(x->x_type->s_name,"hradio")) {
643 int i;
644 x->x_rect_width = 8*20;
645 x->x_rect_height = 25;
646 for (i=0;i<8;i++) {
647 sys_vgui("radiobutton .x%x.c.s%x%d \
648 -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i);
649 }
650 /* TODO pack them */
651 } else if (!strcmp(x->x_type->s_name,"vradio")) {
652 int i;
653 x->x_rect_width = 30;
654 x->x_rect_height = 20*8+5;
655 for (i=0;i<8;i++) {
656 sys_vgui("radiobutton .x%x.c.s%x%d \
657 -command { fatom_cb%x $fatom_val%x} -variable fatom_val%x -value %d\n",canvas,x,i,x,x,x,i);
658 }
659 /* TODO pack them */
660 } else {
661 x->x_rect_width = 32;
662 x->x_rect_height = 140;
663 sys_vgui("scale .x%x.c.s%x \
664 -sliderlength 10 \
665 -showvalue 0 \
666 -length 131 \
667 -from 127 -to 0 \
668 -command fatom_cb%x\n",canvas,x,x);
669 }
670
671 /* set the start value */
672 if (!strcmp(x->x_type->s_name,"checkbutton")) {
673 if (x->x_val)
674 sys_vgui(".x%x.c.s%x select\n",canvas,x,x->x_val);
675 else
676 sys_vgui(".x%x.c.s%x deselect\n",canvas,x,x->x_val);
677 } else
678 sys_vgui(".x%x.c.s%x set %f\n",canvas,x,x->x_val);
679
680}
681
682
683
684
685
686static void fatom_drawme(t_fatom *x, t_glist *glist, int firsttime)
687{
688 t_canvas *canvas=glist_getcanvas(glist);// x->x_glist;//glist_getcanvas(glist);
689 DEBUG(post("drawme %d",firsttime);)
690 if (firsttime) {
691 DEBUG(post("glist %x canvas %x",x->x_glist,canvas));
692 create_widget(x,glist);
693 x->x_glist = canvas;
694 sys_vgui(".x%x.c create window %d %d -anchor nw -window .x%x.c.s%x -tags %xS\n",
695 canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2,x->x_glist,x,x);
696
697 }
698 else {
699 sys_vgui(".x%x.c coords %xS \
700%d %d\n",
701 canvas, x,
702 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)+2);
703 }
704 draw_inlets(x, glist, firsttime, 1,1);
705 // draw_handle(x, glist, firsttime);
706
707}
708
709
710static void fatom_erase(t_fatom* x,t_glist* glist)
711{
712 int n;
713
714 DEBUG(post("erase");)
715 sys_vgui("destroy .x%x.c.s%x\n",glist_getcanvas(glist),x);
716
717 sys_vgui(".x%x.c delete %xS\n",glist_getcanvas(glist), x);
718
719 /* inlets and outlets */
720
721 sys_vgui(".x%x.c delete %xi%d\n",glist_getcanvas(glist),x,0);
722 sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,0);
723 sys_vgui(".x%x.c delete %xhandle\n",glist_getcanvas(glist),x,0);
724}
725
726
727
728/* ------------------------ fatom widgetbehaviour----------------------------- */
729
730
731static void fatom_getrect(t_gobj *z, t_glist *owner,
732 int *xp1, int *yp1, int *xp2, int *yp2)
733{
734 int width, height;
735 t_fatom* s = (t_fatom*)z;
736
737 width = s->x_rect_width;
738 height = s->x_rect_height;
739 *xp1 = text_xpix(&s->x_obj, owner);
740 *yp1 = text_ypix(&s->x_obj, owner);
741 *xp2 = text_xpix(&s->x_obj, owner) + width;
742 *yp2 = text_ypix(&s->x_obj, owner) + height;
743}
744
745static void fatom_displace(t_gobj *z, t_glist *glist,
746 int dx, int dy)
747{
748 t_fatom *x = (t_fatom *)z;
749 DEBUG(post("displace");)
750 x->x_obj.te_xpix += dx;
751 x->x_obj.te_ypix += dy;
752 if (glist_isvisible(glist))
753 {
754 sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n",
755 glist_getcanvas(glist), x,
756 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
757 text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height);
758
759 fatom_drawme(x, glist, 0);
760 canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
761 }
762 DEBUG(post("displace end");)
763}
764
765static void fatom_select(t_gobj *z, t_glist *glist, int state)
766{
767 t_fatom *x = (t_fatom *)z;
768 if (state) {
769 sys_vgui(".x%x.c create rectangle \
770%d %d %d %d -tags %xSEL -outline blue\n",
771 glist_getcanvas(glist),
772 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
773 text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height,
774 x);
775 }
776 else {
777 sys_vgui(".x%x.c delete %xSEL\n",
778 glist_getcanvas(glist), x);
779 }
780
781
782
783}
784
785
786static void fatom_activate(t_gobj *z, t_glist *glist, int state)
787{
788/* t_text *x = (t_text *)z;
789 t_rtext *y = glist_findrtext(glist, x);
790 if (z->g_pd != gatom_class) rtext_activate(y, state);*/
791}
792
793static void fatom_delete(t_gobj *z, t_glist *glist)
794{
795 t_text *x = (t_text *)z;
796 canvas_deletelinesfor(glist_getcanvas(glist), x);
797}
798
799
800static void fatom_vis(t_gobj *z, t_glist *glist, int vis)
801{
802 t_fatom* s = (t_fatom*)z;
803 t_rtext *y;
804 DEBUG(post("vis: %d",vis);)
805 if (vis) {
806#ifdef PD_MINOR_VERSION
807 y = (t_rtext *) rtext_new(glist, (t_text *)z);
808#else
809 y = (t_rtext *) rtext_new(glist, (t_text *)z,0,0);
810#endif
811 fatom_drawme(s, glist, 1);
812 }
813 else {
814 y = glist_findrtext(glist, (t_text *)z);
815 fatom_erase(s,glist);
816 rtext_free(y);
817 }
818}
819
820static void fatom_save(t_gobj *z, t_binbuf *b);
821
822t_widgetbehavior fatom_widgetbehavior;
823
824
825
826
827static void fatom_size(t_fatom* x,t_floatarg w,t_floatarg h) {
828 x->x_rect_width = w;
829 x->x_rect_height = h;
830}
831
832static void fatom_color(t_fatom* x,t_symbol* col)
833{
834
835}
836
837
838static void fatom_f(t_fatom* x,t_floatarg f)
839{
840 x->x_val = f;
841 if (x->x_send == &s_)
842 outlet_float(x->x_obj.ob_outlet,f);
843 else
844 if (x->x_send->s_thing) pd_float(x->x_send->s_thing,f);
845}
846
847
848static void fatom_float(t_fatom* x,t_floatarg f)
849{
850 if (glist_isvisible(x->x_glist)) {
851 if (!strcmp(x->x_type->s_name,"checkbutton")) {
852 if (x->x_val)
853 sys_vgui(".x%x.c.s%x select\n",x->x_glist,x,f);
854 else
855 sys_vgui(".x%x.c.s%x deselect\n",x->x_glist,x,f);
856 } else
857 sys_vgui(".x%x.c.s%x set %f\n",x->x_glist,x,f);
858 }
859 fatom_f(x,f);
860}
861
862
863static void fatom_bang(t_fatom* x,t_floatarg f)
864{
865 outlet_float(x->x_obj.ob_outlet,x->x_val);
866}
867
868
869static void fatom_properties(t_gobj *z, t_glist *owner)
870{
871 post("N/I");
872}
873
874
875static void fatom_save(t_gobj *z, t_binbuf *b)
876{
877
878 t_fatom *x = (t_fatom *)z;
879
880 binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"),
881 x->x_obj.te_xpix, x->x_obj.te_ypix ,
882 gensym("fatom"),x->x_type);
883 binbuf_addv(b, ";");
884}
885
886
887static void *fatom_new(t_fatom* x,int argc,t_atom* argv)
888{
889 char buf[256];
890 int n = 0;
891 x->x_glist = canvas_getcurrent();
892
893 x->x_text = gensym("");
894 x->x_max = 127;
895 x->x_min = 0;
896 x->x_width = 15;
897 x->x_color = gensym("grey");
898 x->x_bgcolor = gensym("grey");
899 x->x_send = &s_;
900
901 while (argc) {
902 if (argv->a_type == A_FLOAT) {
903 if (n==0) x->x_max = atom_getfloat(argv);
904 if (n==1) x->x_min = atom_getfloat(argv);
905 if (n==2) x->x_width = atom_getfloat(argv);
906 }
907
908 if (argv->a_type == A_SYMBOL) {
909 post("%d: symbol value %s",n,atom_getsymbol(argv)->s_name);
910 if (n==3) x->x_send = atom_getsymbol(argv);
911 if (n==4) x->x_color = atom_getsymbol(argv);
912 if (n==5) x->x_bgcolor = atom_getsymbol(argv);
913 }
914 argv++;
915 argc--;
916 n++;
917 }
918
919 /* bind to a symbol for slider callback (later make this based on the
920 filepath ??) */
921
922 sprintf(buf,"fatom%x",(t_int)x);
923 x->x_sym = gensym(buf);
924 pd_bind(&x->x_obj.ob_pd, x->x_sym);
925
926 /* pipe startup code to tk */
927
928 sys_vgui("proc fatom_cb%x {v} {\n pd [concat fatom%x f $v \\;]\n }\n",x,x);
929
930 outlet_new(&x->x_obj, &s_float);
931 return (x);
932}
933
934static void fatom_setup_common(t_class* class)
935{
936
937 fatom_widgetbehavior.w_getrectfn = fatom_getrect;
938 fatom_widgetbehavior.w_displacefn = fatom_displace;
939 fatom_widgetbehavior.w_selectfn = fatom_select;
940 fatom_widgetbehavior.w_activatefn = fatom_activate;
941 fatom_widgetbehavior.w_deletefn = fatom_delete;
942 fatom_widgetbehavior.w_visfn = fatom_vis;
943#if PD_MINOR_VERSION < 37
944 fatom_widgetbehavior.w_savefn = fatom_save;
945 fatom_widgetbehavior.w_propertiesfn = NULL;
946#endif
947 fatom_widgetbehavior.w_clickfn = NULL;
948
949 class_addfloat(class, (t_method)fatom_float);
950 class_addbang(class, (t_method)fatom_bang);
951 class_addmethod(class, (t_method)fatom_f, gensym("f"),
952 A_FLOAT, 0);
953
954/*
955 class_addmethod(class, (t_method)fatom_size, gensym("size"),
956 A_FLOAT, A_FLOAT, 0);
957
958 class_addmethod(class, (t_method)fatom_color, gensym("color"),
959 A_SYMBOL, 0);
960*/
961/*
962 class_addmethod(class, (t_method)fatom_open, gensym("open"),
963 A_SYMBOL, 0);
964*/
965
966 class_setwidget(class,&fatom_widgetbehavior);
967#if PD_MINOR_VERSION >= 37
968 class_setsavefn(class,&fatom_save);
969#endif
970}
diff --git a/apps/plugins/pdbox/PDa/extra/filters.h b/apps/plugins/pdbox/PDa/extra/filters.h
new file mode 100644
index 0000000000..72d997e425
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/filters.h
@@ -0,0 +1,148 @@
1/*
2
3 These filter coefficients computations are taken from
4 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
5
6 written by Robert Bristow-Johnson
7
8*/
9
10
11#ifndef __GGEE_FILTERS_H__
12#define __GGEE_FILTERS_H__
13
14
15
16#ifndef M_PI
17#define M_PI 3.141593f
18#endif
19
20
21#include <math.h>
22#define LN2 0.69314718
23#define e_A(g) (pow(10,(g/40.)))
24#define e_omega(f,r) (2.0*M_PI*f/r)
25#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega)))
26#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1)))
27
28
29
30
31typedef struct _rbjfilter
32{
33 t_object x_obj;
34 t_float x_rate;
35 t_float x_freq;
36 t_float x_gain;
37 t_float x_bw;
38} t_rbjfilter;
39
40
41static int check_stability(t_float fb1,
42 t_float fb2,
43 t_float ff1,
44 t_float ff2,
45 t_float ff3)
46{
47 float discriminant = fb1 * fb1 + 4 * fb2;
48
49 if (discriminant < 0) /* imaginary roots -- resonant filter */
50 {
51 /* they're conjugates so we just check that the product
52 is less than one */
53 if (fb2 >= -1.0f) goto stable;
54 }
55 else /* real roots */
56 {
57 /* check that the parabola 1 - fb1 x - fb2 x^2 has a
58 vertex between -1 and 1, and that it's nonnegative
59 at both ends, which implies both roots are in [1-,1]. */
60 if (fb1 <= 2.0f && fb1 >= -2.0f &&
61 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
62 goto stable;
63 }
64 return 0;
65stable:
66 return 1;
67}
68
69
70
71
72
73
74#endif
75/*
76
77 These filter coefficients computations are taken from
78 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
79
80 written by Robert Bristow-Johnson
81
82*/
83
84
85#ifndef __GGEE_FILTERS_H__
86#define __GGEE_FILTERS_H__
87
88
89
90#ifndef M_PI
91#define M_PI 3.141593f
92#endif
93
94
95#include <math.h>
96#define LN2 0.69314718
97#define e_A(g) (pow(10,(g/40.)))
98#define e_omega(f,r) (2.0*M_PI*f/r)
99#define e_alpha(bw,omega) (sin(omega)*sinh(LN2/2. * bw * omega/sin(omega)))
100#define e_beta(a,S) (sqrt((a*a + 1)/(S) - (a-1)*(a-1)))
101
102
103
104
105typedef struct _rbjfilter
106{
107 t_object x_obj;
108 t_float x_rate;
109 t_float x_freq;
110 t_float x_gain;
111 t_float x_bw;
112} t_rbjfilter;
113
114
115static int check_stability(t_float fb1,
116 t_float fb2,
117 t_float ff1,
118 t_float ff2,
119 t_float ff3)
120{
121 float discriminant = fb1 * fb1 + 4 * fb2;
122
123 if (discriminant < 0) /* imaginary roots -- resonant filter */
124 {
125 /* they're conjugates so we just check that the product
126 is less than one */
127 if (fb2 >= -1.0f) goto stable;
128 }
129 else /* real roots */
130 {
131 /* check that the parabola 1 - fb1 x - fb2 x^2 has a
132 vertex between -1 and 1, and that it's nonnegative
133 at both ends, which implies both roots are in [1-,1]. */
134 if (fb1 <= 2.0f && fb1 >= -2.0f &&
135 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
136 goto stable;
137 }
138 return 0;
139stable:
140 return 1;
141}
142
143
144
145
146
147
148#endif
diff --git a/apps/plugins/pdbox/PDa/extra/g_canvas.h b/apps/plugins/pdbox/PDa/extra/g_canvas.h
new file mode 100644
index 0000000000..54ab985feb
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/g_canvas.h
@@ -0,0 +1,1204 @@
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* this file defines the structure for "glists" and related structures and
6functions. "Glists" and "canvases" and "graphs" used to be different
7structures until being unified in version 0.35.
8
9A glist occupies its own window if the "gl_havewindow" flag is set. Its
10appearance on its "parent" or "owner" (if it has one) is as a graph if
11"gl_isgraph" is set, and otherwise as a text box.
12
13A glist is "root" if it has no owner, i.e., a document window. In this
14case "gl_havewindow" is always set.
15
16We maintain a list of root windows, so that we can traverse the whole
17collection of everything in a Pd process.
18
19If a glist has a window it may still not be "mapped." Miniaturized
20windows aren't mapped, for example, but a window is also not mapped
21immediately upon creation. In either case gl_havewindow is true but
22gl_mapped is false.
23
24Closing a non-root window makes it invisible; closing a root destroys it.
25
26A glist that's just a text object on its parent is always "toplevel." An
27embedded glist can switch back and forth to appear as a toplevel by double-
28clicking on it. Single-clicking a text box makes the toplevel become visible
29and raises the window it's in.
30
31If a glist shows up as a graph on its parent, the graph is blanked while the
32glist has its own window, even if miniaturized.
33
34*/
35
36/* NOTE: this file describes Pd implementation details which may change
37in future releases. The public (stable) API is in m_pd.h. */
38
39#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
40extern "C" {
41#endif
42
43/* --------------------- geometry ---------------------------- */
44#define IOWIDTH 7 /* width of an inlet/outlet in pixels */
45#define IOMIDDLE ((IOWIDTH-1)/2)
46#define GLIST_DEFGRAPHWIDTH 200
47#define GLIST_DEFGRAPHHEIGHT 140
48/* ----------------------- data ------------------------------- */
49
50typedef struct _updateheader
51{
52 struct _updateheader *upd_next;
53 unsigned int upd_array:1; /* true if array, false if glist */
54 unsigned int upd_queued:1; /* true if we're queued */
55} t_updateheader;
56
57 /* types to support glists grabbing mouse motion or keys from parent */
58typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy);
59typedef void (*t_glistkeyfn)(void *z, t_floatarg key);
60
61EXTERN_STRUCT _rtext;
62#define t_rtext struct _rtext
63
64EXTERN_STRUCT _gtemplate;
65#define t_gtemplate struct _gtemplate
66
67EXTERN_STRUCT _guiconnect;
68#define t_guiconnect struct _guiconnect
69
70EXTERN_STRUCT _tscalar;
71#define t_tscalar struct _tscalar
72
73EXTERN_STRUCT _canvasenvironment;
74#define t_canvasenvironment struct _canvasenvironment
75
76typedef struct _selection
77{
78 t_gobj *sel_what;
79 struct _selection *sel_next;
80} t_selection;
81
82 /* this structure is instantiated whenever a glist becomes visible. */
83typedef struct _editor
84{
85 t_updateheader e_upd; /* update header structure */
86 t_selection *e_updlist; /* list of objects to update */
87 t_rtext *e_rtext; /* text responder linked list */
88 t_selection *e_selection; /* head of the selection list */
89 t_rtext *e_textedfor; /* the rtext if any that we are editing */
90 t_gobj *e_grab; /* object being "dragged" */
91 t_glistmotionfn e_motionfn; /* ... motion callback */
92 t_glistkeyfn e_keyfn; /* ... keypress callback */
93 t_binbuf *e_connectbuf; /* connections to deleted objects */
94 t_binbuf *e_deleted; /* last stuff we deleted */
95 t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */
96 struct _glist *e_glist; /* glist which owns this */
97 int e_xwas; /* xpos on last mousedown or motion event */
98 int e_ywas; /* ypos, similarly */
99 int e_selectline_index1; /* indices for the selected line if any */
100 int e_selectline_outno; /* (only valid if e_selectedline is set) */
101 int e_selectline_index2;
102 int e_selectline_inno;
103 t_outconnect *e_selectline_tag;
104 unsigned int e_onmotion: 3; /* action to take on motion */
105 unsigned int e_lastmoved: 1; /* one if mouse has moved since click */
106 unsigned int e_textdirty: 1; /* one if e_textedfor has changed */
107 unsigned int e_selectedline: 1; /* one if a line is selected */
108} t_editor;
109
110#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
111#define MA_MOVE 1 /* drag the selection around */
112#define MA_CONNECT 2 /* make a connection */
113#define MA_REGION 3 /* selection region */
114#define MA_PASSOUT 4 /* send on to e_grab */
115#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */
116
117/* editor structure for "garrays". We don't bother to delete and regenerate
118this structure when the "garray" becomes invisible or visible, although we
119could do so if the structure gets big (like the "editor" above.) */
120
121typedef struct _arrayvis
122{
123 t_updateheader av_upd; /* update header structure */
124 t_garray *av_garray; /* owning structure */
125} t_arrayvis;
126
127/* the t_tick structure describes where to draw x and y "ticks" for a glist */
128
129typedef struct _tick /* where to put ticks on x or y axes */
130{
131 float k_point; /* one point to draw a big tick at */
132 float k_inc; /* x or y increment per little tick */
133 int k_lperb; /* little ticks per big; 0 if no ticks to draw */
134} t_tick;
135
136/* the t_glist structure, which describes a list of elements that live on an
137area of a window.
138
139*/
140
141struct _glist
142{
143 t_object gl_obj; /* header in case we're a glist */
144 t_gobj *gl_list; /* the actual data */
145 struct _gstub *gl_stub; /* safe pointer handler */
146 int gl_valid; /* incremented when pointers might be stale */
147 struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */
148 int gl_pixwidth; /* width in pixels (on parent, if a graph) */
149 int gl_pixheight;
150 float gl_x1; /* bounding rectangle in our own coordinates */
151 float gl_y1;
152 float gl_x2;
153 float gl_y2;
154 int gl_screenx1; /* screen coordinates when toplevel */
155 int gl_screeny1;
156 int gl_screenx2;
157 int gl_screeny2;
158 t_tick gl_xtick; /* ticks marking X values */
159 int gl_nxlabels; /* number of X coordinate labels */
160 t_symbol **gl_xlabel; /* ... an array to hold them */
161 float gl_xlabely; /* ... and their Y coordinates */
162 t_tick gl_ytick; /* same as above for Y ticks and labels */
163 int gl_nylabels;
164 t_symbol **gl_ylabel;
165 float gl_ylabelx;
166 t_editor *gl_editor; /* editor structure when visible */
167 t_symbol *gl_name; /* symbol bound here */
168 int gl_font; /* nominal font size in points, e.g., 10 */
169 struct _glist *gl_next; /* link in list of toplevels */
170 t_canvasenvironment *gl_env; /* root canvases and abstractions only */
171 unsigned int gl_havewindow:1; /* true if we own a window */
172 unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */
173 unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */
174 unsigned int gl_loading:1; /* am now loading from file */
175 unsigned int gl_willvis:1; /* make me visible after loading */
176 unsigned int gl_edit:1; /* edit mode */
177 unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */
178 unsigned int gl_stretch:1; /* stretch contents on resize */
179 unsigned int gl_isgraph:1; /* show as graph on parent */
180};
181
182#define gl_gobj gl_obj.te_g
183#define gl_pd gl_gobj.g_pd
184
185/* a data structure to describe a field in a pure datum */
186
187#define DT_FLOAT 0
188#define DT_SYMBOL 1
189#define DT_LIST 2
190#define DT_ARRAY 3
191
192typedef struct _dataslot
193{
194 int ds_type;
195 t_symbol *ds_name;
196 t_symbol *ds_arraytemplate; /* filled in for arrays only */
197} t_dataslot;
198
199
200/* T.Grill - changed t_pd member to t_pdobj to avoid name clashed */
201typedef struct _template
202{
203 t_pd t_pdobj; /* header */
204 struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */
205 t_symbol *t_sym; /* name */
206 int t_n; /* number of dataslots (fields) */
207 t_dataslot *t_vec; /* array of dataslots */
208} t_template;
209
210struct _array
211{
212 int a_n; /* number of elements */
213 int a_elemsize; /* size in bytes; LATER get this from template */
214 char *a_vec; /* array of elements */
215 t_symbol *a_templatesym; /* template for elements */
216 int a_valid; /* protection against stale pointers into array */
217 t_gpointer a_gp; /* pointer to scalar or array element we're in */
218 t_gstub *a_stub;
219};
220
221 /* structure for traversing all the connections in a glist */
222typedef struct _linetraverser
223{
224 t_canvas *tr_x;
225 t_object *tr_ob;
226 int tr_nout;
227 int tr_outno;
228 t_object *tr_ob2;
229 t_outlet *tr_outlet;
230 t_inlet *tr_inlet;
231 int tr_nin;
232 int tr_inno;
233 int tr_x11, tr_y11, tr_x12, tr_y12;
234 int tr_x21, tr_y21, tr_x22, tr_y22;
235 int tr_lx1, tr_ly1, tr_lx2, tr_ly2;
236 t_outconnect *tr_nextoc;
237 int tr_nextoutno;
238} t_linetraverser;
239
240/* function types used to define graphical behavior for gobjs, a bit like X
241widgets. We don't use Pd methods because Pd's typechecking can't specify the
242types of pointer arguments. Also it's more convenient this way, since
243every "patchable" object can just get the "text" behaviors. */
244
245 /* Call this to get a gobj's bounding rectangle in pixels */
246typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist,
247 int *x1, int *y1, int *x2, int *y2);
248 /* and this to displace a gobj: */
249typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy);
250 /* change color to show selection: */
251typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state);
252 /* change appearance to show activation/deactivation: */
253typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state);
254 /* warn a gobj it's about to be deleted */
255typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist);
256 /* making visible or invisible */
257typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag);
258 /* field a mouse click (when not in "edit" mode) */
259typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist,
260 int xpix, int ypix, int shift, int alt, int dbl, int doit);
261 /* ... and later, resizing; getting/setting font or color... */
262
263struct _widgetbehavior
264{
265 t_getrectfn w_getrectfn;
266 t_displacefn w_displacefn;
267 t_selectfn w_selectfn;
268 t_activatefn w_activatefn;
269 t_deletefn w_deletefn;
270 t_visfn w_visfn;
271 t_clickfn w_clickfn;
272};
273
274/* -------- behaviors for scalars defined by objects in template --------- */
275/* these are set by "drawing commands" in g_template.c which add appearance to
276scalars, which live in some other window. If the scalar is just included
277in a canvas the "parent" is a misnomer. There is also a text scalar object
278which really does draw the scalar on the parent window; see g_scalar.c. */
279
280/* note how the click function wants the whole scalar, not the "data", so
281doesn't work on array elements... LATER reconsider this */
282
283 /* bounding rectangle: */
284typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist,
285 t_word *data, t_template *tmpl, float basex, float basey,
286 int *x1, int *y1, int *x2, int *y2);
287 /* displace it */
288typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist,
289 t_word *data, t_template *tmpl, float basex, float basey,
290 int dx, int dy);
291 /* change color to show selection */
292typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist,
293 t_word *data, t_template *tmpl, float basex, float basey,
294 int state);
295 /* change appearance to show activation/deactivation: */
296typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist,
297 t_word *data, t_template *tmpl, float basex, float basey,
298 int state);
299 /* making visible or invisible */
300typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist,
301 t_word *data, t_template *tmpl, float basex, float basey,
302 int flag);
303 /* field a mouse click */
304typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist,
305 t_scalar *sc, t_template *tmpl, float basex, float basey,
306 int xpix, int ypix, int shift, int alt, int dbl, int doit);
307
308struct _parentwidgetbehavior
309{
310 t_parentgetrectfn w_parentgetrectfn;
311 t_parentdisplacefn w_parentdisplacefn;
312 t_parentselectfn w_parentselectfn;
313 t_parentactivatefn w_parentactivatefn;
314 t_parentvisfn w_parentvisfn;
315 t_parentclickfn w_parentclickfn;
316};
317
318 /* cursor definitions; used as return value for t_parentclickfn */
319#define CURSOR_RUNMODE_NOTHING 0
320#define CURSOR_RUNMODE_CLICKME 1
321#define CURSOR_RUNMODE_THICKEN 2
322#define CURSOR_RUNMODE_ADDPOINT 3
323#define CURSOR_EDITMODE_NOTHING 4
324#define CURSOR_EDITMODE_CONNECT 5
325#define CURSOR_EDITMODE_DISCONNECT 6
326EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);
327
328extern t_canvas *canvas_editing; /* last canvas to start text edting */
329extern t_canvas *canvas_whichfind; /* last canvas we did a find in */
330extern t_canvas *canvas_list; /* list of all root canvases */
331extern t_class *vinlet_class, *voutlet_class;
332extern int glist_valid; /* incremented when pointers might be stale */
333
334/* ------------------- functions on any gobj ----------------------------- */
335EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1,
336 int *x2, int *y2);
337EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy);
338EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state);
339EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state);
340EXTERN void gobj_delete(t_gobj *x, t_glist *owner);
341EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag);
342EXTERN int gobj_click(t_gobj *x, struct _glist *glist,
343 int xpix, int ypix, int shift, int alt, int dbl, int doit);
344EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
345EXTERN void gobj_properties(t_gobj *x, struct _glist *glist);
346EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
347
348/* -------------------- functions on glists --------------------- */
349EXTERN t_glist *glist_new( void);
350EXTERN void glist_init(t_glist *x);
351EXTERN void glist_add(t_glist *x, t_gobj *g);
352EXTERN void glist_cleanup(t_glist *x);
353EXTERN void glist_free(t_glist *x);
354
355EXTERN void glist_clear(t_glist *x);
356EXTERN t_canvas *glist_getcanvas(t_glist *x);
357EXTERN int glist_isselected(t_glist *x, t_gobj *y);
358EXTERN void glist_select(t_glist *x, t_gobj *y);
359EXTERN void glist_deselect(t_glist *x, t_gobj *y);
360EXTERN void glist_noselect(t_glist *x);
361EXTERN void glist_selectall(t_glist *x);
362EXTERN void glist_delete(t_glist *x, t_gobj *y);
363EXTERN void glist_retext(t_glist *x, t_text *y);
364EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
365 t_glistkeyfn keyfn, int xpos, int ypos);
366EXTERN int glist_isvisible(t_glist *x);
367EXTERN int glist_istoplevel(t_glist *x);
368EXTERN t_glist *glist_findgraph(t_glist *x);
369EXTERN int glist_getfont(t_glist *x);
370EXTERN void glist_sort(t_glist *canvas);
371EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format);
372EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format);
373
374EXTERN float glist_pixelstox(t_glist *x, float xpix);
375EXTERN float glist_pixelstoy(t_glist *x, float ypix);
376EXTERN float glist_xtopixels(t_glist *x, float xval);
377EXTERN float glist_ytopixels(t_glist *x, float yval);
378EXTERN float glist_dpixtodx(t_glist *x, float dxpix);
379EXTERN float glist_dpixtody(t_glist *x, float dypix);
380
381EXTERN void glist_redrawitem(t_glist *owner, t_gobj *gobj);
382EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval);
383EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv);
384EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym,
385 float x1, float y1, float x2, float y2,
386 float px1, float py1, float px2, float py2);
387EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name,
388 t_floatarg size, t_floatarg saveit, t_floatarg newgraph);
389EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething);
390EXTERN int glist_isgraph(t_glist *x);
391EXTERN void glist_redraw(t_glist *x);
392EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
393 char *tag, int x1, int y1, int x2, int y2);
394EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag);
395EXTERN void canvas_create_editor(t_glist *x, int createit);
396void canvas_deletelinesforio(t_canvas *x, t_text *text,
397 t_inlet *inp, t_outlet *outp);
398
399
400/* -------------------- functions on texts ------------------------- */
401EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize);
402EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag,
403 int width, int height, int firsttime);
404EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag);
405EXTERN int text_xcoord(t_text *x, t_glist *glist);
406EXTERN int text_ycoord(t_text *x, t_glist *glist);
407EXTERN int text_xpix(t_text *x, t_glist *glist);
408EXTERN int text_ypix(t_text *x, t_glist *glist);
409EXTERN int text_shouldvis(t_text *x, t_glist *glist);
410
411/* -------------------- functions on rtexts ------------------------- */
412#define RTEXT_DOWN 1
413#define RTEXT_DRAG 2
414#define RTEXT_DBL 3
415#define RTEXT_SHIFT 4
416
417EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who);
418EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who);
419EXTERN void rtext_draw(t_rtext *x);
420EXTERN void rtext_erase(t_rtext *x);
421EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x);
422EXTERN int rtext_height(t_rtext *x);
423EXTERN void rtext_displace(t_rtext *x, int dx, int dy);
424EXTERN void rtext_select(t_rtext *x, int state);
425EXTERN void rtext_activate(t_rtext *x, int state);
426EXTERN void rtext_free(t_rtext *x);
427EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s);
428EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag);
429EXTERN void rtext_retext(t_rtext *x);
430EXTERN int rtext_width(t_rtext *x);
431EXTERN int rtext_height(t_rtext *x);
432EXTERN char *rtext_gettag(t_rtext *x);
433EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
434
435/* -------------------- functions on canvases ------------------------ */
436EXTERN t_class *canvas_class;
437
438EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv);
439EXTERN t_symbol *canvas_makebindsym(t_symbol *s);
440EXTERN void canvas_vistext(t_canvas *x, t_text *y);
441EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text);
442EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text);
443EXTERN void canvas_stowconnections(t_canvas *x);
444EXTERN void canvas_restoreconnections(t_canvas *x);
445EXTERN void canvas_redraw(t_canvas *x);
446
447EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym);
448EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip);
449EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym);
450EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op);
451EXTERN void canvas_redrawallfortemplate(t_canvas *tmpl);
452EXTERN void canvas_zapallfortemplate(t_canvas *tmpl);
453EXTERN void canvas_setusedastemplate(t_canvas *x);
454EXTERN t_canvas *canvas_getcurrent(void);
455EXTERN void canvas_setcurrent(t_canvas *x);
456EXTERN void canvas_unsetcurrent(t_canvas *x);
457EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
458EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
459EXTERN void canvas_dirty(t_canvas *x, t_int n);
460EXTERN int canvas_getfont(t_canvas *x);
461typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3);
462
463EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn,
464 t_int x1, t_int x2, t_int x3);
465
466EXTERN void canvas_resortinlets(t_canvas *x);
467EXTERN void canvas_resortoutlets(t_canvas *x);
468EXTERN void canvas_free(t_canvas *x);
469EXTERN void canvas_updatewindowlist( void);
470EXTERN void canvas_editmode(t_canvas *x, t_floatarg yesplease);
471EXTERN int canvas_isabstraction(t_canvas *x);
472EXTERN int canvas_istable(t_canvas *x);
473EXTERN int canvas_showtext(t_canvas *x);
474EXTERN void canvas_vis(t_canvas *x, t_floatarg f);
475EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x);
476EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir);
477EXTERN void canvas_loadbang(t_canvas *x);
478EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
479 int *x1p, int *y1p, int *x2p, int *y2p);
480EXTERN int canvas_setdeleting(t_canvas *x, int flag);
481
482typedef void (*t_undofn)(t_canvas *canvas, void *buf,
483 int action); /* a function that does UNDO/REDO */
484#define UNDO_FREE 0 /* free current undo/redo buffer */
485#define UNDO_UNDO 1 /* undo */
486#define UNDO_REDO 2 /* redo */
487EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
488 const char *name);
489EXTERN void canvas_noundo(t_canvas *x);
490EXTERN int canvas_getindex(t_canvas *x, t_gobj *y);
491
492/* T.Grill - made public for dynamic object creation */
493/* in g_editor.c */
494EXTERN void canvas_connect(t_canvas *x,
495 t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno);
496EXTERN void canvas_disconnect(t_canvas *x,
497 float index1, float outno, float index2, float inno);
498EXTERN int canvas_isconnected (t_canvas *x,
499 t_text *ob1, int n1, t_text *ob2, int n2);
500EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy);
501
502
503/* ---- functions on canvasses as objects --------------------- */
504
505EXTERN void canvas_fattenforscalars(t_canvas *x,
506 int *x1, int *y1, int *x2, int *y2);
507EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis);
508EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift,
509 int alt, int dbl, int doit);
510EXTERN t_glist *canvas_getglistonsuper(void);
511
512EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x);
513EXTERN t_outconnect *linetraverser_next(t_linetraverser *t);
514EXTERN void linetraverser_skipobject(t_linetraverser *t);
515
516/* --------------------- functions on tscalars --------------------- */
517
518EXTERN void tscalar_getrect(t_tscalar *x, t_glist *owner,
519 int *xp1, int *yp1, int *xp2, int *yp2);
520EXTERN void tscalar_vis(t_tscalar *x, t_glist *owner, int flag);
521EXTERN int tscalar_click(t_tscalar *x, int xpix, int ypix, int shift,
522 int alt, int dbl, int doit);
523
524/* --------- functions on garrays (graphical arrays) -------------------- */
525
526EXTERN t_template *garray_template(t_garray *x);
527
528/* -------------------- arrays --------------------- */
529EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl,
530 t_floatarg f, t_floatarg saveit);
531EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent);
532EXTERN void array_resize(t_array *x, t_template *tmpl, int n);
533EXTERN void array_free(t_array *x);
534
535/* --------------------- gpointers and stubs ---------------- */
536EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a);
537EXTERN void gstub_cutoff(t_gstub *gs);
538EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x);
539
540/* --------------------- scalars ------------------------- */
541EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp);
542EXTERN void word_restore(t_word *wp, t_template *tmpl,
543 int argc, t_atom *argv);
544EXTERN t_scalar *scalar_new(t_glist *owner,
545 t_symbol *templatesym);
546EXTERN void scalar_getbasexy(t_scalar *x, float *basex, float *basey);
547
548/* ------helper routines for "garrays" and "plots" -------------- */
549EXTERN int array_doclick(t_array *array, t_glist *glist, t_gobj *gobj,
550 t_symbol *elemtemplatesym,
551 float linewidth, float xloc, float xinc, float yloc,
552 int xpix, int ypix, int shift, int alt, int dbl, int doit);
553
554EXTERN void array_getcoordinate(t_glist *glist,
555 char *elem, int xonset, int yonset, int wonset, int indx,
556 float basex, float basey, float xinc,
557 float *xp, float *yp, float *wp);
558
559EXTERN int array_getfields(t_symbol *elemtemplatesym,
560 t_canvas **elemtemplatecanvasp,
561 t_template **elemtemplatep, int *elemsizep,
562 int *xonsetp, int *yonsetp, int *wonsetp);
563
564/* --------------------- templates ------------------------- */
565EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv);
566EXTERN void template_free(t_template *x);
567EXTERN int template_match(t_template *x1, t_template *x2);
568EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset,
569 int *p_type, t_symbol **p_arraytype);
570EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp,
571 int loud);
572EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp,
573 t_float f, int loud);
574EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
575 t_word *wp, int loud);
576EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
577 t_word *wp, t_symbol *s, int loud);
578
579EXTERN t_template *gtemplate_get(t_gtemplate *x);
580EXTERN t_template *template_findbyname(t_symbol *s);
581EXTERN t_canvas *template_findcanvas(t_template *tmpl);
582
583EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname,
584 t_word *wp, int loud);
585EXTERN void template_setfloat(t_template *x, t_symbol *fieldname,
586 t_word *wp, t_float f, int loud);
587EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
588 t_word *wp, int loud);
589EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
590 t_word *wp, t_symbol *s, int loud);
591
592/* ----------------------- guiconnects, g_guiconnect.c --------- */
593EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym);
594EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);
595
596/* ------------- IEMGUI routines used in other g_ files ---------------- */
597EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s);
598EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s);
599
600#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
601}
602#endif
603/* Copyright (c) 1997-1999 Miller Puckette.
604* For information on usage and redistribution, and for a DISCLAIMER OF ALL
605* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
606
607/* this file defines the structure for "glists" and related structures and
608functions. "Glists" and "canvases" and "graphs" used to be different
609structures until being unified in version 0.35.
610
611A glist occupies its own window if the "gl_havewindow" flag is set. Its
612appearance on its "parent" or "owner" (if it has one) is as a graph if
613"gl_isgraph" is set, and otherwise as a text box.
614
615A glist is "root" if it has no owner, i.e., a document window. In this
616case "gl_havewindow" is always set.
617
618We maintain a list of root windows, so that we can traverse the whole
619collection of everything in a Pd process.
620
621If a glist has a window it may still not be "mapped." Miniaturized
622windows aren't mapped, for example, but a window is also not mapped
623immediately upon creation. In either case gl_havewindow is true but
624gl_mapped is false.
625
626Closing a non-root window makes it invisible; closing a root destroys it.
627
628A glist that's just a text object on its parent is always "toplevel." An
629embedded glist can switch back and forth to appear as a toplevel by double-
630clicking on it. Single-clicking a text box makes the toplevel become visible
631and raises the window it's in.
632
633If a glist shows up as a graph on its parent, the graph is blanked while the
634glist has its own window, even if miniaturized.
635
636*/
637
638/* NOTE: this file describes Pd implementation details which may change
639in future releases. The public (stable) API is in m_pd.h. */
640
641#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
642extern "C" {
643#endif
644
645/* --------------------- geometry ---------------------------- */
646#define IOWIDTH 7 /* width of an inlet/outlet in pixels */
647#define IOMIDDLE ((IOWIDTH-1)/2)
648#define GLIST_DEFGRAPHWIDTH 200
649#define GLIST_DEFGRAPHHEIGHT 140
650/* ----------------------- data ------------------------------- */
651
652typedef struct _updateheader
653{
654 struct _updateheader *upd_next;
655 unsigned int upd_array:1; /* true if array, false if glist */
656 unsigned int upd_queued:1; /* true if we're queued */
657} t_updateheader;
658
659 /* types to support glists grabbing mouse motion or keys from parent */
660typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy);
661typedef void (*t_glistkeyfn)(void *z, t_floatarg key);
662
663EXTERN_STRUCT _rtext;
664#define t_rtext struct _rtext
665
666EXTERN_STRUCT _gtemplate;
667#define t_gtemplate struct _gtemplate
668
669EXTERN_STRUCT _guiconnect;
670#define t_guiconnect struct _guiconnect
671
672EXTERN_STRUCT _tscalar;
673#define t_tscalar struct _tscalar
674
675EXTERN_STRUCT _canvasenvironment;
676#define t_canvasenvironment struct _canvasenvironment
677
678typedef struct _selection
679{
680 t_gobj *sel_what;
681 struct _selection *sel_next;
682} t_selection;
683
684 /* this structure is instantiated whenever a glist becomes visible. */
685typedef struct _editor
686{
687 t_updateheader e_upd; /* update header structure */
688 t_selection *e_updlist; /* list of objects to update */
689 t_rtext *e_rtext; /* text responder linked list */
690 t_selection *e_selection; /* head of the selection list */
691 t_rtext *e_textedfor; /* the rtext if any that we are editing */
692 t_gobj *e_grab; /* object being "dragged" */
693 t_glistmotionfn e_motionfn; /* ... motion callback */
694 t_glistkeyfn e_keyfn; /* ... keypress callback */
695 t_binbuf *e_connectbuf; /* connections to deleted objects */
696 t_binbuf *e_deleted; /* last stuff we deleted */
697 t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */
698 struct _glist *e_glist; /* glist which owns this */
699 int e_xwas; /* xpos on last mousedown or motion event */
700 int e_ywas; /* ypos, similarly */
701 int e_selectline_index1; /* indices for the selected line if any */
702 int e_selectline_outno; /* (only valid if e_selectedline is set) */
703 int e_selectline_index2;
704 int e_selectline_inno;
705 t_outconnect *e_selectline_tag;
706 unsigned int e_onmotion: 3; /* action to take on motion */
707 unsigned int e_lastmoved: 1; /* one if mouse has moved since click */
708 unsigned int e_textdirty: 1; /* one if e_textedfor has changed */
709 unsigned int e_selectedline: 1; /* one if a line is selected */
710} t_editor;
711
712#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
713#define MA_MOVE 1 /* drag the selection around */
714#define MA_CONNECT 2 /* make a connection */
715#define MA_REGION 3 /* selection region */
716#define MA_PASSOUT 4 /* send on to e_grab */
717#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */
718
719/* editor structure for "garrays". We don't bother to delete and regenerate
720this structure when the "garray" becomes invisible or visible, although we
721could do so if the structure gets big (like the "editor" above.) */
722
723typedef struct _arrayvis
724{
725 t_updateheader av_upd; /* update header structure */
726 t_garray *av_garray; /* owning structure */
727} t_arrayvis;
728
729/* the t_tick structure describes where to draw x and y "ticks" for a glist */
730
731typedef struct _tick /* where to put ticks on x or y axes */
732{
733 float k_point; /* one point to draw a big tick at */
734 float k_inc; /* x or y increment per little tick */
735 int k_lperb; /* little ticks per big; 0 if no ticks to draw */
736} t_tick;
737
738/* the t_glist structure, which describes a list of elements that live on an
739area of a window.
740
741*/
742
743struct _glist
744{
745 t_object gl_obj; /* header in case we're a glist */
746 t_gobj *gl_list; /* the actual data */
747 struct _gstub *gl_stub; /* safe pointer handler */
748 int gl_valid; /* incremented when pointers might be stale */
749 struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */
750 int gl_pixwidth; /* width in pixels (on parent, if a graph) */
751 int gl_pixheight;
752 float gl_x1; /* bounding rectangle in our own coordinates */
753 float gl_y1;
754 float gl_x2;
755 float gl_y2;
756 int gl_screenx1; /* screen coordinates when toplevel */
757 int gl_screeny1;
758 int gl_screenx2;
759 int gl_screeny2;
760 t_tick gl_xtick; /* ticks marking X values */
761 int gl_nxlabels; /* number of X coordinate labels */
762 t_symbol **gl_xlabel; /* ... an array to hold them */
763 float gl_xlabely; /* ... and their Y coordinates */
764 t_tick gl_ytick; /* same as above for Y ticks and labels */
765 int gl_nylabels;
766 t_symbol **gl_ylabel;
767 float gl_ylabelx;
768 t_editor *gl_editor; /* editor structure when visible */
769 t_symbol *gl_name; /* symbol bound here */
770 int gl_font; /* nominal font size in points, e.g., 10 */
771 struct _glist *gl_next; /* link in list of toplevels */
772 t_canvasenvironment *gl_env; /* root canvases and abstractions only */
773 unsigned int gl_havewindow:1; /* true if we own a window */
774 unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */
775 unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */
776 unsigned int gl_loading:1; /* am now loading from file */
777 unsigned int gl_willvis:1; /* make me visible after loading */
778 unsigned int gl_edit:1; /* edit mode */
779 unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */
780 unsigned int gl_stretch:1; /* stretch contents on resize */
781 unsigned int gl_isgraph:1; /* show as graph on parent */
782};
783
784#define gl_gobj gl_obj.te_g
785#define gl_pd gl_gobj.g_pd
786
787/* a data structure to describe a field in a pure datum */
788
789#define DT_FLOAT 0
790#define DT_SYMBOL 1
791#define DT_LIST 2
792#define DT_ARRAY 3
793
794typedef struct _dataslot
795{
796 int ds_type;
797 t_symbol *ds_name;
798 t_symbol *ds_arraytemplate; /* filled in for arrays only */
799} t_dataslot;
800
801
802/* T.Grill - changed t_pd member to t_pdobj to avoid name clashed */
803typedef struct _template
804{
805 t_pd t_pdobj; /* header */
806 struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */
807 t_symbol *t_sym; /* name */
808 int t_n; /* number of dataslots (fields) */
809 t_dataslot *t_vec; /* array of dataslots */
810} t_template;
811
812struct _array
813{
814 int a_n; /* number of elements */
815 int a_elemsize; /* size in bytes; LATER get this from template */
816 char *a_vec; /* array of elements */
817 t_symbol *a_templatesym; /* template for elements */
818 int a_valid; /* protection against stale pointers into array */
819 t_gpointer a_gp; /* pointer to scalar or array element we're in */
820 t_gstub *a_stub;
821};
822
823 /* structure for traversing all the connections in a glist */
824typedef struct _linetraverser
825{
826 t_canvas *tr_x;
827 t_object *tr_ob;
828 int tr_nout;
829 int tr_outno;
830 t_object *tr_ob2;
831 t_outlet *tr_outlet;
832 t_inlet *tr_inlet;
833 int tr_nin;
834 int tr_inno;
835 int tr_x11, tr_y11, tr_x12, tr_y12;
836 int tr_x21, tr_y21, tr_x22, tr_y22;
837 int tr_lx1, tr_ly1, tr_lx2, tr_ly2;
838 t_outconnect *tr_nextoc;
839 int tr_nextoutno;
840} t_linetraverser;
841
842/* function types used to define graphical behavior for gobjs, a bit like X
843widgets. We don't use Pd methods because Pd's typechecking can't specify the
844types of pointer arguments. Also it's more convenient this way, since
845every "patchable" object can just get the "text" behaviors. */
846
847 /* Call this to get a gobj's bounding rectangle in pixels */
848typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist,
849 int *x1, int *y1, int *x2, int *y2);
850 /* and this to displace a gobj: */
851typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy);
852 /* change color to show selection: */
853typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state);
854 /* change appearance to show activation/deactivation: */
855typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state);
856 /* warn a gobj it's about to be deleted */
857typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist);
858 /* making visible or invisible */
859typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag);
860 /* field a mouse click (when not in "edit" mode) */
861typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist,
862 int xpix, int ypix, int shift, int alt, int dbl, int doit);
863 /* ... and later, resizing; getting/setting font or color... */
864
865struct _widgetbehavior
866{
867 t_getrectfn w_getrectfn;
868 t_displacefn w_displacefn;
869 t_selectfn w_selectfn;
870 t_activatefn w_activatefn;
871 t_deletefn w_deletefn;
872 t_visfn w_visfn;
873 t_clickfn w_clickfn;
874};
875
876/* -------- behaviors for scalars defined by objects in template --------- */
877/* these are set by "drawing commands" in g_template.c which add appearance to
878scalars, which live in some other window. If the scalar is just included
879in a canvas the "parent" is a misnomer. There is also a text scalar object
880which really does draw the scalar on the parent window; see g_scalar.c. */
881
882/* note how the click function wants the whole scalar, not the "data", so
883doesn't work on array elements... LATER reconsider this */
884
885 /* bounding rectangle: */
886typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist,
887 t_word *data, t_template *tmpl, float basex, float basey,
888 int *x1, int *y1, int *x2, int *y2);
889 /* displace it */
890typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist,
891 t_word *data, t_template *tmpl, float basex, float basey,
892 int dx, int dy);
893 /* change color to show selection */
894typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist,
895 t_word *data, t_template *tmpl, float basex, float basey,
896 int state);
897 /* change appearance to show activation/deactivation: */
898typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist,
899 t_word *data, t_template *tmpl, float basex, float basey,
900 int state);
901 /* making visible or invisible */
902typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist,
903 t_word *data, t_template *tmpl, float basex, float basey,
904 int flag);
905 /* field a mouse click */
906typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist,
907 t_scalar *sc, t_template *tmpl, float basex, float basey,
908 int xpix, int ypix, int shift, int alt, int dbl, int doit);
909
910struct _parentwidgetbehavior
911{
912 t_parentgetrectfn w_parentgetrectfn;
913 t_parentdisplacefn w_parentdisplacefn;
914 t_parentselectfn w_parentselectfn;
915 t_parentactivatefn w_parentactivatefn;
916 t_parentvisfn w_parentvisfn;
917 t_parentclickfn w_parentclickfn;
918};
919
920 /* cursor definitions; used as return value for t_parentclickfn */
921#define CURSOR_RUNMODE_NOTHING 0
922#define CURSOR_RUNMODE_CLICKME 1
923#define CURSOR_RUNMODE_THICKEN 2
924#define CURSOR_RUNMODE_ADDPOINT 3
925#define CURSOR_EDITMODE_NOTHING 4
926#define CURSOR_EDITMODE_CONNECT 5
927#define CURSOR_EDITMODE_DISCONNECT 6
928EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);
929
930extern t_canvas *canvas_editing; /* last canvas to start text edting */
931extern t_canvas *canvas_whichfind; /* last canvas we did a find in */
932extern t_canvas *canvas_list; /* list of all root canvases */
933extern t_class *vinlet_class, *voutlet_class;
934extern int glist_valid; /* incremented when pointers might be stale */
935
936/* ------------------- functions on any gobj ----------------------------- */
937EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1,
938 int *x2, int *y2);
939EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy);
940EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state);
941EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state);
942EXTERN void gobj_delete(t_gobj *x, t_glist *owner);
943EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag);
944EXTERN int gobj_click(t_gobj *x, struct _glist *glist,
945 int xpix, int ypix, int shift, int alt, int dbl, int doit);
946EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
947EXTERN void gobj_properties(t_gobj *x, struct _glist *glist);
948EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
949
950/* -------------------- functions on glists --------------------- */
951EXTERN t_glist *glist_new( void);
952EXTERN void glist_init(t_glist *x);
953EXTERN void glist_add(t_glist *x, t_gobj *g);
954EXTERN void glist_cleanup(t_glist *x);
955EXTERN void glist_free(t_glist *x);
956
957EXTERN void glist_clear(t_glist *x);
958EXTERN t_canvas *glist_getcanvas(t_glist *x);
959EXTERN int glist_isselected(t_glist *x, t_gobj *y);
960EXTERN void glist_select(t_glist *x, t_gobj *y);
961EXTERN void glist_deselect(t_glist *x, t_gobj *y);
962EXTERN void glist_noselect(t_glist *x);
963EXTERN void glist_selectall(t_glist *x);
964EXTERN void glist_delete(t_glist *x, t_gobj *y);
965EXTERN void glist_retext(t_glist *x, t_text *y);
966EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
967 t_glistkeyfn keyfn, int xpos, int ypos);
968EXTERN int glist_isvisible(t_glist *x);
969EXTERN int glist_istoplevel(t_glist *x);
970EXTERN t_glist *glist_findgraph(t_glist *x);
971EXTERN int glist_getfont(t_glist *x);
972EXTERN void glist_sort(t_glist *canvas);
973EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format);
974EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format);
975
976EXTERN float glist_pixelstox(t_glist *x, float xpix);
977EXTERN float glist_pixelstoy(t_glist *x, float ypix);
978EXTERN float glist_xtopixels(t_glist *x, float xval);
979EXTERN float glist_ytopixels(t_glist *x, float yval);
980EXTERN float glist_dpixtodx(t_glist *x, float dxpix);
981EXTERN float glist_dpixtody(t_glist *x, float dypix);
982
983EXTERN void glist_redrawitem(t_glist *owner, t_gobj *gobj);
984EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval);
985EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv);
986EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym,
987 float x1, float y1, float x2, float y2,
988 float px1, float py1, float px2, float py2);
989EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name,
990 t_floatarg size, t_floatarg saveit, t_floatarg newgraph);
991EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething);
992EXTERN int glist_isgraph(t_glist *x);
993EXTERN void glist_redraw(t_glist *x);
994EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
995 char *tag, int x1, int y1, int x2, int y2);
996EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag);
997EXTERN void canvas_create_editor(t_glist *x, int createit);
998void canvas_deletelinesforio(t_canvas *x, t_text *text,
999 t_inlet *inp, t_outlet *outp);
1000
1001
1002/* -------------------- functions on texts ------------------------- */
1003EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize);
1004EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag,
1005 int width, int height, int firsttime);
1006EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag);
1007EXTERN int text_xcoord(t_text *x, t_glist *glist);
1008EXTERN int text_ycoord(t_text *x, t_glist *glist);
1009EXTERN int text_xpix(t_text *x, t_glist *glist);
1010EXTERN int text_ypix(t_text *x, t_glist *glist);
1011EXTERN int text_shouldvis(t_text *x, t_glist *glist);
1012
1013/* -------------------- functions on rtexts ------------------------- */
1014#define RTEXT_DOWN 1
1015#define RTEXT_DRAG 2
1016#define RTEXT_DBL 3
1017#define RTEXT_SHIFT 4
1018
1019EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who);
1020EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who);
1021EXTERN void rtext_draw(t_rtext *x);
1022EXTERN void rtext_erase(t_rtext *x);
1023EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x);
1024EXTERN int rtext_height(t_rtext *x);
1025EXTERN void rtext_displace(t_rtext *x, int dx, int dy);
1026EXTERN void rtext_select(t_rtext *x, int state);
1027EXTERN void rtext_activate(t_rtext *x, int state);
1028EXTERN void rtext_free(t_rtext *x);
1029EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s);
1030EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag);
1031EXTERN void rtext_retext(t_rtext *x);
1032EXTERN int rtext_width(t_rtext *x);
1033EXTERN int rtext_height(t_rtext *x);
1034EXTERN char *rtext_gettag(t_rtext *x);
1035EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
1036
1037/* -------------------- functions on canvases ------------------------ */
1038EXTERN t_class *canvas_class;
1039
1040EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv);
1041EXTERN t_symbol *canvas_makebindsym(t_symbol *s);
1042EXTERN void canvas_vistext(t_canvas *x, t_text *y);
1043EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text);
1044EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text);
1045EXTERN void canvas_stowconnections(t_canvas *x);
1046EXTERN void canvas_restoreconnections(t_canvas *x);
1047EXTERN void canvas_redraw(t_canvas *x);
1048
1049EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym);
1050EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip);
1051EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym);
1052EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op);
1053EXTERN void canvas_redrawallfortemplate(t_canvas *tmpl);
1054EXTERN void canvas_zapallfortemplate(t_canvas *tmpl);
1055EXTERN void canvas_setusedastemplate(t_canvas *x);
1056EXTERN t_canvas *canvas_getcurrent(void);
1057EXTERN void canvas_setcurrent(t_canvas *x);
1058EXTERN void canvas_unsetcurrent(t_canvas *x);
1059EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
1060EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
1061EXTERN void canvas_dirty(t_canvas *x, t_int n);
1062EXTERN int canvas_getfont(t_canvas *x);
1063typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3);
1064
1065EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn,
1066 t_int x1, t_int x2, t_int x3);
1067
1068EXTERN void canvas_resortinlets(t_canvas *x);
1069EXTERN void canvas_resortoutlets(t_canvas *x);
1070EXTERN void canvas_free(t_canvas *x);
1071EXTERN void canvas_updatewindowlist( void);
1072EXTERN void canvas_editmode(t_canvas *x, t_floatarg yesplease);
1073EXTERN int canvas_isabstraction(t_canvas *x);
1074EXTERN int canvas_istable(t_canvas *x);
1075EXTERN int canvas_showtext(t_canvas *x);
1076EXTERN void canvas_vis(t_canvas *x, t_floatarg f);
1077EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x);
1078EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir);
1079EXTERN void canvas_loadbang(t_canvas *x);
1080EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
1081 int *x1p, int *y1p, int *x2p, int *y2p);
1082EXTERN int canvas_setdeleting(t_canvas *x, int flag);
1083
1084typedef void (*t_undofn)(t_canvas *canvas, void *buf,
1085 int action); /* a function that does UNDO/REDO */
1086#define UNDO_FREE 0 /* free current undo/redo buffer */
1087#define UNDO_UNDO 1 /* undo */
1088#define UNDO_REDO 2 /* redo */
1089EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
1090 const char *name);
1091EXTERN void canvas_noundo(t_canvas *x);
1092EXTERN int canvas_getindex(t_canvas *x, t_gobj *y);
1093
1094/* T.Grill - made public for dynamic object creation */
1095/* in g_editor.c */
1096EXTERN void canvas_connect(t_canvas *x,
1097 t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno);
1098EXTERN void canvas_disconnect(t_canvas *x,
1099 float index1, float outno, float index2, float inno);
1100EXTERN int canvas_isconnected (t_canvas *x,
1101 t_text *ob1, int n1, t_text *ob2, int n2);
1102EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy);
1103
1104
1105/* ---- functions on canvasses as objects --------------------- */
1106
1107EXTERN void canvas_fattenforscalars(t_canvas *x,
1108 int *x1, int *y1, int *x2, int *y2);
1109EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis);
1110EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift,
1111 int alt, int dbl, int doit);
1112EXTERN t_glist *canvas_getglistonsuper(void);
1113
1114EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x);
1115EXTERN t_outconnect *linetraverser_next(t_linetraverser *t);
1116EXTERN void linetraverser_skipobject(t_linetraverser *t);
1117
1118/* --------------------- functions on tscalars --------------------- */
1119
1120EXTERN void tscalar_getrect(t_tscalar *x, t_glist *owner,
1121 int *xp1, int *yp1, int *xp2, int *yp2);
1122EXTERN void tscalar_vis(t_tscalar *x, t_glist *owner, int flag);
1123EXTERN int tscalar_click(t_tscalar *x, int xpix, int ypix, int shift,
1124 int alt, int dbl, int doit);
1125
1126/* --------- functions on garrays (graphical arrays) -------------------- */
1127
1128EXTERN t_template *garray_template(t_garray *x);
1129
1130/* -------------------- arrays --------------------- */
1131EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl,
1132 t_floatarg f, t_floatarg saveit);
1133EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent);
1134EXTERN void array_resize(t_array *x, t_template *tmpl, int n);
1135EXTERN void array_free(t_array *x);
1136
1137/* --------------------- gpointers and stubs ---------------- */
1138EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a);
1139EXTERN void gstub_cutoff(t_gstub *gs);
1140EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x);
1141
1142/* --------------------- scalars ------------------------- */
1143EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp);
1144EXTERN void word_restore(t_word *wp, t_template *tmpl,
1145 int argc, t_atom *argv);
1146EXTERN t_scalar *scalar_new(t_glist *owner,
1147 t_symbol *templatesym);
1148EXTERN void scalar_getbasexy(t_scalar *x, float *basex, float *basey);
1149
1150/* ------helper routines for "garrays" and "plots" -------------- */
1151EXTERN int array_doclick(t_array *array, t_glist *glist, t_gobj *gobj,
1152 t_symbol *elemtemplatesym,
1153 float linewidth, float xloc, float xinc, float yloc,
1154 int xpix, int ypix, int shift, int alt, int dbl, int doit);
1155
1156EXTERN void array_getcoordinate(t_glist *glist,
1157 char *elem, int xonset, int yonset, int wonset, int indx,
1158 float basex, float basey, float xinc,
1159 float *xp, float *yp, float *wp);
1160
1161EXTERN int array_getfields(t_symbol *elemtemplatesym,
1162 t_canvas **elemtemplatecanvasp,
1163 t_template **elemtemplatep, int *elemsizep,
1164 int *xonsetp, int *yonsetp, int *wonsetp);
1165
1166/* --------------------- templates ------------------------- */
1167EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv);
1168EXTERN void template_free(t_template *x);
1169EXTERN int template_match(t_template *x1, t_template *x2);
1170EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset,
1171 int *p_type, t_symbol **p_arraytype);
1172EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp,
1173 int loud);
1174EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp,
1175 t_float f, int loud);
1176EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
1177 t_word *wp, int loud);
1178EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
1179 t_word *wp, t_symbol *s, int loud);
1180
1181EXTERN t_template *gtemplate_get(t_gtemplate *x);
1182EXTERN t_template *template_findbyname(t_symbol *s);
1183EXTERN t_canvas *template_findcanvas(t_template *tmpl);
1184
1185EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname,
1186 t_word *wp, int loud);
1187EXTERN void template_setfloat(t_template *x, t_symbol *fieldname,
1188 t_word *wp, t_float f, int loud);
1189EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
1190 t_word *wp, int loud);
1191EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
1192 t_word *wp, t_symbol *s, int loud);
1193
1194/* ----------------------- guiconnects, g_guiconnect.c --------- */
1195EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym);
1196EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);
1197
1198/* ------------- IEMGUI routines used in other g_ files ---------------- */
1199EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s);
1200EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s);
1201
1202#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
1203}
1204#endif
diff --git a/apps/plugins/pdbox/PDa/extra/gcanvas-help.pd b/apps/plugins/pdbox/PDa/extra/gcanvas-help.pd
new file mode 100644
index 0000000000..e0e3fd6f4d
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/gcanvas-help.pd
@@ -0,0 +1,16 @@
1#N canvas 0 0 240 300 8;
2#X obj 21 61 gcanvas 80 80;
3#X text 14 9 gcanvas .. mouse coordinate enabled canvas;
4#X text 13 22 ==========================================;
5#X floatatom 21 148 5 0 0 0 - - -;
6#X floatatom 94 147 5 0 0 0 - - -;
7#X connect 0 0 3 0;
8#X connect 0 1 4 0;
9#N canvas 0 0 240 300 8;
10#X obj 21 61 gcanvas 80 80;
11#X text 14 9 gcanvas .. mouse coordinate enabled canvas;
12#X text 13 22 ==========================================;
13#X floatatom 21 148 5 0 0 0 - - -;
14#X floatatom 94 147 5 0 0 0 - - -;
15#X connect 0 0 3 0;
16#X connect 0 1 4 0;
diff --git a/apps/plugins/pdbox/PDa/extra/gcanvas.c b/apps/plugins/pdbox/PDa/extra/gcanvas.c
new file mode 100644
index 0000000000..aed5c96cec
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/gcanvas.c
@@ -0,0 +1,758 @@
1/* (C) Guenter Geiger <geiger@xdv.org> */
2
3
4#include "m_pd.h"
5#include "g_canvas.h"
6
7/* ------------------------ gcanvas ----------------------------- */
8
9
10#define BACKGROUNDCOLOR "grey"
11
12#define DEFAULTSIZE 80
13
14static t_class *gcanvas_class;
15
16typedef struct _gcanvas
17{
18 t_object x_obj;
19 t_glist * x_glist;
20 t_outlet* out2;
21 t_outlet* out3;
22 int x_width;
23 int x_height;
24 int x;
25 int y;
26 int x_xgrid;
27 int x_ygrid;
28} t_gcanvas;
29
30
31static void rectangle(void* cv,void* o,char c,int x, int y,int w,int h,char* color) {
32 sys_vgui(".x%x.c create rectangle \
33 %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color);
34}
35
36static void move_object(void* cv,void* o,char c,int x, int y,int w,int h) {
37 sys_vgui(".x%x.c coords %x%c %d %d %d %d\n",
38 cv,o,c,x,y,x+w,y+h);
39
40}
41
42static void color_object(void* cv,void* o,char c,char* color) {
43 sys_vgui(".x%x.c itemconfigure %x%c -fill %s\n", cv,
44 o, c,color);
45}
46
47static void delete_object(void* cv,void* o,char c) {
48 sys_vgui(".x%x.c delete %x%c\n",
49 cv, o,c);
50}
51
52static void line(void* cv,void* o,char c,int x,int y,int w,int h,char* color) {
53 sys_vgui(".x%x.c create line \
54 %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color);
55}
56
57
58/* widget helper functions */
59
60void gcanvas_drawme(t_gcanvas *x, t_glist *glist, int firsttime)
61{
62 int i;
63 if (firsttime) {
64 rectangle(glist_getcanvas(glist),x,'a',
65 x->x_obj.te_xpix, x->x_obj.te_ypix,
66 x->x_width, x->x_height,BACKGROUNDCOLOR);
67 for (i=1;i<x->x_xgrid;i++)
68 line(glist_getcanvas(glist),x,'b'+ i,
69 x->x_obj.te_xpix + x->x_width*i/x->x_xgrid,
70 x->x_obj.te_ypix,
71 0, x->x_height,"red");
72 for (i=1;i<x->x_ygrid;i++)
73 line(glist_getcanvas(glist),x,'B'+ i,
74 x->x_obj.te_xpix,
75 x->x_obj.te_ypix + x->x_height*i/x->x_ygrid,
76 x->x_width, 0,"blue");
77 }
78 else {
79 move_object(
80 glist_getcanvas(glist),x,'a',
81 x->x_obj.te_xpix, x->x_obj.te_ypix,
82 x->x_width, x->x_height);
83 for (i=1;i<x->x_xgrid;i++)
84 move_object(glist_getcanvas(glist),x,'b'+ i,
85 x->x_obj.te_xpix + x->x_width*i/x->x_xgrid,
86 x->x_obj.te_ypix,
87 0, x->x_height);
88 for (i=1;i<x->x_ygrid;i++)
89 move_object(glist_getcanvas(glist),x,'B'+ i,
90 x->x_obj.te_xpix,
91 x->x_obj.te_ypix + x->x_height*i/x->x_ygrid,
92 x->x_width, 0);
93 }
94
95 {
96 /* outlets */
97 int n = 3;
98 int nplus, i;
99 nplus = (n == 1 ? 1 : n-1);
100 for (i = 0; i < n; i++)
101 {
102 int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus;
103 if (firsttime)
104 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n",
105 glist_getcanvas(glist),
106 onset, x->x_obj.te_ypix + x->x_height - 1,
107 onset + IOWIDTH, x->x_obj.te_ypix + x->x_height,
108 x, i);
109 else
110 sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
111 glist_getcanvas(glist), x, i,
112 onset, x->x_obj.te_ypix + x->x_height - 1,
113 onset + IOWIDTH, x->x_obj.te_ypix + x->x_height);
114 }
115 /* inlets */
116 n = 0;
117 nplus = (n == 1 ? 1 : n-1);
118 for (i = 0; i < n; i++)
119 {
120 int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus;
121 if (firsttime)
122 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
123 glist_getcanvas(glist),
124 onset, x->x_obj.te_ypix,
125 onset + IOWIDTH, x->x_obj.te_ypix + 1,
126 x, i);
127 else
128 sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
129 glist_getcanvas(glist), x, i,
130 onset, x->x_obj.te_ypix,
131 onset + IOWIDTH, x->x_obj.te_ypix + 1);
132
133 }
134 }
135
136}
137
138
139
140
141void gcanvas_erase(t_gcanvas* x,t_glist* glist)
142{
143 int n,i;
144 delete_object(glist_getcanvas(glist),x,'a');
145 for (i=1;i<x->x_xgrid;i++)
146 delete_object(glist_getcanvas(glist),x,'b'+ i);
147 for (i=1;i<x->x_ygrid;i++)
148 delete_object(glist_getcanvas(glist),x,'B'+ i);
149
150 n = 2;
151 while (n--) {
152 sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,n);
153 }
154}
155
156
157
158/* ------------------------ gcanvas widgetbehaviour----------------------------- */
159
160
161static void gcanvas_getrect(t_gobj *z, t_glist *owner,
162 int *xp1, int *yp1, int *xp2, int *yp2)
163{
164 int width, height;
165 t_gcanvas* s = (t_gcanvas*)z;
166
167
168 width = s->x_width;
169 height = s->x_height;
170 *xp1 = s->x_obj.te_xpix;
171 *yp1 = s->x_obj.te_ypix;
172 *xp2 = s->x_obj.te_xpix + width;
173 *yp2 = s->x_obj.te_ypix + height;
174}
175
176static void gcanvas_displace(t_gobj *z, t_glist *glist,
177 int dx, int dy)
178{
179 t_gcanvas *x = (t_gcanvas *)z;
180 x->x_obj.te_xpix += dx;
181 x->x_obj.te_ypix += dy;
182 gcanvas_drawme(x, glist, 0);
183 canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
184}
185
186static void gcanvas_select(t_gobj *z, t_glist *glist, int state)
187{
188 t_gcanvas *x = (t_gcanvas *)z;
189 color_object(glist,x,'a',state ? "blue" : BACKGROUNDCOLOR);
190}
191
192
193static void gcanvas_activate(t_gobj *z, t_glist *glist, int state)
194{
195/* t_text *x = (t_text *)z;
196 t_rtext *y = glist_findrtext(glist, x);
197 if (z->g_pd != gatom_class) rtext_activate(y, state);*/
198}
199
200static void gcanvas_delete(t_gobj *z, t_glist *glist)
201{
202 t_text *x = (t_text *)z;
203 canvas_deletelinesfor(glist_getcanvas(glist), x);
204}
205
206
207static void gcanvas_vis(t_gobj *z, t_glist *glist, int vis)
208{
209 t_gcanvas* s = (t_gcanvas*)z;
210 if (vis)
211 gcanvas_drawme(s, glist, 1);
212 else
213 gcanvas_erase(s,glist);
214}
215
216/* can we use the normal text save function ?? */
217
218static void gcanvas_save(t_gobj *z, t_binbuf *b)
219{
220 t_gcanvas *x = (t_gcanvas *)z;
221 binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"),
222 (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix,
223 gensym("gcanvas"),x->x_width,x->x_height,
224 x->x_xgrid,
225 x->x_ygrid);
226 binbuf_addv(b, ";");
227}
228
229
230t_widgetbehavior gcanvas_widgetbehavior;
231
232static void gcanvas_motion(t_gcanvas *x, t_floatarg dx, t_floatarg dy)
233{
234 x->x += dx;
235 x->y += dy;
236 outlet_float(x->out2,x->y);
237 outlet_float(x->x_obj.ob_outlet,x->x);
238}
239
240void gcanvas_key(t_gcanvas *x, t_floatarg f)
241{
242 post("key");
243}
244
245
246static void gcanvas_click(t_gcanvas *x,
247 t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
248 t_floatarg doit,int up)
249{
250 glist_grab(x->x_glist, &x->x_obj.te_g, (t_glistmotionfn) gcanvas_motion,
251 (t_glistkeyfn) NULL, xpos, ypos);
252
253 x->x = xpos - x->x_obj.te_xpix;
254 x->y = ypos - x->x_obj.te_ypix;
255 outlet_float(x->out2,x->y);
256 outlet_float(x->x_obj.ob_outlet,x->x);
257 outlet_float(x->out3,0);
258}
259
260static int gcanvas_newclick(t_gobj *z, struct _glist *glist,
261 int xpix, int ypix, int shift, int alt, int dbl, int doit)
262{
263 if (doit)
264 gcanvas_click((t_gcanvas *)z, (t_floatarg)xpix, (t_floatarg)ypix,
265 (t_floatarg)shift, 0, (t_floatarg)alt,dbl);
266
267 if (dbl) outlet_float(((t_gcanvas*)z)->out3,1);
268 return (1);
269}
270
271void gcanvas_size(t_gcanvas* x,t_floatarg w,t_floatarg h) {
272 x->x_width = w;
273 x->x_height = h;
274 gcanvas_drawme(x, x->x_glist, 0);
275}
276
277static void gcanvas_setwidget(void)
278{
279 gcanvas_widgetbehavior.w_getrectfn = gcanvas_getrect;
280 gcanvas_widgetbehavior.w_displacefn = gcanvas_displace;
281 gcanvas_widgetbehavior.w_selectfn = gcanvas_select;
282 gcanvas_widgetbehavior.w_activatefn = gcanvas_activate;
283 gcanvas_widgetbehavior.w_deletefn = gcanvas_delete;
284 gcanvas_widgetbehavior.w_visfn = gcanvas_vis;
285 gcanvas_widgetbehavior.w_clickfn = gcanvas_newclick;
286 class_setsavefn(gcanvas_class,gcanvas_save);
287}
288
289
290static void *gcanvas_new(t_symbol* s,t_int ac,t_atom* at)
291{
292 t_gcanvas *x = (t_gcanvas *)pd_new(gcanvas_class);
293
294 x->x_glist = (t_glist*) canvas_getcurrent();
295
296
297 /* Fetch the width */
298
299 x->x_width = DEFAULTSIZE;
300 if (ac-- > 0) {
301 if (at->a_type != A_FLOAT)
302 error("gcanvas: wrong argument type");
303 else
304 x->x_width = atom_getfloat(at++);
305
306 if (x->x_width < 0 || x->x_width > 2000) {
307 error("gcanvas: unallowed width %f",x->x_width);
308 x->x_width = DEFAULTSIZE;
309 }
310 }
311
312 /* Fetch the height */
313
314 x->x_height = DEFAULTSIZE;
315 if (ac-- > 0) {
316 if (at->a_type != A_FLOAT)
317 error("gcanvas: wrong argument type");
318 else
319 x->x_height = atom_getfloat(at++);
320
321 if (x->x_height < 0 || x->x_height > 2000) {
322 error("gcanvas: unallowed height %f",x->x_height);
323 x->x_width = DEFAULTSIZE;
324 }
325 }
326
327 /* Fetch the xgrid */
328
329 x->x_xgrid = 0;
330 if (ac-- > 0) {
331 if (at->a_type != A_FLOAT)
332 error("gcanvas: wrong argument type");
333 else
334 x->x_xgrid = atom_getfloat(at++);
335
336 if (x->x_xgrid < 0 || x->x_xgrid > x->x_width/2) {
337 error("gcanvas: unallowed xgrid %f",x->x_xgrid);
338 x->x_xgrid = 0;
339 }
340 }
341
342 /* Fetch the ygrid */
343
344 x->x_ygrid = 0;
345 if (ac-- > 0) {
346 if (at->a_type != A_FLOAT)
347 error("gcanvas: wrong argument type");
348 else
349 x->x_ygrid = atom_getfloat(at++);
350
351 if (x->x_ygrid < 0 || x->x_ygrid > x->x_height/2) {
352 error("gcanvas: unallowed xgrid %f",x->x_ygrid);
353 x->x_ygrid = 0;
354 }
355 }
356
357 outlet_new(&x->x_obj, &s_float);
358 x->out2 = outlet_new(&x->x_obj, &s_float);
359 x->out3 = outlet_new(&x->x_obj, &s_float);
360 return (x);
361}
362
363
364
365void gcanvas_setup(void)
366{
367 gcanvas_class = class_new(gensym("gcanvas"), (t_newmethod)gcanvas_new, 0,
368 sizeof(t_gcanvas),0, A_GIMME,0);
369
370 class_addmethod(gcanvas_class, (t_method)gcanvas_click, gensym("click"),
371 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
372 class_addmethod(gcanvas_class, (t_method)gcanvas_size, gensym("size"),
373 A_FLOAT, A_FLOAT, 0);
374
375 gcanvas_setwidget();
376 class_setwidget(gcanvas_class,&gcanvas_widgetbehavior);
377}
378
379
380/* (C) Guenter Geiger <geiger@xdv.org> */
381
382
383#include "m_pd.h"
384#include "g_canvas.h"
385
386/* ------------------------ gcanvas ----------------------------- */
387
388
389#define BACKGROUNDCOLOR "grey"
390
391#define DEFAULTSIZE 80
392
393static t_class *gcanvas_class;
394
395typedef struct _gcanvas
396{
397 t_object x_obj;
398 t_glist * x_glist;
399 t_outlet* out2;
400 t_outlet* out3;
401 int x_width;
402 int x_height;
403 int x;
404 int y;
405 int x_xgrid;
406 int x_ygrid;
407} t_gcanvas;
408
409
410static void rectangle(void* cv,void* o,char c,int x, int y,int w,int h,char* color) {
411 sys_vgui(".x%x.c create rectangle \
412 %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color);
413}
414
415static void move_object(void* cv,void* o,char c,int x, int y,int w,int h) {
416 sys_vgui(".x%x.c coords %x%c %d %d %d %d\n",
417 cv,o,c,x,y,x+w,y+h);
418
419}
420
421static void color_object(void* cv,void* o,char c,char* color) {
422 sys_vgui(".x%x.c itemconfigure %x%c -fill %s\n", cv,
423 o, c,color);
424}
425
426static void delete_object(void* cv,void* o,char c) {
427 sys_vgui(".x%x.c delete %x%c\n",
428 cv, o,c);
429}
430
431static void line(void* cv,void* o,char c,int x,int y,int w,int h,char* color) {
432 sys_vgui(".x%x.c create line \
433 %d %d %d %d -tags %x%c -fill %s\n",cv,x,y,x+w,y+h,o,c,color);
434}
435
436
437/* widget helper functions */
438
439void gcanvas_drawme(t_gcanvas *x, t_glist *glist, int firsttime)
440{
441 int i;
442 if (firsttime) {
443 rectangle(glist_getcanvas(glist),x,'a',
444 x->x_obj.te_xpix, x->x_obj.te_ypix,
445 x->x_width, x->x_height,BACKGROUNDCOLOR);
446 for (i=1;i<x->x_xgrid;i++)
447 line(glist_getcanvas(glist),x,'b'+ i,
448 x->x_obj.te_xpix + x->x_width*i/x->x_xgrid,
449 x->x_obj.te_ypix,
450 0, x->x_height,"red");
451 for (i=1;i<x->x_ygrid;i++)
452 line(glist_getcanvas(glist),x,'B'+ i,
453 x->x_obj.te_xpix,
454 x->x_obj.te_ypix + x->x_height*i/x->x_ygrid,
455 x->x_width, 0,"blue");
456 }
457 else {
458 move_object(
459 glist_getcanvas(glist),x,'a',
460 x->x_obj.te_xpix, x->x_obj.te_ypix,
461 x->x_width, x->x_height);
462 for (i=1;i<x->x_xgrid;i++)
463 move_object(glist_getcanvas(glist),x,'b'+ i,
464 x->x_obj.te_xpix + x->x_width*i/x->x_xgrid,
465 x->x_obj.te_ypix,
466 0, x->x_height);
467 for (i=1;i<x->x_ygrid;i++)
468 move_object(glist_getcanvas(glist),x,'B'+ i,
469 x->x_obj.te_xpix,
470 x->x_obj.te_ypix + x->x_height*i/x->x_ygrid,
471 x->x_width, 0);
472 }
473
474 {
475 /* outlets */
476 int n = 3;
477 int nplus, i;
478 nplus = (n == 1 ? 1 : n-1);
479 for (i = 0; i < n; i++)
480 {
481 int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus;
482 if (firsttime)
483 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n",
484 glist_getcanvas(glist),
485 onset, x->x_obj.te_ypix + x->x_height - 1,
486 onset + IOWIDTH, x->x_obj.te_ypix + x->x_height,
487 x, i);
488 else
489 sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
490 glist_getcanvas(glist), x, i,
491 onset, x->x_obj.te_ypix + x->x_height - 1,
492 onset + IOWIDTH, x->x_obj.te_ypix + x->x_height);
493 }
494 /* inlets */
495 n = 0;
496 nplus = (n == 1 ? 1 : n-1);
497 for (i = 0; i < n; i++)
498 {
499 int onset = x->x_obj.te_xpix + (x->x_width - IOWIDTH) * i / nplus;
500 if (firsttime)
501 sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
502 glist_getcanvas(glist),
503 onset, x->x_obj.te_ypix,
504 onset + IOWIDTH, x->x_obj.te_ypix + 1,
505 x, i);
506 else
507 sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
508 glist_getcanvas(glist), x, i,
509 onset, x->x_obj.te_ypix,
510 onset + IOWIDTH, x->x_obj.te_ypix + 1);
511
512 }
513 }
514
515}
516
517
518
519
520void gcanvas_erase(t_gcanvas* x,t_glist* glist)
521{
522 int n,i;
523 delete_object(glist_getcanvas(glist),x,'a');
524 for (i=1;i<x->x_xgrid;i++)
525 delete_object(glist_getcanvas(glist),x,'b'+ i);
526 for (i=1;i<x->x_ygrid;i++)
527 delete_object(glist_getcanvas(glist),x,'B'+ i);
528
529 n = 2;
530 while (n--) {
531 sys_vgui(".x%x.c delete %xo%d\n",glist_getcanvas(glist),x,n);
532 }
533}
534
535
536
537/* ------------------------ gcanvas widgetbehaviour----------------------------- */
538
539
540static void gcanvas_getrect(t_gobj *z, t_glist *owner,
541 int *xp1, int *yp1, int *xp2, int *yp2)
542{
543 int width, height;
544 t_gcanvas* s = (t_gcanvas*)z;
545
546
547 width = s->x_width;
548 height = s->x_height;
549 *xp1 = s->x_obj.te_xpix;
550 *yp1 = s->x_obj.te_ypix;
551 *xp2 = s->x_obj.te_xpix + width;
552 *yp2 = s->x_obj.te_ypix + height;
553}
554
555static void gcanvas_displace(t_gobj *z, t_glist *glist,
556 int dx, int dy)
557{
558 t_gcanvas *x = (t_gcanvas *)z;
559 x->x_obj.te_xpix += dx;
560 x->x_obj.te_ypix += dy;
561 gcanvas_drawme(x, glist, 0);
562 canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
563}
564
565static void gcanvas_select(t_gobj *z, t_glist *glist, int state)
566{
567 t_gcanvas *x = (t_gcanvas *)z;
568 color_object(glist,x,'a',state ? "blue" : BACKGROUNDCOLOR);
569}
570
571
572static void gcanvas_activate(t_gobj *z, t_glist *glist, int state)
573{
574/* t_text *x = (t_text *)z;
575 t_rtext *y = glist_findrtext(glist, x);
576 if (z->g_pd != gatom_class) rtext_activate(y, state);*/
577}
578
579static void gcanvas_delete(t_gobj *z, t_glist *glist)
580{
581 t_text *x = (t_text *)z;
582 canvas_deletelinesfor(glist_getcanvas(glist), x);
583}
584
585
586static void gcanvas_vis(t_gobj *z, t_glist *glist, int vis)
587{
588 t_gcanvas* s = (t_gcanvas*)z;
589 if (vis)
590 gcanvas_drawme(s, glist, 1);
591 else
592 gcanvas_erase(s,glist);
593}
594
595/* can we use the normal text save function ?? */
596
597static void gcanvas_save(t_gobj *z, t_binbuf *b)
598{
599 t_gcanvas *x = (t_gcanvas *)z;
600 binbuf_addv(b, "ssiisiiii", gensym("#X"),gensym("obj"),
601 (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix,
602 gensym("gcanvas"),x->x_width,x->x_height,
603 x->x_xgrid,
604 x->x_ygrid);
605 binbuf_addv(b, ";");
606}
607
608
609t_widgetbehavior gcanvas_widgetbehavior;
610
611static void gcanvas_motion(t_gcanvas *x, t_floatarg dx, t_floatarg dy)
612{
613 x->x += dx;
614 x->y += dy;
615 outlet_float(x->out2,x->y);
616 outlet_float(x->x_obj.ob_outlet,x->x);
617}
618
619void gcanvas_key(t_gcanvas *x, t_floatarg f)
620{
621 post("key");
622}
623
624
625static void gcanvas_click(t_gcanvas *x,
626 t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
627 t_floatarg doit,int up)
628{
629 glist_grab(x->x_glist, &x->x_obj.te_g, (t_glistmotionfn) gcanvas_motion,
630 (t_glistkeyfn) NULL, xpos, ypos);
631
632 x->x = xpos - x->x_obj.te_xpix;
633 x->y = ypos - x->x_obj.te_ypix;
634 outlet_float(x->out2,x->y);
635 outlet_float(x->x_obj.ob_outlet,x->x);
636 outlet_float(x->out3,0);
637}
638
639static int gcanvas_newclick(t_gobj *z, struct _glist *glist,
640 int xpix, int ypix, int shift, int alt, int dbl, int doit)
641{
642 if (doit)
643 gcanvas_click((t_gcanvas *)z, (t_floatarg)xpix, (t_floatarg)ypix,
644 (t_floatarg)shift, 0, (t_floatarg)alt,dbl);
645
646 if (dbl) outlet_float(((t_gcanvas*)z)->out3,1);
647 return (1);
648}
649
650void gcanvas_size(t_gcanvas* x,t_floatarg w,t_floatarg h) {
651 x->x_width = w;
652 x->x_height = h;
653 gcanvas_drawme(x, x->x_glist, 0);
654}
655
656static void gcanvas_setwidget(void)
657{
658 gcanvas_widgetbehavior.w_getrectfn = gcanvas_getrect;
659 gcanvas_widgetbehavior.w_displacefn = gcanvas_displace;
660 gcanvas_widgetbehavior.w_selectfn = gcanvas_select;
661 gcanvas_widgetbehavior.w_activatefn = gcanvas_activate;
662 gcanvas_widgetbehavior.w_deletefn = gcanvas_delete;
663 gcanvas_widgetbehavior.w_visfn = gcanvas_vis;
664 gcanvas_widgetbehavior.w_clickfn = gcanvas_newclick;
665 class_setsavefn(gcanvas_class,gcanvas_save);
666}
667
668
669static void *gcanvas_new(t_symbol* s,t_int ac,t_atom* at)
670{
671 t_gcanvas *x = (t_gcanvas *)pd_new(gcanvas_class);
672
673 x->x_glist = (t_glist*) canvas_getcurrent();
674
675
676 /* Fetch the width */
677
678 x->x_width = DEFAULTSIZE;
679 if (ac-- > 0) {
680 if (at->a_type != A_FLOAT)
681 error("gcanvas: wrong argument type");
682 else
683 x->x_width = atom_getfloat(at++);
684
685 if (x->x_width < 0 || x->x_width > 2000) {
686 error("gcanvas: unallowed width %f",x->x_width);
687 x->x_width = DEFAULTSIZE;
688 }
689 }
690
691 /* Fetch the height */
692
693 x->x_height = DEFAULTSIZE;
694 if (ac-- > 0) {
695 if (at->a_type != A_FLOAT)
696 error("gcanvas: wrong argument type");
697 else
698 x->x_height = atom_getfloat(at++);
699
700 if (x->x_height < 0 || x->x_height > 2000) {
701 error("gcanvas: unallowed height %f",x->x_height);
702 x->x_width = DEFAULTSIZE;
703 }
704 }
705
706 /* Fetch the xgrid */
707
708 x->x_xgrid = 0;
709 if (ac-- > 0) {
710 if (at->a_type != A_FLOAT)
711 error("gcanvas: wrong argument type");
712 else
713 x->x_xgrid = atom_getfloat(at++);
714
715 if (x->x_xgrid < 0 || x->x_xgrid > x->x_width/2) {
716 error("gcanvas: unallowed xgrid %f",x->x_xgrid);
717 x->x_xgrid = 0;
718 }
719 }
720
721 /* Fetch the ygrid */
722
723 x->x_ygrid = 0;
724 if (ac-- > 0) {
725 if (at->a_type != A_FLOAT)
726 error("gcanvas: wrong argument type");
727 else
728 x->x_ygrid = atom_getfloat(at++);
729
730 if (x->x_ygrid < 0 || x->x_ygrid > x->x_height/2) {
731 error("gcanvas: unallowed xgrid %f",x->x_ygrid);
732 x->x_ygrid = 0;
733 }
734 }
735
736 outlet_new(&x->x_obj, &s_float);
737 x->out2 = outlet_new(&x->x_obj, &s_float);
738 x->out3 = outlet_new(&x->x_obj, &s_float);
739 return (x);
740}
741
742
743
744void gcanvas_setup(void)
745{
746 gcanvas_class = class_new(gensym("gcanvas"), (t_newmethod)gcanvas_new, 0,
747 sizeof(t_gcanvas),0, A_GIMME,0);
748
749 class_addmethod(gcanvas_class, (t_method)gcanvas_click, gensym("click"),
750 A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
751 class_addmethod(gcanvas_class, (t_method)gcanvas_size, gensym("size"),
752 A_FLOAT, A_FLOAT, 0);
753
754 gcanvas_setwidget();
755 class_setwidget(gcanvas_class,&gcanvas_widgetbehavior);
756}
757
758
diff --git a/apps/plugins/pdbox/PDa/extra/highpass.c b/apps/plugins/pdbox/PDa/extra/highpass.c
new file mode 100644
index 0000000000..88ba4564e6
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/highpass.c
@@ -0,0 +1,174 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4/*
5
6 These filter coefficients computations are taken from
7 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
8
9 written by Robert Bristow-Johnson
10
11*/
12
13#include "m_pd.h"
14#ifdef NT
15#pragma warning( disable : 4244 )
16#pragma warning( disable : 4305 )
17#endif
18#include <math.h>
19#include "filters.h"
20
21
22/* ------------------- highpass ----------------------------*/
23
24static t_class *highpass_class;
25
26void highpass_bang(t_rbjfilter *x)
27{
28 t_atom at[5];
29 t_float omega = e_omega(x->x_freq,x->x_rate);
30 t_float alpha = e_alpha(x->x_bw* 0.01,omega);
31 t_float b1 = -(1 + cos(omega));
32 t_float b0 = -b1/2.;
33 t_float b2 = b0;
34 t_float a0 = 1 + alpha;
35 t_float a1 = -2.*cos(omega);
36 t_float a2 = 1 - alpha;
37
38/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
39
40 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
41 post("highpass: filter unstable -> resetting");
42 a0=1.;a1=0.;a2=0.;
43 b0=1.;b1=0.;b2=0.;
44 }
45
46 SETFLOAT(at,-a1/a0);
47 SETFLOAT(at+1,-a2/a0);
48 SETFLOAT(at+2,b0/a0);
49 SETFLOAT(at+3,b1/a0);
50 SETFLOAT(at+4,b2/a0);
51
52 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
53}
54
55
56void highpass_float(t_rbjfilter *x,t_floatarg f)
57{
58 x->x_freq = f;
59 highpass_bang(x);
60}
61
62
63static void *highpass_new(t_floatarg f,t_floatarg bw)
64{
65 t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class);
66
67 x->x_rate = 44100.0;
68 outlet_new(&x->x_obj,&s_float);
69/* floatinlet_new(&x->x_obj, &x->x_gain); */
70 floatinlet_new(&x->x_obj, &x->x_bw);
71 if (f > 0.) x->x_freq = f;
72 if (bw > 0.) x->x_bw = bw;
73 return (x);
74}
75
76
77void highpass_setup(void)
78{
79 highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0,
80 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
81 class_addbang(highpass_class,highpass_bang);
82 class_addfloat(highpass_class,highpass_float);
83}
84
85
86
87
88/* (C) Guenter Geiger <geiger@epy.co.at> */
89
90
91/*
92
93 These filter coefficients computations are taken from
94 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
95
96 written by Robert Bristow-Johnson
97
98*/
99
100#include "m_pd.h"
101#ifdef NT
102#pragma warning( disable : 4244 )
103#pragma warning( disable : 4305 )
104#endif
105#include <math.h>
106#include "filters.h"
107
108
109/* ------------------- highpass ----------------------------*/
110
111static t_class *highpass_class;
112
113void highpass_bang(t_rbjfilter *x)
114{
115 t_atom at[5];
116 t_float omega = e_omega(x->x_freq,x->x_rate);
117 t_float alpha = e_alpha(x->x_bw* 0.01,omega);
118 t_float b1 = -(1 + cos(omega));
119 t_float b0 = -b1/2.;
120 t_float b2 = b0;
121 t_float a0 = 1 + alpha;
122 t_float a1 = -2.*cos(omega);
123 t_float a2 = 1 - alpha;
124
125/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
126
127 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
128 post("highpass: filter unstable -> resetting");
129 a0=1.;a1=0.;a2=0.;
130 b0=1.;b1=0.;b2=0.;
131 }
132
133 SETFLOAT(at,-a1/a0);
134 SETFLOAT(at+1,-a2/a0);
135 SETFLOAT(at+2,b0/a0);
136 SETFLOAT(at+3,b1/a0);
137 SETFLOAT(at+4,b2/a0);
138
139 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
140}
141
142
143void highpass_float(t_rbjfilter *x,t_floatarg f)
144{
145 x->x_freq = f;
146 highpass_bang(x);
147}
148
149
150static void *highpass_new(t_floatarg f,t_floatarg bw)
151{
152 t_rbjfilter *x = (t_rbjfilter *)pd_new(highpass_class);
153
154 x->x_rate = 44100.0;
155 outlet_new(&x->x_obj,&s_float);
156/* floatinlet_new(&x->x_obj, &x->x_gain); */
157 floatinlet_new(&x->x_obj, &x->x_bw);
158 if (f > 0.) x->x_freq = f;
159 if (bw > 0.) x->x_bw = bw;
160 return (x);
161}
162
163
164void highpass_setup(void)
165{
166 highpass_class = class_new(gensym("highpass"), (t_newmethod)highpass_new, 0,
167 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
168 class_addbang(highpass_class,highpass_bang);
169 class_addfloat(highpass_class,highpass_float);
170}
171
172
173
174
diff --git a/apps/plugins/pdbox/PDa/extra/highshelf.c b/apps/plugins/pdbox/PDa/extra/highshelf.c
new file mode 100644
index 0000000000..0060d896c2
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/highshelf.c
@@ -0,0 +1,180 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4/*
5
6 These filter coefficients computations are taken from
7 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
8
9 written by Robert Bristow-Johnson
10
11*/
12
13#include "m_pd.h"
14#ifdef NT
15#pragma warning( disable : 4244 )
16#pragma warning( disable : 4305 )
17#endif
18#include <math.h>
19#include "filters.h"
20
21
22/* ------------------- highshelf ----------------------------*/
23
24static t_class *highshelf_class;
25
26void highshelf_bang(t_rbjfilter *x)
27{
28 t_atom at[5];
29 t_float omega = e_omega(x->x_freq,x->x_rate);
30 t_float A = e_A(x->x_gain);
31 t_float cs = cos(omega);
32 t_float sn = sin(omega);
33 t_float beta = e_beta(A,x->x_bw* 0.01);
34
35 t_float b0 = A*((A+1) + (A-1)*cs + beta*sn);
36 t_float b1 =-2.*A*((A-1) + (A+1)*cs);
37 t_float b2 = A*((A+1) + (A-1)*cs - beta*sn);
38 t_float a0 = ((A+1) - (A-1)*cs + beta*sn);
39 t_float a1 = 2.*((A-1) - (A+1)*cs);
40 t_float a2 = ((A+1) - (A-1)*cs - beta*sn);
41
42/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/
43
44 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
45 post("highshelf: filter unstable -> resetting");
46 a0=1.;a1=0.;a2=0.;
47 b0=1.;b1=0.;b2=0.;
48 }
49
50 SETFLOAT(at,-a1/a0);
51 SETFLOAT(at+1,-a2/a0);
52 SETFLOAT(at+2,b0/a0);
53 SETFLOAT(at+3,b1/a0);
54 SETFLOAT(at+4,b2/a0);
55
56 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
57}
58
59
60void highshelf_float(t_rbjfilter *x,t_floatarg f)
61{
62 x->x_freq = f;
63 highshelf_bang(x);
64}
65
66
67static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw)
68{
69 t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class);
70
71 x->x_rate = 44100.0;
72 outlet_new(&x->x_obj,&s_float);
73 floatinlet_new(&x->x_obj, &x->x_gain);
74 floatinlet_new(&x->x_obj, &x->x_bw);
75 if (f > 0.) x->x_freq = f;
76 if (bw > 0.) x->x_bw = bw;
77 if (g != 0.) x->x_gain = g;
78 return (x);
79}
80
81
82void highshelf_setup(void)
83{
84 highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0,
85 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
86 class_addbang(highshelf_class,highshelf_bang);
87 class_addfloat(highshelf_class,highshelf_float);
88}
89
90
91/* (C) Guenter Geiger <geiger@epy.co.at> */
92
93
94/*
95
96 These filter coefficients computations are taken from
97 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
98
99 written by Robert Bristow-Johnson
100
101*/
102
103#include "m_pd.h"
104#ifdef NT
105#pragma warning( disable : 4244 )
106#pragma warning( disable : 4305 )
107#endif
108#include <math.h>
109#include "filters.h"
110
111
112/* ------------------- highshelf ----------------------------*/
113
114static t_class *highshelf_class;
115
116void highshelf_bang(t_rbjfilter *x)
117{
118 t_atom at[5];
119 t_float omega = e_omega(x->x_freq,x->x_rate);
120 t_float A = e_A(x->x_gain);
121 t_float cs = cos(omega);
122 t_float sn = sin(omega);
123 t_float beta = e_beta(A,x->x_bw* 0.01);
124
125 t_float b0 = A*((A+1) + (A-1)*cs + beta*sn);
126 t_float b1 =-2.*A*((A-1) + (A+1)*cs);
127 t_float b2 = A*((A+1) + (A-1)*cs - beta*sn);
128 t_float a0 = ((A+1) - (A-1)*cs + beta*sn);
129 t_float a1 = 2.*((A-1) - (A+1)*cs);
130 t_float a2 = ((A+1) - (A-1)*cs - beta*sn);
131
132/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw);*/
133
134 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
135 post("highshelf: filter unstable -> resetting");
136 a0=1.;a1=0.;a2=0.;
137 b0=1.;b1=0.;b2=0.;
138 }
139
140 SETFLOAT(at,-a1/a0);
141 SETFLOAT(at+1,-a2/a0);
142 SETFLOAT(at+2,b0/a0);
143 SETFLOAT(at+3,b1/a0);
144 SETFLOAT(at+4,b2/a0);
145
146 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
147}
148
149
150void highshelf_float(t_rbjfilter *x,t_floatarg f)
151{
152 x->x_freq = f;
153 highshelf_bang(x);
154}
155
156
157static void *highshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw)
158{
159 t_rbjfilter *x = (t_rbjfilter *)pd_new(highshelf_class);
160
161 x->x_rate = 44100.0;
162 outlet_new(&x->x_obj,&s_float);
163 floatinlet_new(&x->x_obj, &x->x_gain);
164 floatinlet_new(&x->x_obj, &x->x_bw);
165 if (f > 0.) x->x_freq = f;
166 if (bw > 0.) x->x_bw = bw;
167 if (g != 0.) x->x_gain = g;
168 return (x);
169}
170
171
172void highshelf_setup(void)
173{
174 highshelf_class = class_new(gensym("highshelf"), (t_newmethod)highshelf_new, 0,
175 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
176 class_addbang(highshelf_class,highshelf_bang);
177 class_addfloat(highshelf_class,highshelf_float);
178}
179
180
diff --git a/apps/plugins/pdbox/PDa/extra/hlshelf.c b/apps/plugins/pdbox/PDa/extra/hlshelf.c
new file mode 100644
index 0000000000..46190c9b7c
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/hlshelf.c
@@ -0,0 +1,452 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4#include <m_pd.h>
5#include <math.h>
6
7#ifdef NT
8#pragma warning( disable : 4244 )
9#pragma warning( disable : 4305 )
10#endif
11
12/* ------------------------ hlshelf ----------------------------- */
13
14
15#ifndef M_PI
16#define M_PI 3.141593f
17#endif
18
19#define SRATE 44100.0
20#define MAX_GAIN 120.0f
21
22static t_class *hlshelf_class;
23
24
25typedef struct _hlshelf
26{
27 t_object x_obj;
28 float s_rate;
29 float s_gain0;
30 float s_gain1;
31 float s_gain2;
32 float s_ltransfq;
33 float s_htransfq;
34 float s_lradians;
35 float s_hradians;
36} t_hlshelf;
37
38
39int hlshelf_check_stability(t_float fb1,
40 t_float fb2,
41 t_float ff1,
42 t_float ff2,
43 t_float ff3)
44{
45 float discriminant = fb1 * fb1 + 4 * fb2;
46
47 if (discriminant < 0) /* imaginary roots -- resonant filter */
48 {
49 /* they're conjugates so we just check that the product
50 is less than one */
51 if (fb2 >= -1.0f) goto stable;
52 }
53 else /* real roots */
54 {
55 /* check that the parabola 1 - fb1 x - fb2 x^2 has a
56 vertex between -1 and 1, and that it's nonnegative
57 at both ends, which implies both roots are in [1-,1]. */
58 if (fb1 <= 2.0f && fb1 >= -2.0f &&
59 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
60 goto stable;
61 }
62 return 0;
63stable:
64 return 1;
65}
66
67
68void hlshelf_check(t_hlshelf *x)
69{
70
71 if(x->s_gain0 - x->s_gain1 > MAX_GAIN) {
72 x->s_gain0 = x->s_gain1 + MAX_GAIN;
73 post("setting gain0 to %f",x->s_gain0);
74 }
75
76
77 if(x->s_gain1 > MAX_GAIN) {
78 x->s_gain1 = MAX_GAIN;
79 post("setting gain1 to %f",x->s_gain1);
80 }
81
82 if(x->s_gain2 - x->s_gain1 > MAX_GAIN) {
83 x->s_gain2 = x->s_gain1 + MAX_GAIN;
84 post("setting gain2 to %f",x->s_gain2);
85 }
86
87 /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */
88 x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f;
89
90 if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f;
91
92 x->s_lradians = M_PI * x->s_ltransfq / x->s_rate;
93 x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate));
94
95}
96
97
98void hlshelf_bang(t_hlshelf *x)
99{
100 t_atom at[6];
101 float c0, c1, c2, d0, d1, d2; /* output coefs */
102 float a1, a2, b1, b2, g1, g2; /* temp coefs */
103 double xf;
104
105 hlshelf_check(x);
106
107 /* low shelf */
108 xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */
109 if(xf < -200.) /* exp(x) -> 0 */
110 {
111 a1 = 1.0f;
112 b1 = -1.0f;
113 g1 = 0.0f;
114 }
115 else
116 {
117 double t = tan(x->s_lradians);
118 double e = exp(xf);
119 double r = t / e;
120 double kr = t * e;
121
122 a1 = (r - 1) / (r + 1);
123 b1 = (kr - 1) / (kr + 1);
124 g1 = (kr + 1) / (r + 1);
125 }
126
127 /* high shelf */
128 xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */
129 if(xf < -200.) /* exp(x) -> 0 */
130 {
131 a2 = -1.0f;
132 b2 = 1.0f;
133 g2 = 0.0f;
134 }
135 else
136 {
137 double t = tan(x->s_hradians);
138 double e = exp(xf);
139 double r = t / e;
140 double kr = t * e;
141
142 a2 = (1 - r) / (1 + r);
143 b2 = (1 - kr) / (1 + kr);
144 g2 = (1 + kr) / (1 + r);
145 }
146
147 /* form product */
148 c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ;
149 c1 = a1 + a2;
150 c2 = a1 * a2;
151 d0 = 1.0f;
152 d1 = b1 + b2;
153 d2 = b1 * b2;
154
155 if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) {
156 post("hlshelf: filter unstable -> resetting");
157 c0=1.;c1=0.;c2=0.;
158 d0=1.;d1=0.;d2=0.;
159 }
160
161 SETFLOAT(at,-c1/d0);
162 SETFLOAT(at+1,-c2/d0);
163 SETFLOAT(at+2,d0/d0);
164 SETFLOAT(at+3,d1/d0);
165 SETFLOAT(at+4,d2/d0);
166
167 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
168}
169
170void hlshelf_float(t_hlshelf *x,t_floatarg f)
171{
172 x->s_gain0 = f;
173 hlshelf_bang(x);
174}
175
176
177static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at)
178{
179 t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class);
180 t_float k0 = atom_getfloat(at);
181 t_float k1 = atom_getfloat(at+1);
182 t_float k2 = atom_getfloat(at+2);
183 t_float f1 = atom_getfloat(at+3);
184 t_float f2 = atom_getfloat(at+4);
185
186
187 f1 = atom_getfloat(at);
188 f2 = atom_getfloat(at);
189
190 if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */
191 f1 = 150.0f;
192 f2 = 5000.0f;
193 }
194
195 if (f1 < 0) f1 = 0.0f;
196 if (f2 > SRATE) f2 = .5f*SRATE;
197
198 x->s_rate = SRATE; /* srate default */
199 x->s_gain0 = k0;
200 x->s_gain1 = k1;
201 x->s_gain2 = k2;
202
203 x->s_ltransfq = 0.0f;
204 x->s_htransfq = SRATE/2;
205
206 x->s_lradians = M_PI * x->s_ltransfq / x->s_rate;
207 x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate));
208
209 floatinlet_new(&x->x_obj, &x->s_gain1);
210 floatinlet_new(&x->x_obj, &x->s_gain2);
211 floatinlet_new(&x->x_obj, &x->s_ltransfq);
212 floatinlet_new(&x->x_obj, &x->s_htransfq);
213 outlet_new(&x->x_obj, &s_list);
214
215 return (x);
216}
217
218void hlshelf_setup(void)
219{
220 hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0,
221 sizeof(t_hlshelf), 0, A_GIMME, 0);
222 class_addbang(hlshelf_class,hlshelf_bang);
223 class_addfloat(hlshelf_class,hlshelf_float);
224}
225
226
227/* (C) Guenter Geiger <geiger@epy.co.at> */
228
229
230#include <m_pd.h>
231#include <math.h>
232
233#ifdef NT
234#pragma warning( disable : 4244 )
235#pragma warning( disable : 4305 )
236#endif
237
238/* ------------------------ hlshelf ----------------------------- */
239
240
241#ifndef M_PI
242#define M_PI 3.141593f
243#endif
244
245#define SRATE 44100.0
246#define MAX_GAIN 120.0f
247
248static t_class *hlshelf_class;
249
250
251typedef struct _hlshelf
252{
253 t_object x_obj;
254 float s_rate;
255 float s_gain0;
256 float s_gain1;
257 float s_gain2;
258 float s_ltransfq;
259 float s_htransfq;
260 float s_lradians;
261 float s_hradians;
262} t_hlshelf;
263
264
265int hlshelf_check_stability(t_float fb1,
266 t_float fb2,
267 t_float ff1,
268 t_float ff2,
269 t_float ff3)
270{
271 float discriminant = fb1 * fb1 + 4 * fb2;
272
273 if (discriminant < 0) /* imaginary roots -- resonant filter */
274 {
275 /* they're conjugates so we just check that the product
276 is less than one */
277 if (fb2 >= -1.0f) goto stable;
278 }
279 else /* real roots */
280 {
281 /* check that the parabola 1 - fb1 x - fb2 x^2 has a
282 vertex between -1 and 1, and that it's nonnegative
283 at both ends, which implies both roots are in [1-,1]. */
284 if (fb1 <= 2.0f && fb1 >= -2.0f &&
285 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0)
286 goto stable;
287 }
288 return 0;
289stable:
290 return 1;
291}
292
293
294void hlshelf_check(t_hlshelf *x)
295{
296
297 if(x->s_gain0 - x->s_gain1 > MAX_GAIN) {
298 x->s_gain0 = x->s_gain1 + MAX_GAIN;
299 post("setting gain0 to %f",x->s_gain0);
300 }
301
302
303 if(x->s_gain1 > MAX_GAIN) {
304 x->s_gain1 = MAX_GAIN;
305 post("setting gain1 to %f",x->s_gain1);
306 }
307
308 if(x->s_gain2 - x->s_gain1 > MAX_GAIN) {
309 x->s_gain2 = x->s_gain1 + MAX_GAIN;
310 post("setting gain2 to %f",x->s_gain2);
311 }
312
313 /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */
314 x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f;
315
316 if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f;
317
318 x->s_lradians = M_PI * x->s_ltransfq / x->s_rate;
319 x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate));
320
321}
322
323
324void hlshelf_bang(t_hlshelf *x)
325{
326 t_atom at[6];
327 float c0, c1, c2, d0, d1, d2; /* output coefs */
328 float a1, a2, b1, b2, g1, g2; /* temp coefs */
329 double xf;
330
331 hlshelf_check(x);
332
333 /* low shelf */
334 xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */
335 if(xf < -200.) /* exp(x) -> 0 */
336 {
337 a1 = 1.0f;
338 b1 = -1.0f;
339 g1 = 0.0f;
340 }
341 else
342 {
343 double t = tan(x->s_lradians);
344 double e = exp(xf);
345 double r = t / e;
346 double kr = t * e;
347
348 a1 = (r - 1) / (r + 1);
349 b1 = (kr - 1) / (kr + 1);
350 g1 = (kr + 1) / (r + 1);
351 }
352
353 /* high shelf */
354 xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */
355 if(xf < -200.) /* exp(x) -> 0 */
356 {
357 a2 = -1.0f;
358 b2 = 1.0f;
359 g2 = 0.0f;
360 }
361 else
362 {
363 double t = tan(x->s_hradians);
364 double e = exp(xf);
365 double r = t / e;
366 double kr = t * e;
367
368 a2 = (1 - r) / (1 + r);
369 b2 = (1 - kr) / (1 + kr);
370 g2 = (1 + kr) / (1 + r);
371 }
372
373 /* form product */
374 c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ;
375 c1 = a1 + a2;
376 c2 = a1 * a2;
377 d0 = 1.0f;
378 d1 = b1 + b2;
379 d2 = b1 * b2;
380
381 if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) {
382 post("hlshelf: filter unstable -> resetting");
383 c0=1.;c1=0.;c2=0.;
384 d0=1.;d1=0.;d2=0.;
385 }
386
387 SETFLOAT(at,-c1/d0);
388 SETFLOAT(at+1,-c2/d0);
389 SETFLOAT(at+2,d0/d0);
390 SETFLOAT(at+3,d1/d0);
391 SETFLOAT(at+4,d2/d0);
392
393 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
394}
395
396void hlshelf_float(t_hlshelf *x,t_floatarg f)
397{
398 x->s_gain0 = f;
399 hlshelf_bang(x);
400}
401
402
403static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at)
404{
405 t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class);
406 t_float k0 = atom_getfloat(at);
407 t_float k1 = atom_getfloat(at+1);
408 t_float k2 = atom_getfloat(at+2);
409 t_float f1 = atom_getfloat(at+3);
410 t_float f2 = atom_getfloat(at+4);
411
412
413 f1 = atom_getfloat(at);
414 f2 = atom_getfloat(at);
415
416 if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */
417 f1 = 150.0f;
418 f2 = 5000.0f;
419 }
420
421 if (f1 < 0) f1 = 0.0f;
422 if (f2 > SRATE) f2 = .5f*SRATE;
423
424 x->s_rate = SRATE; /* srate default */
425 x->s_gain0 = k0;
426 x->s_gain1 = k1;
427 x->s_gain2 = k2;
428
429 x->s_ltransfq = 0.0f;
430 x->s_htransfq = SRATE/2;
431
432 x->s_lradians = M_PI * x->s_ltransfq / x->s_rate;
433 x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate));
434
435 floatinlet_new(&x->x_obj, &x->s_gain1);
436 floatinlet_new(&x->x_obj, &x->s_gain2);
437 floatinlet_new(&x->x_obj, &x->s_ltransfq);
438 floatinlet_new(&x->x_obj, &x->s_htransfq);
439 outlet_new(&x->x_obj, &s_list);
440
441 return (x);
442}
443
444void hlshelf_setup(void)
445{
446 hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0,
447 sizeof(t_hlshelf), 0, A_GIMME, 0);
448 class_addbang(hlshelf_class,hlshelf_bang);
449 class_addfloat(hlshelf_class,hlshelf_float);
450}
451
452
diff --git a/apps/plugins/pdbox/PDa/extra/image.c b/apps/plugins/pdbox/PDa/extra/image.c
new file mode 100644
index 0000000000..6de48ef8fb
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/image.c
@@ -0,0 +1,434 @@
1#include "m_pd.h"
2#include "g_canvas.h"
3
4#ifdef NT
5#pragma warning( disable : 4244 )
6#pragma warning( disable : 4305 )
7#endif
8
9/* ------------------------ image ----------------------------- */
10
11static t_class *image_class;
12
13typedef struct _image
14{
15 t_object x_obj;
16 t_glist * x_glist;
17 int x_width;
18 int x_height;
19 t_symbol* x_fname;
20} t_image;
21
22/* widget helper functions */
23
24void image_drawme(t_image *x, t_glist *glist, int firsttime)
25{
26 if (firsttime) {
27 char fname[MAXPDSTRING];
28 canvas_makefilename(glist_getcanvas(x->x_glist), x->x_fname->s_name,
29 fname, MAXPDSTRING);
30
31 sys_vgui("image create photo img%x -file %s\n",x,fname);
32 sys_vgui(".x%x.c create image %d %d -image img%x -tags %xS\n",
33 glist_getcanvas(glist),text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x,x);
34
35 /* TODO callback from gui
36 sys_vgui("image_size logo");
37 */
38 }
39 else {
40 sys_vgui(".x%x.c coords %xS \
41%d %d\n",
42 glist_getcanvas(glist), x,
43 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));
44 }
45
46}
47
48
49void image_erase(t_image* x,t_glist* glist)
50{
51 int n;
52 sys_vgui(".x%x.c delete %xS\n",
53 glist_getcanvas(glist), x);
54
55}
56
57
58
59/* ------------------------ image widgetbehaviour----------------------------- */
60
61
62static void image_getrect(t_gobj *z, t_glist *glist,
63 int *xp1, int *yp1, int *xp2, int *yp2)
64{
65 int width, height;
66 t_image* x = (t_image*)z;
67
68
69 width = x->x_width;
70 height = x->x_height;
71 *xp1 = text_xpix(&x->x_obj, glist);
72 *yp1 = text_ypix(&x->x_obj, glist);
73 *xp2 = text_xpix(&x->x_obj, glist) + width;
74 *yp2 = text_ypix(&x->x_obj, glist) + height;
75}
76
77static void image_displace(t_gobj *z, t_glist *glist,
78 int dx, int dy)
79{
80 t_image *x = (t_image *)z;
81 x->x_obj.te_xpix += dx;
82 x->x_obj.te_ypix += dy;
83 sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n",
84 glist_getcanvas(glist), x,
85 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
86 text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height);
87
88 image_drawme(x, glist, 0);
89 canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
90}
91
92static void image_select(t_gobj *z, t_glist *glist, int state)
93{
94 t_image *x = (t_image *)z;
95 if (state) {
96 sys_vgui(".x%x.c create rectangle \
97%d %d %d %d -tags %xSEL -outline blue\n",
98 glist_getcanvas(glist),
99 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
100 text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height,
101 x);
102 }
103 else {
104 sys_vgui(".x%x.c delete %xSEL\n",
105 glist_getcanvas(glist), x);
106 }
107
108
109
110}
111
112
113static void image_activate(t_gobj *z, t_glist *glist, int state)
114{
115/* t_text *x = (t_text *)z;
116 t_rtext *y = glist_findrtext(glist, x);
117 if (z->g_pd != gatom_class) rtext_activate(y, state);*/
118}
119
120static void image_delete(t_gobj *z, t_glist *glist)
121{
122 t_text *x = (t_text *)z;
123 canvas_deletelinesfor(glist_getcanvas(glist), x);
124}
125
126
127static void image_vis(t_gobj *z, t_glist *glist, int vis)
128{
129 t_image* s = (t_image*)z;
130 if (vis)
131 image_drawme(s, glist, 1);
132 else
133 image_erase(s,glist);
134}
135
136/* can we use the normal text save function ?? */
137
138static void image_save(t_gobj *z, t_binbuf *b)
139{
140 t_image *x = (t_image *)z;
141 binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"),
142 x->x_obj.te_xpix, x->x_obj.te_ypix,
143 gensym("image"),x->x_fname);
144 binbuf_addv(b, ";");
145}
146
147
148t_widgetbehavior image_widgetbehavior;
149
150void image_size(t_image* x,t_floatarg w,t_floatarg h) {
151 x->x_width = w;
152 x->x_height = h;
153}
154
155void image_color(t_image* x,t_symbol* col)
156{
157/* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang ..
158 so color black does the same as bang, but doesn't forward the bang
159*/
160}
161
162static void image_setwidget(void)
163{
164 image_widgetbehavior.w_getrectfn = image_getrect;
165 image_widgetbehavior.w_displacefn = image_displace;
166 image_widgetbehavior.w_selectfn = image_select;
167 image_widgetbehavior.w_activatefn = image_activate;
168 image_widgetbehavior.w_deletefn = image_delete;
169 image_widgetbehavior.w_visfn = image_vis;
170#if (PD_VERSION_MINOR > 31)
171 image_widgetbehavior.w_clickfn = NULL;
172 image_widgetbehavior.w_propertiesfn = NULL;
173#endif
174#if PD_MINOR_VERSION < 37
175 image_widgetbehavior.w_savefn = image_save;
176#endif
177}
178
179
180static void *image_new(t_symbol* fname)
181{
182 t_image *x = (t_image *)pd_new(image_class);
183
184 x->x_glist = (t_glist*) canvas_getcurrent();
185
186 x->x_width = 15;
187 x->x_height = 15;
188
189 x->x_fname = fname;
190 outlet_new(&x->x_obj, &s_float);
191 return (x);
192}
193
194void image_setup(void)
195{
196 image_class = class_new(gensym("image"), (t_newmethod)image_new, 0,
197 sizeof(t_image),0, A_DEFSYM,0);
198
199/*
200 class_addmethod(image_class, (t_method)image_size, gensym("size"),
201 A_FLOAT, A_FLOAT, 0);
202
203 class_addmethod(image_class, (t_method)image_color, gensym("color"),
204 A_SYMBOL, 0);
205*/
206/*
207 class_addmethod(image_class, (t_method)image_open, gensym("open"),
208 A_SYMBOL, 0);
209*/
210 image_setwidget();
211 class_setwidget(image_class,&image_widgetbehavior);
212#if PD_MINOR_VERSION >= 37
213 class_setsavefn(image_class,&image_save);
214#endif
215}
216
217
218#include "m_pd.h"
219#include "g_canvas.h"
220
221#ifdef NT
222#pragma warning( disable : 4244 )
223#pragma warning( disable : 4305 )
224#endif
225
226/* ------------------------ image ----------------------------- */
227
228static t_class *image_class;
229
230typedef struct _image
231{
232 t_object x_obj;
233 t_glist * x_glist;
234 int x_width;
235 int x_height;
236 t_symbol* x_fname;
237} t_image;
238
239/* widget helper functions */
240
241void image_drawme(t_image *x, t_glist *glist, int firsttime)
242{
243 if (firsttime) {
244 char fname[MAXPDSTRING];
245 canvas_makefilename(glist_getcanvas(x->x_glist), x->x_fname->s_name,
246 fname, MAXPDSTRING);
247
248 sys_vgui("image create photo img%x -file %s\n",x,fname);
249 sys_vgui(".x%x.c create image %d %d -image img%x -tags %xS\n",
250 glist_getcanvas(glist),text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x,x);
251
252 /* TODO callback from gui
253 sys_vgui("image_size logo");
254 */
255 }
256 else {
257 sys_vgui(".x%x.c coords %xS \
258%d %d\n",
259 glist_getcanvas(glist), x,
260 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));
261 }
262
263}
264
265
266void image_erase(t_image* x,t_glist* glist)
267{
268 int n;
269 sys_vgui(".x%x.c delete %xS\n",
270 glist_getcanvas(glist), x);
271
272}
273
274
275
276/* ------------------------ image widgetbehaviour----------------------------- */
277
278
279static void image_getrect(t_gobj *z, t_glist *glist,
280 int *xp1, int *yp1, int *xp2, int *yp2)
281{
282 int width, height;
283 t_image* x = (t_image*)z;
284
285
286 width = x->x_width;
287 height = x->x_height;
288 *xp1 = text_xpix(&x->x_obj, glist);
289 *yp1 = text_ypix(&x->x_obj, glist);
290 *xp2 = text_xpix(&x->x_obj, glist) + width;
291 *yp2 = text_ypix(&x->x_obj, glist) + height;
292}
293
294static void image_displace(t_gobj *z, t_glist *glist,
295 int dx, int dy)
296{
297 t_image *x = (t_image *)z;
298 x->x_obj.te_xpix += dx;
299 x->x_obj.te_ypix += dy;
300 sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n",
301 glist_getcanvas(glist), x,
302 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
303 text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height);
304
305 image_drawme(x, glist, 0);
306 canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
307}
308
309static void image_select(t_gobj *z, t_glist *glist, int state)
310{
311 t_image *x = (t_image *)z;
312 if (state) {
313 sys_vgui(".x%x.c create rectangle \
314%d %d %d %d -tags %xSEL -outline blue\n",
315 glist_getcanvas(glist),
316 text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
317 text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height,
318 x);
319 }
320 else {
321 sys_vgui(".x%x.c delete %xSEL\n",
322 glist_getcanvas(glist), x);
323 }
324
325
326
327}
328
329
330static void image_activate(t_gobj *z, t_glist *glist, int state)
331{
332/* t_text *x = (t_text *)z;
333 t_rtext *y = glist_findrtext(glist, x);
334 if (z->g_pd != gatom_class) rtext_activate(y, state);*/
335}
336
337static void image_delete(t_gobj *z, t_glist *glist)
338{
339 t_text *x = (t_text *)z;
340 canvas_deletelinesfor(glist_getcanvas(glist), x);
341}
342
343
344static void image_vis(t_gobj *z, t_glist *glist, int vis)
345{
346 t_image* s = (t_image*)z;
347 if (vis)
348 image_drawme(s, glist, 1);
349 else
350 image_erase(s,glist);
351}
352
353/* can we use the normal text save function ?? */
354
355static void image_save(t_gobj *z, t_binbuf *b)
356{
357 t_image *x = (t_image *)z;
358 binbuf_addv(b, "ssiiss", gensym("#X"),gensym("obj"),
359 x->x_obj.te_xpix, x->x_obj.te_ypix,
360 gensym("image"),x->x_fname);
361 binbuf_addv(b, ";");
362}
363
364
365t_widgetbehavior image_widgetbehavior;
366
367void image_size(t_image* x,t_floatarg w,t_floatarg h) {
368 x->x_width = w;
369 x->x_height = h;
370}
371
372void image_color(t_image* x,t_symbol* col)
373{
374/* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang ..
375 so color black does the same as bang, but doesn't forward the bang
376*/
377}
378
379static void image_setwidget(void)
380{
381 image_widgetbehavior.w_getrectfn = image_getrect;
382 image_widgetbehavior.w_displacefn = image_displace;
383 image_widgetbehavior.w_selectfn = image_select;
384 image_widgetbehavior.w_activatefn = image_activate;
385 image_widgetbehavior.w_deletefn = image_delete;
386 image_widgetbehavior.w_visfn = image_vis;
387#if (PD_VERSION_MINOR > 31)
388 image_widgetbehavior.w_clickfn = NULL;
389 image_widgetbehavior.w_propertiesfn = NULL;
390#endif
391#if PD_MINOR_VERSION < 37
392 image_widgetbehavior.w_savefn = image_save;
393#endif
394}
395
396
397static void *image_new(t_symbol* fname)
398{
399 t_image *x = (t_image *)pd_new(image_class);
400
401 x->x_glist = (t_glist*) canvas_getcurrent();
402
403 x->x_width = 15;
404 x->x_height = 15;
405
406 x->x_fname = fname;
407 outlet_new(&x->x_obj, &s_float);
408 return (x);
409}
410
411void image_setup(void)
412{
413 image_class = class_new(gensym("image"), (t_newmethod)image_new, 0,
414 sizeof(t_image),0, A_DEFSYM,0);
415
416/*
417 class_addmethod(image_class, (t_method)image_size, gensym("size"),
418 A_FLOAT, A_FLOAT, 0);
419
420 class_addmethod(image_class, (t_method)image_color, gensym("color"),
421 A_SYMBOL, 0);
422*/
423/*
424 class_addmethod(image_class, (t_method)image_open, gensym("open"),
425 A_SYMBOL, 0);
426*/
427 image_setwidget();
428 class_setwidget(image_class,&image_widgetbehavior);
429#if PD_MINOR_VERSION >= 37
430 class_setsavefn(image_class,&image_save);
431#endif
432}
433
434
diff --git a/apps/plugins/pdbox/PDa/extra/lowpass.c b/apps/plugins/pdbox/PDa/extra/lowpass.c
new file mode 100644
index 0000000000..c242aff0a8
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/lowpass.c
@@ -0,0 +1,178 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4/*
5
6 These filter coefficients computations are taken from
7 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
8
9 written by Robert Bristow-Johnson
10
11*/
12
13#include "m_pd.h"
14#ifdef NT
15#pragma warning( disable : 4244 )
16#pragma warning( disable : 4305 )
17#endif
18#include <math.h>
19#include "filters.h"
20
21
22
23/* ------------------- lowpass ----------------------------*/
24
25static t_class *lowpass_class;
26
27void lowpass_bang(t_rbjfilter *x)
28{
29 t_atom at[5];
30 t_float omega = e_omega(x->x_freq,x->x_rate);
31 t_float alpha = e_alpha(x->x_bw*0.01,omega);
32 t_float b1 = 1 - cos(omega);
33 t_float b0 = b1/2.;
34 t_float b2 = b0;
35 t_float a0 = 1 + alpha;
36 t_float a1 = -2.*cos(omega);
37 t_float a2 = 1 - alpha;
38
39/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
40
41 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
42 post("lowpass: filter unstable -> resetting");
43 a0=1.;a1=0.;a2=0.;
44 b0=1.;b1=0.;b2=0.;
45 }
46
47 SETFLOAT(at,-a1/a0);
48 SETFLOAT(at+1,-a2/a0);
49 SETFLOAT(at+2,b0/a0);
50 SETFLOAT(at+3,b1/a0);
51 SETFLOAT(at+4,b2/a0);
52
53 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
54}
55
56
57void lowpass_float(t_rbjfilter *x,t_floatarg f)
58{
59 x->x_freq = f;
60 lowpass_bang(x);
61}
62
63
64static void *lowpass_new(t_floatarg f,t_floatarg bw)
65{
66 t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class);
67
68 x->x_rate = 44100.0;
69 outlet_new(&x->x_obj,&s_float);
70/* floatinlet_new(&x->x_obj, &x->x_gain); */
71 floatinlet_new(&x->x_obj, &x->x_bw);
72
73 if (f > 0.) x->x_freq = f;
74 if (bw > 0.) x->x_bw = bw;
75 return (x);
76}
77
78
79void lowpass_setup(void)
80{
81 lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0,
82 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
83 class_addbang(lowpass_class,lowpass_bang);
84 class_addfloat(lowpass_class,lowpass_float);
85}
86
87
88
89
90/* (C) Guenter Geiger <geiger@epy.co.at> */
91
92
93/*
94
95 These filter coefficients computations are taken from
96 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
97
98 written by Robert Bristow-Johnson
99
100*/
101
102#include "m_pd.h"
103#ifdef NT
104#pragma warning( disable : 4244 )
105#pragma warning( disable : 4305 )
106#endif
107#include <math.h>
108#include "filters.h"
109
110
111
112/* ------------------- lowpass ----------------------------*/
113
114static t_class *lowpass_class;
115
116void lowpass_bang(t_rbjfilter *x)
117{
118 t_atom at[5];
119 t_float omega = e_omega(x->x_freq,x->x_rate);
120 t_float alpha = e_alpha(x->x_bw*0.01,omega);
121 t_float b1 = 1 - cos(omega);
122 t_float b0 = b1/2.;
123 t_float b2 = b0;
124 t_float a0 = 1 + alpha;
125 t_float a1 = -2.*cos(omega);
126 t_float a2 = 1 - alpha;
127
128/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
129
130 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
131 post("lowpass: filter unstable -> resetting");
132 a0=1.;a1=0.;a2=0.;
133 b0=1.;b1=0.;b2=0.;
134 }
135
136 SETFLOAT(at,-a1/a0);
137 SETFLOAT(at+1,-a2/a0);
138 SETFLOAT(at+2,b0/a0);
139 SETFLOAT(at+3,b1/a0);
140 SETFLOAT(at+4,b2/a0);
141
142 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
143}
144
145
146void lowpass_float(t_rbjfilter *x,t_floatarg f)
147{
148 x->x_freq = f;
149 lowpass_bang(x);
150}
151
152
153static void *lowpass_new(t_floatarg f,t_floatarg bw)
154{
155 t_rbjfilter *x = (t_rbjfilter *)pd_new(lowpass_class);
156
157 x->x_rate = 44100.0;
158 outlet_new(&x->x_obj,&s_float);
159/* floatinlet_new(&x->x_obj, &x->x_gain); */
160 floatinlet_new(&x->x_obj, &x->x_bw);
161
162 if (f > 0.) x->x_freq = f;
163 if (bw > 0.) x->x_bw = bw;
164 return (x);
165}
166
167
168void lowpass_setup(void)
169{
170 lowpass_class = class_new(gensym("lowpass"), (t_newmethod)lowpass_new, 0,
171 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
172 class_addbang(lowpass_class,lowpass_bang);
173 class_addfloat(lowpass_class,lowpass_float);
174}
175
176
177
178
diff --git a/apps/plugins/pdbox/PDa/extra/lowshelf.c b/apps/plugins/pdbox/PDa/extra/lowshelf.c
new file mode 100644
index 0000000000..52c30d839d
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/lowshelf.c
@@ -0,0 +1,182 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4/*
5
6 These filter coefficients computations are taken from
7 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
8
9 written by Robert Bristow-Johnson
10
11*/
12
13#include "m_pd.h"
14#ifdef NT
15#pragma warning( disable : 4244 )
16#pragma warning( disable : 4305 )
17#endif
18#include <math.h>
19#include "filters.h"
20
21
22
23/* ------------------- lowshelf ----------------------------*/
24
25static t_class *lowshelf_class;
26
27void lowshelf_bang(t_rbjfilter *x)
28{
29 t_atom at[5];
30 t_float omega = e_omega(x->x_freq,x->x_rate);
31 t_float A = e_A(x->x_gain);
32 t_float cs = cos(omega);
33 t_float sn = sin(omega);
34 t_float beta = e_beta(A,x->x_bw*0.01);
35
36 t_float b0 = A*((A+1) - (A-1)*cs + beta*sn);
37 t_float b1 = 2.*A*((A-1) - (A+1)*cs);
38 t_float b2 = A*((A+1) - (A-1)*cs - beta*sn);
39 t_float a0 = ((A+1) + (A-1)*cs + beta*sn);
40 t_float a1 = -2.*((A-1) + (A+1)*cs);
41 t_float a2 = ((A+1) + (A-1)*cs - beta*sn);
42
43/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
44
45 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
46 post("lowshelf: filter unstable -> resetting");
47 a0=1.;a1=0.;a2=0.;
48 b0=1.;b1=0.;b2=0.;
49 }
50
51 SETFLOAT(at,-a1/a0);
52 SETFLOAT(at+1,-a2/a0);
53 SETFLOAT(at+2,b0/a0);
54 SETFLOAT(at+3,b1/a0);
55 SETFLOAT(at+4,b2/a0);
56
57 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
58}
59
60
61void lowshelf_float(t_rbjfilter *x,t_floatarg f)
62{
63 x->x_freq = f;
64 lowshelf_bang(x);
65}
66
67
68static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw)
69{
70 t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class);
71
72 x->x_rate = 44100.0;
73 outlet_new(&x->x_obj,&s_float);
74 floatinlet_new(&x->x_obj, &x->x_gain);
75 floatinlet_new(&x->x_obj, &x->x_bw);
76 if (f > 0.) x->x_freq = f;
77 if (bw > 0.) x->x_bw = bw;
78 if (g != 0.) x->x_gain = g;
79 return (x);
80}
81
82
83void lowshelf_setup(void)
84{
85 lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0,
86 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
87 class_addbang(lowshelf_class,lowshelf_bang);
88 class_addfloat(lowshelf_class,lowshelf_float);
89}
90
91
92/* (C) Guenter Geiger <geiger@epy.co.at> */
93
94
95/*
96
97 These filter coefficients computations are taken from
98 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
99
100 written by Robert Bristow-Johnson
101
102*/
103
104#include "m_pd.h"
105#ifdef NT
106#pragma warning( disable : 4244 )
107#pragma warning( disable : 4305 )
108#endif
109#include <math.h>
110#include "filters.h"
111
112
113
114/* ------------------- lowshelf ----------------------------*/
115
116static t_class *lowshelf_class;
117
118void lowshelf_bang(t_rbjfilter *x)
119{
120 t_atom at[5];
121 t_float omega = e_omega(x->x_freq,x->x_rate);
122 t_float A = e_A(x->x_gain);
123 t_float cs = cos(omega);
124 t_float sn = sin(omega);
125 t_float beta = e_beta(A,x->x_bw*0.01);
126
127 t_float b0 = A*((A+1) - (A-1)*cs + beta*sn);
128 t_float b1 = 2.*A*((A-1) - (A+1)*cs);
129 t_float b2 = A*((A+1) - (A-1)*cs - beta*sn);
130 t_float a0 = ((A+1) + (A-1)*cs + beta*sn);
131 t_float a1 = -2.*((A-1) + (A+1)*cs);
132 t_float a2 = ((A+1) + (A-1)*cs - beta*sn);
133
134/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
135
136 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
137 post("lowshelf: filter unstable -> resetting");
138 a0=1.;a1=0.;a2=0.;
139 b0=1.;b1=0.;b2=0.;
140 }
141
142 SETFLOAT(at,-a1/a0);
143 SETFLOAT(at+1,-a2/a0);
144 SETFLOAT(at+2,b0/a0);
145 SETFLOAT(at+3,b1/a0);
146 SETFLOAT(at+4,b2/a0);
147
148 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
149}
150
151
152void lowshelf_float(t_rbjfilter *x,t_floatarg f)
153{
154 x->x_freq = f;
155 lowshelf_bang(x);
156}
157
158
159static void *lowshelf_new(t_floatarg f,t_floatarg g,t_floatarg bw)
160{
161 t_rbjfilter *x = (t_rbjfilter *)pd_new(lowshelf_class);
162
163 x->x_rate = 44100.0;
164 outlet_new(&x->x_obj,&s_float);
165 floatinlet_new(&x->x_obj, &x->x_gain);
166 floatinlet_new(&x->x_obj, &x->x_bw);
167 if (f > 0.) x->x_freq = f;
168 if (bw > 0.) x->x_bw = bw;
169 if (g != 0.) x->x_gain = g;
170 return (x);
171}
172
173
174void lowshelf_setup(void)
175{
176 lowshelf_class = class_new(gensym("lowshelf"), (t_newmethod)lowshelf_new, 0,
177 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
178 class_addbang(lowshelf_class,lowshelf_bang);
179 class_addfloat(lowshelf_class,lowshelf_float);
180}
181
182
diff --git a/apps/plugins/pdbox/PDa/extra/m_pd.h b/apps/plugins/pdbox/PDa/extra/m_pd.h
new file mode 100644
index 0000000000..403c5b382b
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/m_pd.h
@@ -0,0 +1,1300 @@
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5#ifndef __m_pd_h_
6
7#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
8extern "C" {
9#endif
10
11#define PD_VERSION 0.37 /* oops, don't use this... */ */
12#define PD_MAJOR_VERSION 0 /* ... use these two instead. */
13#define PD_MINOR_VERSION 37
14
15/* old name for "MSW" flag -- we have to take it for the sake of many old
16"nmakefiles" for externs, which will define NT and not MSW */
17#if defined(NT) && !defined(MSW)
18#define MSW
19#endif
20
21#ifdef MSW
22// #pragma warning( disable : 4091 )
23#pragma warning( disable : 4305 ) /* uncast const double to float */
24#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */
25#pragma warning( disable : 4101 ) /* unused automatic variables */
26#endif /* MSW */
27
28 /* the external storage class is "extern" in UNIX; in MSW it's ugly. */
29#ifdef MSW
30#ifdef PD_INTERNAL
31#define EXTERN __declspec(dllexport) extern
32#else
33#define EXTERN __declspec(dllimport) extern
34#endif /* PD_INTERNAL */
35#else
36#define EXTERN extern
37#endif /* MSW */
38
39 /* and depending on the compiler, hidden data structures are
40 declared differently: */
41#if defined( __GNUC__) || defined( __BORLANDC__ ) || defined( __MWERKS__ )
42#define EXTERN_STRUCT struct
43#else
44#define EXTERN_STRUCT extern struct
45#endif
46
47
48#if !defined(_SIZE_T) && !defined(_SIZE_T_)
49#include <stddef.h> /* just for size_t -- how lame! */
50#endif
51
52#define MAXPDSTRING 1000 /* use this for anything you want */
53#define MAXPDARG 5 /* max number of args we can typecheck today */
54
55 /* signed and unsigned integer types the size of a pointer: */
56#ifdef __alpha__
57typedef long t_int;
58#else
59typedef int t_int;
60#endif
61
62typedef float t_float; /* a floating-point number at most the same size */
63typedef float t_floatarg; /* floating-point type for function calls */
64
65typedef struct _symbol
66{
67 char *s_name;
68 struct _class **s_thing;
69 struct _symbol *s_next;
70} t_symbol;
71
72EXTERN_STRUCT _array;
73#define t_array struct _array /* g_canvas.h */
74
75/* pointers to glist and array elements go through a "stub" which sticks
76around after the glist or array is freed. The stub itself is deleted when
77both the glist/array is gone and the refcount is zero, ensuring that no
78gpointers are pointing here. */
79
80#define GP_NONE 0 /* the stub points nowhere (has been cut off) */
81#define GP_GLIST 1 /* the stub points to a glist element */
82#define GP_ARRAY 2 /* ... or array */
83
84typedef struct _gstub
85{
86 union
87 {
88 struct _glist *gs_glist; /* glist we're in */
89 struct _array *gs_array; /* array we're in */
90 } gs_un;
91 int gs_which; /* GP_GLIST/GP_ARRAY */
92 int gs_refcount; /* number of gpointers pointing here */
93} t_gstub;
94
95typedef struct _gpointer /* pointer to a gobj in a glist */
96{
97 union
98 {
99 struct _scalar *gp_scalar; /* scalar we're in (if glist) */
100 union word *gp_w; /* raw data (if array) */
101 } gp_un;
102 int gp_valid; /* number which must match gpointee */
103 t_gstub *gp_stub; /* stub which points to glist/array */
104} t_gpointer;
105
106typedef union word
107{
108 t_float w_float;
109 t_symbol *w_symbol;
110 t_gpointer *w_gpointer;
111 t_array *w_array;
112 struct _glist *w_list;
113 int w_index;
114} t_word;
115
116typedef enum
117{
118 A_NULL,
119 A_FLOAT,
120 A_SYMBOL,
121 A_POINTER,
122 A_SEMI,
123 A_COMMA,
124 A_DEFFLOAT,
125 A_DEFSYM,
126 A_DOLLAR,
127 A_DOLLSYM,
128 A_GIMME,
129 A_CANT
130} t_atomtype;
131
132#define A_DEFSYMBOL A_DEFSYM /* better name for this */
133
134typedef struct _atom
135{
136 t_atomtype a_type;
137 union word a_w;
138} t_atom;
139
140EXTERN_STRUCT _class;
141#define t_class struct _class
142
143EXTERN_STRUCT _outlet;
144#define t_outlet struct _outlet
145
146EXTERN_STRUCT _inlet;
147#define t_inlet struct _inlet
148
149EXTERN_STRUCT _binbuf;
150#define t_binbuf struct _binbuf
151
152EXTERN_STRUCT _clock;
153#define t_clock struct _clock
154
155EXTERN_STRUCT _outconnect;
156#define t_outconnect struct _outconnect
157
158EXTERN_STRUCT _glist;
159#define t_glist struct _glist
160#define t_canvas struct _glist /* LATER lose this */
161
162typedef t_class *t_pd; /* pure datum: nothing but a class pointer */
163
164typedef struct _gobj /* a graphical object */
165{
166 t_pd g_pd; /* pure datum header (class) */
167 struct _gobj *g_next; /* next in list */
168} t_gobj;
169
170typedef struct _scalar /* a graphical object holding data */
171{
172 t_gobj sc_gobj; /* header for graphical object */
173 t_symbol *sc_template; /* template name (LATER replace with pointer) */
174 t_word sc_vec[1]; /* indeterminate-length array of words */
175} t_scalar;
176
177typedef struct _text /* patchable object - graphical, with text */
178{
179 t_gobj te_g; /* header for graphical object */
180 t_binbuf *te_binbuf; /* holder for the text */
181 t_outlet *te_outlet; /* linked list of outlets */
182 t_inlet *te_inlet; /* linked list of inlets */
183 short te_xpix; /* x&y location (within the toplevel) */
184 short te_ypix;
185 short te_width; /* requested width in chars, 0 if auto */
186 unsigned int te_type:2; /* from defs below */
187} t_text;
188
189#define T_TEXT 0 /* just a textual comment */
190#define T_OBJECT 1 /* a MAX style patchable object */
191#define T_MESSAGE 2 /* a MAX stype message */
192#define T_ATOM 3 /* a cell to display a number or symbol */
193
194#define te_pd te_g.g_pd
195
196 /* t_object is synonym for t_text (LATER unify them) */
197
198typedef struct _text t_object;
199
200#define ob_outlet te_outlet
201#define ob_inlet te_inlet
202#define ob_binbuf te_binbuf
203#define ob_pd te_g.g_pd
204#define ob_g te_g
205
206typedef void (*t_method)(void);
207typedef void *(*t_newmethod)( void);
208typedef void (*t_gotfn)(void *x, ...);
209
210/* ---------------- pre-defined objects and symbols --------------*/
211EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */
212EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */
213EXTERN t_symbol s_pointer;
214EXTERN t_symbol s_float;
215EXTERN t_symbol s_symbol;
216EXTERN t_symbol s_bang;
217EXTERN t_symbol s_list;
218EXTERN t_symbol s_anything;
219EXTERN t_symbol s_signal;
220EXTERN t_symbol s__N;
221EXTERN t_symbol s__X;
222EXTERN t_symbol s_x;
223EXTERN t_symbol s_y;
224EXTERN t_symbol s_;
225
226/* --------- prototypes from the central message system ----------- */
227EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv);
228EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv);
229EXTERN t_symbol *gensym(char *s);
230EXTERN t_gotfn getfn(t_pd *x, t_symbol *s);
231EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s);
232EXTERN void nullfn(void);
233EXTERN void pd_vmess(t_pd *x, t_symbol *s, char *fmt, ...);
234#define mess0(x, s) ((*getfn((x), (s)))((x)))
235#define mess1(x, s, a) ((*getfn((x), (s)))((x), (a)))
236#define mess2(x, s, a,b) ((*getfn((x), (s)))((x), (a),(b)))
237#define mess3(x, s, a,b,c) ((*getfn((x), (s)))((x), (a),(b),(c)))
238#define mess4(x, s, a,b,c,d) ((*getfn((x), (s)))((x), (a),(b),(c),(d)))
239#define mess5(x, s, a,b,c,d,e) ((*getfn((x), (s)))((x), (a),(b),(c),(d),(e)))
240EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
241EXTERN t_pd *pd_newest(void);
242
243/* --------------- memory management -------------------- */
244EXTERN void *getbytes(size_t nbytes);
245EXTERN void *getzbytes(size_t nbytes);
246EXTERN void *copybytes(void *src, size_t nbytes);
247EXTERN void freebytes(void *x, size_t nbytes);
248EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize);
249
250/* -------------------- atoms ----------------------------- */
251
252#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0)
253#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0)
254#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \
255 (atom)->a_w.w_gpointer = (gp))
256#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f))
257#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \
258 (atom)->a_w.w_symbol = (s))
259#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \
260 (atom)->a_w.w_index = (n))
261#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \
262 (atom)->a_w.w_symbol= (s))
263
264EXTERN t_float atom_getfloat(t_atom *a);
265EXTERN t_int atom_getint(t_atom *a);
266EXTERN t_symbol *atom_getsymbol(t_atom *a);
267EXTERN t_symbol *atom_gensym(t_atom *a);
268EXTERN t_float atom_getfloatarg(int which, int argc, t_atom *argv);
269EXTERN t_int atom_getintarg(int which, int argc, t_atom *argv);
270EXTERN t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv);
271
272EXTERN void atom_string(t_atom *a, char *buf, unsigned int bufsize);
273
274/* ------------------ binbufs --------------- */
275
276EXTERN t_binbuf *binbuf_new(void);
277EXTERN void binbuf_free(t_binbuf *x);
278EXTERN t_binbuf *binbuf_duplicate(t_binbuf *y);
279
280EXTERN void binbuf_text(t_binbuf *x, char *text, size_t size);
281EXTERN void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp);
282EXTERN void binbuf_clear(t_binbuf *x);
283EXTERN void binbuf_add(t_binbuf *x, int argc, t_atom *argv);
284EXTERN void binbuf_addv(t_binbuf *x, char *fmt, ...);
285EXTERN void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y);
286EXTERN void binbuf_addsemi(t_binbuf *x);
287EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv);
288EXTERN void binbuf_print(t_binbuf *x);
289EXTERN int binbuf_getnatom(t_binbuf *x);
290EXTERN t_atom *binbuf_getvec(t_binbuf *x);
291EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv);
292EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname,
293 int crflag);
294EXTERN int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
295 int crflag);
296EXTERN int binbuf_write(t_binbuf *x, char *filename, char *dir,
297 int crflag);
298EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir);
299EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av,
300 int tonew);
301
302/* ------------------ clocks --------------- */
303
304typedef long long t_time;
305EXTERN t_clock *clock_new(void *owner, t_method fn);
306EXTERN void clock_set(t_clock *x, t_time systime);
307EXTERN void clock_delay(t_clock *x, t_time delaytime);
308EXTERN void clock_unset(t_clock *x);
309EXTERN t_time clock_getlogicaltime(void);
310EXTERN t_time clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */
311EXTERN t_time clock_gettimesince(t_time prevsystime);
312EXTERN t_time clock_getsystimeafter(t_time delaytime);
313EXTERN void clock_free(t_clock *x);
314
315/* ----------------- pure data ---------------- */
316EXTERN t_pd *pd_new(t_class *cls);
317EXTERN void pd_free(t_pd *x);
318EXTERN void pd_bind(t_pd *x, t_symbol *s);
319EXTERN void pd_unbind(t_pd *x, t_symbol *s);
320EXTERN t_pd *pd_findbyclass(t_symbol *s, t_class *c);
321EXTERN void pd_pushsym(t_pd *x);
322EXTERN void pd_popsym(t_pd *x);
323EXTERN t_symbol *pd_getfilename(void);
324EXTERN t_symbol *pd_getdirname(void);
325EXTERN void pd_bang(t_pd *x);
326EXTERN void pd_pointer(t_pd *x, t_gpointer *gp);
327EXTERN void pd_float(t_pd *x, t_float f);
328EXTERN void pd_symbol(t_pd *x, t_symbol *s);
329EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv);
330EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv);
331#define pd_class(x) (*(x))
332
333/* ----------------- pointers ---------------- */
334EXTERN void gpointer_init(t_gpointer *gp);
335EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto);
336EXTERN void gpointer_unset(t_gpointer *gp);
337EXTERN int gpointer_check(const t_gpointer *gp, int headok);
338
339/* ----------------- patchable "objects" -------------- */
340EXTERN_STRUCT _inlet;
341#define t_inlet struct _inlet
342EXTERN_STRUCT _outlet;
343#define t_outlet struct _outlet
344
345EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1,
346 t_symbol *s2);
347EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
348EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp);
349EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
350EXTERN void inlet_free(t_inlet *x);
351
352EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s);
353EXTERN void outlet_bang(t_outlet *x);
354EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp);
355EXTERN void outlet_float(t_outlet *x, t_float f);
356EXTERN void outlet_symbol(t_outlet *x, t_symbol *s);
357EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
358EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
359EXTERN t_symbol *outlet_getsymbol(t_outlet *x);
360EXTERN void outlet_free(t_outlet *x);
361EXTERN t_object *pd_checkobject(t_pd *x);
362
363
364/* -------------------- canvases -------------- */
365
366EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir);
367
368EXTERN void canvas_setargs(int argc, t_atom *argv);
369EXTERN void canvas_getargs(int *argcp, t_atom **argvp);
370EXTERN t_symbol *canvas_getcurrentdir(void);
371EXTERN t_glist *canvas_getcurrent(void);
372EXTERN void canvas_makefilename(t_glist *c, char *file,
373 char *result,int resultsize);
374EXTERN t_symbol *canvas_getdir(t_glist *x);
375EXTERN int sys_fontwidth(int fontsize);
376EXTERN int sys_fontheight(int fontsize);
377EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b);
378
379/* ---------------- widget behaviors ---------------------- */
380
381EXTERN_STRUCT _widgetbehavior;
382#define t_widgetbehavior struct _widgetbehavior
383
384EXTERN_STRUCT _parentwidgetbehavior;
385#define t_parentwidgetbehavior struct _parentwidgetbehavior
386EXTERN t_parentwidgetbehavior *pd_getparentwidget(t_pd *x);
387
388/* -------------------- classes -------------- */
389
390#define CLASS_DEFAULT 0 /* flags for new classes below */
391#define CLASS_PD 1
392#define CLASS_GOBJ 2
393#define CLASS_PATCHABLE 3
394#define CLASS_NOINLET 8
395
396#define CLASS_TYPEMASK 3
397
398
399EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod,
400 t_method freemethod, size_t size, int flags, t_atomtype arg1, ...);
401EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s,
402 t_atomtype type1, ...);
403EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
404 t_atomtype arg1, ...);
405EXTERN void class_addbang(t_class *c, t_method fn);
406EXTERN void class_addpointer(t_class *c, t_method fn);
407EXTERN void class_doaddfloat(t_class *c, t_method fn);
408EXTERN void class_addsymbol(t_class *c, t_method fn);
409EXTERN void class_addlist(t_class *c, t_method fn);
410EXTERN void class_addanything(t_class *c, t_method fn);
411EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s);
412EXTERN void class_setwidget(t_class *c, t_widgetbehavior *w);
413EXTERN void class_setparentwidget(t_class *c, t_parentwidgetbehavior *w);
414EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c);
415EXTERN char *class_getname(t_class *c);
416EXTERN char *class_gethelpname(t_class *c);
417EXTERN void class_setdrawcommand(t_class *c);
418EXTERN int class_isdrawcommand(t_class *c);
419EXTERN void class_domainsignalin(t_class *c, int onset);
420#define CLASS_MAINSIGNALIN(c, type, field) \
421 class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0)
422
423 /* prototype for functions to save Pd's to a binbuf */
424typedef void (*t_savefn)(t_gobj *x, t_binbuf *b);
425EXTERN void class_setsavefn(t_class *c, t_savefn f);
426EXTERN t_savefn class_getsavefn(t_class *c);
427 /* prototype for functions to open properties dialogs */
428typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist);
429EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f);
430EXTERN t_propertiesfn class_getpropertiesfn(t_class *c);
431
432#ifndef PD_CLASS_DEF
433#define class_addbang(x, y) class_addbang((x), (t_method)(y))
434#define class_addpointer(x, y) class_addpointer((x), (t_method)(y))
435#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y))
436#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y))
437#define class_addlist(x, y) class_addlist((x), (t_method)(y))
438#define class_addanything(x, y) class_addanything((x), (t_method)(y))
439#endif
440
441/* ------------ printing --------------------------------- */
442EXTERN void post(char *fmt, ...);
443EXTERN void startpost(char *fmt, ...);
444EXTERN void poststring(char *s);
445EXTERN void postfloat(float f);
446EXTERN void postatom(int argc, t_atom *argv);
447EXTERN void endpost(void);
448EXTERN void error(char *fmt, ...);
449EXTERN void bug(char *fmt, ...);
450EXTERN void pd_error(void *object, char *fmt, ...);
451EXTERN void sys_logerror(char *object, char *s);
452EXTERN void sys_unixerror(char *object);
453EXTERN void sys_ouch(void);
454
455#ifdef __linux__
456EXTERN char* sys_get_path( void);
457#endif
458EXTERN void sys_addpath(const char* p);
459
460
461/* ------------ system interface routines ------------------- */
462EXTERN int sys_isreadablefile(const char *name);
463EXTERN void sys_bashfilename(const char *from, char *to);
464EXTERN void sys_unbashfilename(const char *from, char *to);
465EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
466 char *dirresult, char **nameresult, unsigned int size, int bin);
467EXTERN int sched_geteventno(void);
468EXTERN double sys_getrealtime(void);
469
470
471/* ------------ threading ------------------- */
472/* T.Grill - see m_sched.c */
473
474EXTERN void sys_lock(void);
475EXTERN void sys_unlock(void);
476EXTERN int sys_trylock(void);
477
478
479/* --------------- signals ----------------------------------- */
480
481#define MAXLOGSIG 32
482#define MAXSIGSIZE (1 << MAXLOGSIG)
483#ifndef FIXEDPOINT
484typedef float t_sample;
485#else
486#include "m_fixed.h"
487#endif
488
489
490typedef struct _signal
491{
492 int s_n; /* number of points in the array */
493 t_sample *s_vec; /* the array */
494 float s_sr; /* sample rate */
495 int s_refcount; /* number of times used */
496 int s_isborrowed; /* whether we're going to borrow our array */
497 struct _signal *s_borrowedfrom; /* signal to borrow it from */
498 struct _signal *s_nextfree; /* next in freelist */
499 struct _signal *s_nextused; /* next in used list */
500} t_signal;
501
502
503typedef t_int *(*t_perfroutine)(t_int *args);
504
505EXTERN t_int *plus_perform(t_int *args);
506EXTERN t_int *zero_perform(t_int *args);
507EXTERN t_int *copy_perform(t_int *args);
508
509EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n);
510EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n);
511EXTERN void dsp_add_scalarcopy(t_sample *in, t_sample *out, int n);
512EXTERN void dsp_add_zero(t_sample *out, int n);
513
514EXTERN int sys_getblksize(void);
515EXTERN float sys_getsr(void);
516EXTERN int sys_get_inchannels(void);
517EXTERN int sys_get_outchannels(void);
518
519EXTERN void dsp_add(t_perfroutine f, int n, ...);
520EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec);
521EXTERN void pd_fft(float *buf, int npoints, int inverse);
522EXTERN int ilog2(int n);
523
524EXTERN void mayer_fht(t_sample *fz, int n);
525EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag);
526EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag);
527EXTERN void mayer_realfft(int n, t_sample *real);
528EXTERN void mayer_realifft(int n, t_sample *real);
529
530EXTERN t_sample *cos_table;
531
532#define LOGCOSTABSIZE 9
533#define COSTABSIZE (1<<LOGCOSTABSIZE)
534
535EXTERN int canvas_suspend_dsp(void);
536EXTERN void canvas_resume_dsp(int oldstate);
537EXTERN void canvas_update_dsp(void);
538
539/* IOhannes { (up/downsampling) */
540typedef struct _resample
541{
542 int method; /* up/downsampling method ID */
543
544 t_int downsample; /* downsampling factor */
545 t_int upsample; /* upsampling factor */
546
547 t_sample *s_vec; /* here we hold the resampled data */
548 int s_n;
549
550 t_sample *coeffs; /* coefficients for filtering... */
551 int coefsize;
552
553 t_sample *buffer; /* buffer for filtering */
554 int bufsize;
555} t_resample;
556
557EXTERN void resample_init(t_resample *x);
558EXTERN void resample_free(t_resample *x);
559
560EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method);
561EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method);
562EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method);
563/* } IOhannes */
564
565/* ----------------------- utility functions for signals -------------- */
566EXTERN float mtof(float);
567EXTERN float ftom(float);
568EXTERN float rmstodb(float);
569EXTERN float powtodb(float);
570EXTERN float dbtorms(float);
571EXTERN float dbtopow(float);
572
573EXTERN float q8_sqrt(float);
574EXTERN float q8_rsqrt(float);
575#ifndef N32
576EXTERN float qsqrt(float); /* old names kept for extern compatibility */
577EXTERN float qrsqrt(float);
578#endif
579/* --------------------- data --------------------------------- */
580
581 /* graphical arrays */
582EXTERN_STRUCT _garray;
583#define t_garray struct _garray
584
585EXTERN t_class *garray_class;
586EXTERN int garray_getfloatarray(t_garray *x, int *size, t_sample **vec);
587EXTERN float garray_get(t_garray *x, t_symbol *s, t_int indx);
588EXTERN void garray_redraw(t_garray *x);
589EXTERN int garray_npoints(t_garray *x);
590EXTERN char *garray_vec(t_garray *x);
591EXTERN void garray_resize(t_garray *x, t_floatarg f);
592EXTERN void garray_usedindsp(t_garray *x);
593EXTERN void garray_setsaveit(t_garray *x, int saveit);
594EXTERN t_class *scalar_class;
595
596EXTERN t_float *value_get(t_symbol *s);
597EXTERN void value_release(t_symbol *s);
598EXTERN int value_getfloat(t_symbol *s, t_float *f);
599EXTERN int value_setfloat(t_symbol *s, t_float f);
600
601/* ------- GUI interface - functions to send strings to TK --------- */
602EXTERN void sys_vgui(char *fmt, ...);
603EXTERN void sys_gui(char *s);
604
605 /* dialog window creation and destruction */
606EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
607EXTERN void gfxstub_deleteforkey(void *key);
608
609extern t_class *glob_pdobject; /* object to send "pd" messages */
610
611/*------------- Max 0.26 compatibility --------------------*/
612
613/* the following reflects the new way classes are laid out, with the class
614 pointing to the messlist and not vice versa. Externs shouldn't feel it. */
615typedef t_class *t_externclass;
616
617EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine,
618 t_method freeroutine, t_symbol *name, size_t size, int tiny, \
619 t_atomtype arg1, ...);
620EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...);
621
622#define t_getbytes getbytes
623#define t_freebytes freebytes
624#define t_resizebytes resizebytes
625#define typedmess pd_typedmess
626#define vmess pd_vmess
627
628/* A definition to help gui objects straddle 0.34-0.35 changes. If this is
629defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */
630
631#define PD_USE_TE_XPIX
632
633#if 0
634/* a test for NANs and denormals. Should only be necessary on i386. */
635#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
636 (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
637/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */
638#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \
639 (((*(unsigned int*)&(f))&0x60000000)==0x60000000))
640#else
641#define PD_BADFLOAT(f) 0
642#define PD_BIGORSMALL(f) 0
643#endif
644
645#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
646}
647#endif
648
649#define __m_pd_h_
650#endif /* __m_pd_h_ */
651/* Copyright (c) 1997-1999 Miller Puckette.
652* For information on usage and redistribution, and for a DISCLAIMER OF ALL
653* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
654
655#ifndef __m_pd_h_
656
657#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
658extern "C" {
659#endif
660
661#define PD_VERSION 0.37 /* oops, don't use this... */ */
662#define PD_MAJOR_VERSION 0 /* ... use these two instead. */
663#define PD_MINOR_VERSION 37
664
665/* old name for "MSW" flag -- we have to take it for the sake of many old
666"nmakefiles" for externs, which will define NT and not MSW */
667#if defined(NT) && !defined(MSW)
668#define MSW
669#endif
670
671#ifdef MSW
672// #pragma warning( disable : 4091 )
673#pragma warning( disable : 4305 ) /* uncast const double to float */
674#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */
675#pragma warning( disable : 4101 ) /* unused automatic variables */
676#endif /* MSW */
677
678 /* the external storage class is "extern" in UNIX; in MSW it's ugly. */
679#ifdef MSW
680#ifdef PD_INTERNAL
681#define EXTERN __declspec(dllexport) extern
682#else
683#define EXTERN __declspec(dllimport) extern
684#endif /* PD_INTERNAL */
685#else
686#define EXTERN extern
687#endif /* MSW */
688
689 /* and depending on the compiler, hidden data structures are
690 declared differently: */
691#if defined( __GNUC__) || defined( __BORLANDC__ ) || defined( __MWERKS__ )
692#define EXTERN_STRUCT struct
693#else
694#define EXTERN_STRUCT extern struct
695#endif
696
697
698#if !defined(_SIZE_T) && !defined(_SIZE_T_)
699#include <stddef.h> /* just for size_t -- how lame! */
700#endif
701
702#define MAXPDSTRING 1000 /* use this for anything you want */
703#define MAXPDARG 5 /* max number of args we can typecheck today */
704
705 /* signed and unsigned integer types the size of a pointer: */
706#ifdef __alpha__
707typedef long t_int;
708#else
709typedef int t_int;
710#endif
711
712typedef float t_float; /* a floating-point number at most the same size */
713typedef float t_floatarg; /* floating-point type for function calls */
714
715typedef struct _symbol
716{
717 char *s_name;
718 struct _class **s_thing;
719 struct _symbol *s_next;
720} t_symbol;
721
722EXTERN_STRUCT _array;
723#define t_array struct _array /* g_canvas.h */
724
725/* pointers to glist and array elements go through a "stub" which sticks
726around after the glist or array is freed. The stub itself is deleted when
727both the glist/array is gone and the refcount is zero, ensuring that no
728gpointers are pointing here. */
729
730#define GP_NONE 0 /* the stub points nowhere (has been cut off) */
731#define GP_GLIST 1 /* the stub points to a glist element */
732#define GP_ARRAY 2 /* ... or array */
733
734typedef struct _gstub
735{
736 union
737 {
738 struct _glist *gs_glist; /* glist we're in */
739 struct _array *gs_array; /* array we're in */
740 } gs_un;
741 int gs_which; /* GP_GLIST/GP_ARRAY */
742 int gs_refcount; /* number of gpointers pointing here */
743} t_gstub;
744
745typedef struct _gpointer /* pointer to a gobj in a glist */
746{
747 union
748 {
749 struct _scalar *gp_scalar; /* scalar we're in (if glist) */
750 union word *gp_w; /* raw data (if array) */
751 } gp_un;
752 int gp_valid; /* number which must match gpointee */
753 t_gstub *gp_stub; /* stub which points to glist/array */
754} t_gpointer;
755
756typedef union word
757{
758 t_float w_float;
759 t_symbol *w_symbol;
760 t_gpointer *w_gpointer;
761 t_array *w_array;
762 struct _glist *w_list;
763 int w_index;
764} t_word;
765
766typedef enum
767{
768 A_NULL,
769 A_FLOAT,
770 A_SYMBOL,
771 A_POINTER,
772 A_SEMI,
773 A_COMMA,
774 A_DEFFLOAT,
775 A_DEFSYM,
776 A_DOLLAR,
777 A_DOLLSYM,
778 A_GIMME,
779 A_CANT
780} t_atomtype;
781
782#define A_DEFSYMBOL A_DEFSYM /* better name for this */
783
784typedef struct _atom
785{
786 t_atomtype a_type;
787 union word a_w;
788} t_atom;
789
790EXTERN_STRUCT _class;
791#define t_class struct _class
792
793EXTERN_STRUCT _outlet;
794#define t_outlet struct _outlet
795
796EXTERN_STRUCT _inlet;
797#define t_inlet struct _inlet
798
799EXTERN_STRUCT _binbuf;
800#define t_binbuf struct _binbuf
801
802EXTERN_STRUCT _clock;
803#define t_clock struct _clock
804
805EXTERN_STRUCT _outconnect;
806#define t_outconnect struct _outconnect
807
808EXTERN_STRUCT _glist;
809#define t_glist struct _glist
810#define t_canvas struct _glist /* LATER lose this */
811
812typedef t_class *t_pd; /* pure datum: nothing but a class pointer */
813
814typedef struct _gobj /* a graphical object */
815{
816 t_pd g_pd; /* pure datum header (class) */
817 struct _gobj *g_next; /* next in list */
818} t_gobj;
819
820typedef struct _scalar /* a graphical object holding data */
821{
822 t_gobj sc_gobj; /* header for graphical object */
823 t_symbol *sc_template; /* template name (LATER replace with pointer) */
824 t_word sc_vec[1]; /* indeterminate-length array of words */
825} t_scalar;
826
827typedef struct _text /* patchable object - graphical, with text */
828{
829 t_gobj te_g; /* header for graphical object */
830 t_binbuf *te_binbuf; /* holder for the text */
831 t_outlet *te_outlet; /* linked list of outlets */
832 t_inlet *te_inlet; /* linked list of inlets */
833 short te_xpix; /* x&y location (within the toplevel) */
834 short te_ypix;
835 short te_width; /* requested width in chars, 0 if auto */
836 unsigned int te_type:2; /* from defs below */
837} t_text;
838
839#define T_TEXT 0 /* just a textual comment */
840#define T_OBJECT 1 /* a MAX style patchable object */
841#define T_MESSAGE 2 /* a MAX stype message */
842#define T_ATOM 3 /* a cell to display a number or symbol */
843
844#define te_pd te_g.g_pd
845
846 /* t_object is synonym for t_text (LATER unify them) */
847
848typedef struct _text t_object;
849
850#define ob_outlet te_outlet
851#define ob_inlet te_inlet
852#define ob_binbuf te_binbuf
853#define ob_pd te_g.g_pd
854#define ob_g te_g
855
856typedef void (*t_method)(void);
857typedef void *(*t_newmethod)( void);
858typedef void (*t_gotfn)(void *x, ...);
859
860/* ---------------- pre-defined objects and symbols --------------*/
861EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */
862EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */
863EXTERN t_symbol s_pointer;
864EXTERN t_symbol s_float;
865EXTERN t_symbol s_symbol;
866EXTERN t_symbol s_bang;
867EXTERN t_symbol s_list;
868EXTERN t_symbol s_anything;
869EXTERN t_symbol s_signal;
870EXTERN t_symbol s__N;
871EXTERN t_symbol s__X;
872EXTERN t_symbol s_x;
873EXTERN t_symbol s_y;
874EXTERN t_symbol s_;
875
876/* --------- prototypes from the central message system ----------- */
877EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv);
878EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv);
879EXTERN t_symbol *gensym(char *s);
880EXTERN t_gotfn getfn(t_pd *x, t_symbol *s);
881EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s);
882EXTERN void nullfn(void);
883EXTERN void pd_vmess(t_pd *x, t_symbol *s, char *fmt, ...);
884#define mess0(x, s) ((*getfn((x), (s)))((x)))
885#define mess1(x, s, a) ((*getfn((x), (s)))((x), (a)))
886#define mess2(x, s, a,b) ((*getfn((x), (s)))((x), (a),(b)))
887#define mess3(x, s, a,b,c) ((*getfn((x), (s)))((x), (a),(b),(c)))
888#define mess4(x, s, a,b,c,d) ((*getfn((x), (s)))((x), (a),(b),(c),(d)))
889#define mess5(x, s, a,b,c,d,e) ((*getfn((x), (s)))((x), (a),(b),(c),(d),(e)))
890EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
891EXTERN t_pd *pd_newest(void);
892
893/* --------------- memory management -------------------- */
894EXTERN void *getbytes(size_t nbytes);
895EXTERN void *getzbytes(size_t nbytes);
896EXTERN void *copybytes(void *src, size_t nbytes);
897EXTERN void freebytes(void *x, size_t nbytes);
898EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize);
899
900/* -------------------- atoms ----------------------------- */
901
902#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0)
903#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0)
904#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \
905 (atom)->a_w.w_gpointer = (gp))
906#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f))
907#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \
908 (atom)->a_w.w_symbol = (s))
909#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \
910 (atom)->a_w.w_index = (n))
911#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \
912 (atom)->a_w.w_symbol= (s))
913
914EXTERN t_float atom_getfloat(t_atom *a);
915EXTERN t_int atom_getint(t_atom *a);
916EXTERN t_symbol *atom_getsymbol(t_atom *a);
917EXTERN t_symbol *atom_gensym(t_atom *a);
918EXTERN t_float atom_getfloatarg(int which, int argc, t_atom *argv);
919EXTERN t_int atom_getintarg(int which, int argc, t_atom *argv);
920EXTERN t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv);
921
922EXTERN void atom_string(t_atom *a, char *buf, unsigned int bufsize);
923
924/* ------------------ binbufs --------------- */
925
926EXTERN t_binbuf *binbuf_new(void);
927EXTERN void binbuf_free(t_binbuf *x);
928EXTERN t_binbuf *binbuf_duplicate(t_binbuf *y);
929
930EXTERN void binbuf_text(t_binbuf *x, char *text, size_t size);
931EXTERN void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp);
932EXTERN void binbuf_clear(t_binbuf *x);
933EXTERN void binbuf_add(t_binbuf *x, int argc, t_atom *argv);
934EXTERN void binbuf_addv(t_binbuf *x, char *fmt, ...);
935EXTERN void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y);
936EXTERN void binbuf_addsemi(t_binbuf *x);
937EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv);
938EXTERN void binbuf_print(t_binbuf *x);
939EXTERN int binbuf_getnatom(t_binbuf *x);
940EXTERN t_atom *binbuf_getvec(t_binbuf *x);
941EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv);
942EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname,
943 int crflag);
944EXTERN int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
945 int crflag);
946EXTERN int binbuf_write(t_binbuf *x, char *filename, char *dir,
947 int crflag);
948EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir);
949EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av,
950 int tonew);
951
952/* ------------------ clocks --------------- */
953
954typedef long long t_time;
955EXTERN t_clock *clock_new(void *owner, t_method fn);
956EXTERN void clock_set(t_clock *x, t_time systime);
957EXTERN void clock_delay(t_clock *x, t_time delaytime);
958EXTERN void clock_unset(t_clock *x);
959EXTERN t_time clock_getlogicaltime(void);
960EXTERN t_time clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */
961EXTERN t_time clock_gettimesince(t_time prevsystime);
962EXTERN t_time clock_getsystimeafter(t_time delaytime);
963EXTERN void clock_free(t_clock *x);
964
965/* ----------------- pure data ---------------- */
966EXTERN t_pd *pd_new(t_class *cls);
967EXTERN void pd_free(t_pd *x);
968EXTERN void pd_bind(t_pd *x, t_symbol *s);
969EXTERN void pd_unbind(t_pd *x, t_symbol *s);
970EXTERN t_pd *pd_findbyclass(t_symbol *s, t_class *c);
971EXTERN void pd_pushsym(t_pd *x);
972EXTERN void pd_popsym(t_pd *x);
973EXTERN t_symbol *pd_getfilename(void);
974EXTERN t_symbol *pd_getdirname(void);
975EXTERN void pd_bang(t_pd *x);
976EXTERN void pd_pointer(t_pd *x, t_gpointer *gp);
977EXTERN void pd_float(t_pd *x, t_float f);
978EXTERN void pd_symbol(t_pd *x, t_symbol *s);
979EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv);
980EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv);
981#define pd_class(x) (*(x))
982
983/* ----------------- pointers ---------------- */
984EXTERN void gpointer_init(t_gpointer *gp);
985EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto);
986EXTERN void gpointer_unset(t_gpointer *gp);
987EXTERN int gpointer_check(const t_gpointer *gp, int headok);
988
989/* ----------------- patchable "objects" -------------- */
990EXTERN_STRUCT _inlet;
991#define t_inlet struct _inlet
992EXTERN_STRUCT _outlet;
993#define t_outlet struct _outlet
994
995EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1,
996 t_symbol *s2);
997EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
998EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp);
999EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
1000EXTERN void inlet_free(t_inlet *x);
1001
1002EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s);
1003EXTERN void outlet_bang(t_outlet *x);
1004EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp);
1005EXTERN void outlet_float(t_outlet *x, t_float f);
1006EXTERN void outlet_symbol(t_outlet *x, t_symbol *s);
1007EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
1008EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
1009EXTERN t_symbol *outlet_getsymbol(t_outlet *x);
1010EXTERN void outlet_free(t_outlet *x);
1011EXTERN t_object *pd_checkobject(t_pd *x);
1012
1013
1014/* -------------------- canvases -------------- */
1015
1016EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir);
1017
1018EXTERN void canvas_setargs(int argc, t_atom *argv);
1019EXTERN void canvas_getargs(int *argcp, t_atom **argvp);
1020EXTERN t_symbol *canvas_getcurrentdir(void);
1021EXTERN t_glist *canvas_getcurrent(void);
1022EXTERN void canvas_makefilename(t_glist *c, char *file,
1023 char *result,int resultsize);
1024EXTERN t_symbol *canvas_getdir(t_glist *x);
1025EXTERN int sys_fontwidth(int fontsize);
1026EXTERN int sys_fontheight(int fontsize);
1027EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b);
1028
1029/* ---------------- widget behaviors ---------------------- */
1030
1031EXTERN_STRUCT _widgetbehavior;
1032#define t_widgetbehavior struct _widgetbehavior
1033
1034EXTERN_STRUCT _parentwidgetbehavior;
1035#define t_parentwidgetbehavior struct _parentwidgetbehavior
1036EXTERN t_parentwidgetbehavior *pd_getparentwidget(t_pd *x);
1037
1038/* -------------------- classes -------------- */
1039
1040#define CLASS_DEFAULT 0 /* flags for new classes below */
1041#define CLASS_PD 1
1042#define CLASS_GOBJ 2
1043#define CLASS_PATCHABLE 3
1044#define CLASS_NOINLET 8
1045
1046#define CLASS_TYPEMASK 3
1047
1048
1049EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod,
1050 t_method freemethod, size_t size, int flags, t_atomtype arg1, ...);
1051EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s,
1052 t_atomtype type1, ...);
1053EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
1054 t_atomtype arg1, ...);
1055EXTERN void class_addbang(t_class *c, t_method fn);
1056EXTERN void class_addpointer(t_class *c, t_method fn);
1057EXTERN void class_doaddfloat(t_class *c, t_method fn);
1058EXTERN void class_addsymbol(t_class *c, t_method fn);
1059EXTERN void class_addlist(t_class *c, t_method fn);
1060EXTERN void class_addanything(t_class *c, t_method fn);
1061EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s);
1062EXTERN void class_setwidget(t_class *c, t_widgetbehavior *w);
1063EXTERN void class_setparentwidget(t_class *c, t_parentwidgetbehavior *w);
1064EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c);
1065EXTERN char *class_getname(t_class *c);
1066EXTERN char *class_gethelpname(t_class *c);
1067EXTERN void class_setdrawcommand(t_class *c);
1068EXTERN int class_isdrawcommand(t_class *c);
1069EXTERN void class_domainsignalin(t_class *c, int onset);
1070#define CLASS_MAINSIGNALIN(c, type, field) \
1071 class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0)
1072
1073 /* prototype for functions to save Pd's to a binbuf */
1074typedef void (*t_savefn)(t_gobj *x, t_binbuf *b);
1075EXTERN void class_setsavefn(t_class *c, t_savefn f);
1076EXTERN t_savefn class_getsavefn(t_class *c);
1077 /* prototype for functions to open properties dialogs */
1078typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist);
1079EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f);
1080EXTERN t_propertiesfn class_getpropertiesfn(t_class *c);
1081
1082#ifndef PD_CLASS_DEF
1083#define class_addbang(x, y) class_addbang((x), (t_method)(y))
1084#define class_addpointer(x, y) class_addpointer((x), (t_method)(y))
1085#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y))
1086#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y))
1087#define class_addlist(x, y) class_addlist((x), (t_method)(y))
1088#define class_addanything(x, y) class_addanything((x), (t_method)(y))
1089#endif
1090
1091/* ------------ printing --------------------------------- */
1092EXTERN void post(char *fmt, ...);
1093EXTERN void startpost(char *fmt, ...);
1094EXTERN void poststring(char *s);
1095EXTERN void postfloat(float f);
1096EXTERN void postatom(int argc, t_atom *argv);
1097EXTERN void endpost(void);
1098EXTERN void error(char *fmt, ...);
1099EXTERN void bug(char *fmt, ...);
1100EXTERN void pd_error(void *object, char *fmt, ...);
1101EXTERN void sys_logerror(char *object, char *s);
1102EXTERN void sys_unixerror(char *object);
1103EXTERN void sys_ouch(void);
1104
1105#ifdef __linux__
1106EXTERN char* sys_get_path( void);
1107#endif
1108EXTERN void sys_addpath(const char* p);
1109
1110
1111/* ------------ system interface routines ------------------- */
1112EXTERN int sys_isreadablefile(const char *name);
1113EXTERN void sys_bashfilename(const char *from, char *to);
1114EXTERN void sys_unbashfilename(const char *from, char *to);
1115EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
1116 char *dirresult, char **nameresult, unsigned int size, int bin);
1117EXTERN int sched_geteventno(void);
1118EXTERN double sys_getrealtime(void);
1119
1120
1121/* ------------ threading ------------------- */
1122/* T.Grill - see m_sched.c */
1123
1124EXTERN void sys_lock(void);
1125EXTERN void sys_unlock(void);
1126EXTERN int sys_trylock(void);
1127
1128
1129/* --------------- signals ----------------------------------- */
1130
1131#define MAXLOGSIG 32
1132#define MAXSIGSIZE (1 << MAXLOGSIG)
1133#ifndef FIXEDPOINT
1134typedef float t_sample;
1135#else
1136#include "m_fixed.h"
1137#endif
1138
1139
1140typedef struct _signal
1141{
1142 int s_n; /* number of points in the array */
1143 t_sample *s_vec; /* the array */
1144 float s_sr; /* sample rate */
1145 int s_refcount; /* number of times used */
1146 int s_isborrowed; /* whether we're going to borrow our array */
1147 struct _signal *s_borrowedfrom; /* signal to borrow it from */
1148 struct _signal *s_nextfree; /* next in freelist */
1149 struct _signal *s_nextused; /* next in used list */
1150} t_signal;
1151
1152
1153typedef t_int *(*t_perfroutine)(t_int *args);
1154
1155EXTERN t_int *plus_perform(t_int *args);
1156EXTERN t_int *zero_perform(t_int *args);
1157EXTERN t_int *copy_perform(t_int *args);
1158
1159EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n);
1160EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n);
1161EXTERN void dsp_add_scalarcopy(t_sample *in, t_sample *out, int n);
1162EXTERN void dsp_add_zero(t_sample *out, int n);
1163
1164EXTERN int sys_getblksize(void);
1165EXTERN float sys_getsr(void);
1166EXTERN int sys_get_inchannels(void);
1167EXTERN int sys_get_outchannels(void);
1168
1169EXTERN void dsp_add(t_perfroutine f, int n, ...);
1170EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec);
1171EXTERN void pd_fft(float *buf, int npoints, int inverse);
1172EXTERN int ilog2(int n);
1173
1174EXTERN void mayer_fht(t_sample *fz, int n);
1175EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag);
1176EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag);
1177EXTERN void mayer_realfft(int n, t_sample *real);
1178EXTERN void mayer_realifft(int n, t_sample *real);
1179
1180EXTERN t_sample *cos_table;
1181
1182#define LOGCOSTABSIZE 9
1183#define COSTABSIZE (1<<LOGCOSTABSIZE)
1184
1185EXTERN int canvas_suspend_dsp(void);
1186EXTERN void canvas_resume_dsp(int oldstate);
1187EXTERN void canvas_update_dsp(void);
1188
1189/* IOhannes { (up/downsampling) */
1190typedef struct _resample
1191{
1192 int method; /* up/downsampling method ID */
1193
1194 t_int downsample; /* downsampling factor */
1195 t_int upsample; /* upsampling factor */
1196
1197 t_sample *s_vec; /* here we hold the resampled data */
1198 int s_n;
1199
1200 t_sample *coeffs; /* coefficients for filtering... */
1201 int coefsize;
1202
1203 t_sample *buffer; /* buffer for filtering */
1204 int bufsize;
1205} t_resample;
1206
1207EXTERN void resample_init(t_resample *x);
1208EXTERN void resample_free(t_resample *x);
1209
1210EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method);
1211EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method);
1212EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method);
1213/* } IOhannes */
1214
1215/* ----------------------- utility functions for signals -------------- */
1216EXTERN float mtof(float);
1217EXTERN float ftom(float);
1218EXTERN float rmstodb(float);
1219EXTERN float powtodb(float);
1220EXTERN float dbtorms(float);
1221EXTERN float dbtopow(float);
1222
1223EXTERN float q8_sqrt(float);
1224EXTERN float q8_rsqrt(float);
1225#ifndef N32
1226EXTERN float qsqrt(float); /* old names kept for extern compatibility */
1227EXTERN float qrsqrt(float);
1228#endif
1229/* --------------------- data --------------------------------- */
1230
1231 /* graphical arrays */
1232EXTERN_STRUCT _garray;
1233#define t_garray struct _garray
1234
1235EXTERN t_class *garray_class;
1236EXTERN int garray_getfloatarray(t_garray *x, int *size, t_sample **vec);
1237EXTERN float garray_get(t_garray *x, t_symbol *s, t_int indx);
1238EXTERN void garray_redraw(t_garray *x);
1239EXTERN int garray_npoints(t_garray *x);
1240EXTERN char *garray_vec(t_garray *x);
1241EXTERN void garray_resize(t_garray *x, t_floatarg f);
1242EXTERN void garray_usedindsp(t_garray *x);
1243EXTERN void garray_setsaveit(t_garray *x, int saveit);
1244EXTERN t_class *scalar_class;
1245
1246EXTERN t_float *value_get(t_symbol *s);
1247EXTERN void value_release(t_symbol *s);
1248EXTERN int value_getfloat(t_symbol *s, t_float *f);
1249EXTERN int value_setfloat(t_symbol *s, t_float f);
1250
1251/* ------- GUI interface - functions to send strings to TK --------- */
1252EXTERN void sys_vgui(char *fmt, ...);
1253EXTERN void sys_gui(char *s);
1254
1255 /* dialog window creation and destruction */
1256EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
1257EXTERN void gfxstub_deleteforkey(void *key);
1258
1259extern t_class *glob_pdobject; /* object to send "pd" messages */
1260
1261/*------------- Max 0.26 compatibility --------------------*/
1262
1263/* the following reflects the new way classes are laid out, with the class
1264 pointing to the messlist and not vice versa. Externs shouldn't feel it. */
1265typedef t_class *t_externclass;
1266
1267EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine,
1268 t_method freeroutine, t_symbol *name, size_t size, int tiny, \
1269 t_atomtype arg1, ...);
1270EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...);
1271
1272#define t_getbytes getbytes
1273#define t_freebytes freebytes
1274#define t_resizebytes resizebytes
1275#define typedmess pd_typedmess
1276#define vmess pd_vmess
1277
1278/* A definition to help gui objects straddle 0.34-0.35 changes. If this is
1279defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */
1280
1281#define PD_USE_TE_XPIX
1282
1283#if 0
1284/* a test for NANs and denormals. Should only be necessary on i386. */
1285#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
1286 (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
1287/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */
1288#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \
1289 (((*(unsigned int*)&(f))&0x60000000)==0x60000000))
1290#else
1291#define PD_BADFLOAT(f) 0
1292#define PD_BIGORSMALL(f) 0
1293#endif
1294
1295#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
1296}
1297#endif
1298
1299#define __m_pd_h_
1300#endif /* __m_pd_h_ */
diff --git a/apps/plugins/pdbox/PDa/extra/makefile b/apps/plugins/pdbox/PDa/extra/makefile
new file mode 100644
index 0000000000..270491de63
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/makefile
@@ -0,0 +1,66 @@
1
2VERSION = 0.2
3SOURCE = $(shell ls *.c)
4TARGETS = $(SOURCE:.c=.pd_linux)
5
6EXT= pd_linux
7
8AFLAGS = -g -O2 -I./ -DFIXEDPOINT
9EFLAGS = -shared -Wl,-export-dynamic
10PREFIX = /usr
11
12
13all: $(TARGETS)
14
15clean:
16 -rm $(TARGETS)
17 -rm *.o *~
18
19tar: clean
20 cd ..;tar czvf PDa-externals-$(VERSION).tgz PDa-externals
21
22upload: tar
23 scp ../PDa-externals-$(VERSION).tgz gige@xdv.org:~/www/pda/release
24
25install:
26 install -d $(DESTDIR)/$(PREFIX)/lib/pd/extra
27 cp $(TARGETS) $(DESTDIR)/$(PREFIX)/lib/pd/extra
28
29%.$(EXT) : %.o
30 $(CC) -o $@ $(EFLAGS) $+
31
32%.o : %.c
33 $(CC) -c $(AFLAGS) $(CFLAGS) $+
34
35VERSION = 0.2
36SOURCE = $(shell ls *.c)
37TARGETS = $(SOURCE:.c=.pd_linux)
38
39EXT= pd_linux
40
41AFLAGS = -g -O2 -I./ -DFIXEDPOINT
42EFLAGS = -shared -Wl,-export-dynamic
43PREFIX = /usr
44
45
46all: $(TARGETS)
47
48clean:
49 -rm $(TARGETS)
50 -rm *.o *~
51
52tar: clean
53 cd ..;tar czvf PDa-externals-$(VERSION).tgz PDa-externals
54
55upload: tar
56 scp ../PDa-externals-$(VERSION).tgz gige@xdv.org:~/www/pda/release
57
58install:
59 install -d $(DESTDIR)/$(PREFIX)/lib/pd/extra
60 cp $(TARGETS) $(DESTDIR)/$(PREFIX)/lib/pd/extra
61
62%.$(EXT) : %.o
63 $(CC) -o $@ $(EFLAGS) $+
64
65%.o : %.c
66 $(CC) -c $(AFLAGS) $(CFLAGS) $+ \ No newline at end of file
diff --git a/apps/plugins/pdbox/PDa/extra/moog~.c b/apps/plugins/pdbox/PDa/extra/moog~.c
new file mode 100644
index 0000000000..ee7acc99aa
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/moog~.c
@@ -0,0 +1,366 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4#include "math.h"
5#include <m_pd.h>
6
7/* ----------------------------- moog ----------------------------- */
8static t_class *moog_class;
9
10
11typedef struct _moog
12{
13 t_object x_obj;
14 t_pd in2;
15 t_sample x_1,x_2,x_3,x_4;
16 t_sample y_1,y_2,y_3,y_4;
17} t_moog;
18
19static void moog_reset(t_moog *x)
20{
21 x->x_1 = x->x_2 = x->x_3 = x->x_4 = 0;
22 x->y_1 = x->y_2 = x->y_3 = x->y_4 = 0;
23
24}
25
26
27
28static void *moog_new(t_symbol *s, int argc, t_atom *argv)
29{
30 if (argc > 1) post("moog~: extra arguments ignored");
31 {
32 t_moog *x = (t_moog *)pd_new(moog_class);
33 outlet_new(&x->x_obj, &s_signal);
34 inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
35 inlet_new(&x->x_obj, &x->in2, &s_signal, &s_signal);
36 moog_reset(x);
37 return (x);
38 }
39
40
41}
42
43
44
45static t_sample calc_k(t_sample f,t_sample k) {
46 if (k>itofix(4)) k = itofix(4);
47 if (k < 0) k = 0;
48 if (f <= itofix(3800)) return k;
49 k = k - mult(0.5,(f-idiv(itofix(3800),itofix(4300))));
50 return k;
51}
52
53t_int *moog_perform(t_int *w)
54{
55 t_moog* x = (t_moog*) (w[1]);
56 t_sample *in1 = (t_sample *)(w[2]);
57 t_sample *p = (t_sample *)(w[3]);
58 t_sample *k = (t_sample *)(w[4]);
59
60 t_sample *out = (t_sample *)(w[5]);
61 int n = (int)(w[6]);
62 t_sample in;
63 t_sample pt,pt1;
64
65 t_sample x1 = x->x_1;
66 t_sample x2 = x->x_2;
67 t_sample x3 = x->x_3;
68 t_sample x4 = x->x_4;
69 t_sample ys1 = x->y_1;
70 t_sample ys2 = x->y_2;
71 t_sample ys3 = x->y_3;
72 t_sample ys4 = x->y_4;
73
74
75 while (n--) {
76 if (*p > itofix(8140)) *p = itofix(8140);
77 *k = calc_k(*p,*k);
78 pt =*p;
79 pt1=mult((pt+1),ftofix(0.76923077));
80 in = *in1++ - mult(*k,ys4);
81 ys1 = mult(pt1,in) + mult(0.3,x1) - mult(pt,ys1);
82 x1 = in;
83 ys2 = mult(pt1,ys1) + mult(0.3,x2) - mult(pt,ys2);
84 x2 = ys1;
85 ys3 = mult(pt1,ys2) + mult(0.3,x3) - mult(pt,ys3);
86 x3 = ys2;
87 ys4 = mult(pt1,ys3) + mult(0.3,x4) - mult(pt,ys4);
88 x4 = ys3;
89 *out++ = ys4;
90 }
91
92
93 x->y_1 = ys1;
94 x->y_2 = ys2;
95 x->y_3 = ys3;
96 x->y_4 = ys4;
97 x->x_1 = x1;
98 x->x_2 = x2;
99 x->x_3 = x3;
100 x->x_4 = x4;
101
102 return (w+7);
103}
104
105
106#define CLIP(x) x = ((x) > 1.0 ? (1.0) : (x))
107
108t_int *moog_perf8(t_int *w)
109{
110 t_moog* x = (t_moog*) (w[1]);
111 t_sample *in1 = (t_sample *)(w[2]);
112 t_sample *p = (t_sample *)(w[3]);
113 t_sample *k = (t_sample *)(w[4]);
114 t_sample *out = (t_sample *)(w[5]);
115 int n = (int)(w[6]);
116
117 t_sample x1 = x->x_1;
118 t_sample x2 = x->x_2;
119 t_sample x3 = x->x_3;
120 t_sample x4 = x->x_4;
121 t_sample ys1 = x->y_1;
122 t_sample ys2 = x->y_2;
123 t_sample ys3 = x->y_3;
124 t_sample ys4 = x->y_4;
125
126 t_sample temp,temp2;
127 t_sample pt,pt1;
128 t_sample in;
129
130 while (n--) {
131 if (*p > itofix(8140)) *p = itofix(8140);
132 *k = calc_k(*p,*k);
133
134 pt =mult(*p, ftofix(0.01*0.0140845)) - ftofix(0.9999999f);
135 pt1=mult((pt+itofix(1)),ftofix(0.76923077));
136 in = *in1++ - mult(*k,ys4);
137 ys1 = mult(pt1,(in + mult(ftofix(0.3),x1))) - mult(pt,ys1);
138 x1 = in;
139 ys2 = mult(pt1,(ys1 + mult(0.3,x2))) - mult(pt,ys2);
140 x2 = ys1;
141 ys3 = mult(pt1,(ys2 + mult(0.3,x3))) - mult(pt,ys3);
142 x3 = ys2;
143 ys4 = mult(pt1,(ys3 + mult(0.3,x4))) - mult(pt,ys4);
144 x4 = ys3;
145 *out++ = ys4;
146
147 p++;k++;
148 }
149
150 x->y_1 = ys1;
151 x->y_2 = ys2;
152 x->y_3 = ys3;
153 x->y_4 = ys4;
154 x->x_1 = x1;
155 x->x_2 = x2;
156 x->x_3 = x3;
157 x->x_4 = x4;
158
159 return (w+7);
160}
161
162void dsp_add_moog(t_moog *x, t_sample *in1, t_sample *in2, t_sample *in3, t_sample *out, int n)
163{
164 if (n&7)
165 dsp_add(moog_perform, 6,(t_int)x, in1,in2,in3, out, n);
166 else
167 dsp_add(moog_perf8, 6,(t_int) x, in1, in2, in3, out, n);
168}
169
170static void moog_dsp(t_moog *x, t_signal **sp)
171{
172 dsp_add_moog(x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,sp[0]->s_n);
173}
174
175
176void moog_tilde_setup(void)
177{
178 moog_class = class_new(gensym("moog~"), (t_newmethod)moog_new, 0,
179 sizeof(t_moog), 0, A_GIMME, 0);
180 class_addmethod(moog_class, nullfn, gensym("signal"), 0);
181 class_addmethod(moog_class, (t_method)moog_reset, gensym("reset"), 0);
182 class_addmethod(moog_class, (t_method)moog_dsp, gensym("dsp"), A_NULL);
183}
184/* (C) Guenter Geiger <geiger@epy.co.at> */
185
186
187#include "math.h"
188#include <m_pd.h>
189
190/* ----------------------------- moog ----------------------------- */
191static t_class *moog_class;
192
193
194typedef struct _moog
195{
196 t_object x_obj;
197 t_pd in2;
198 t_sample x_1,x_2,x_3,x_4;
199 t_sample y_1,y_2,y_3,y_4;
200} t_moog;
201
202static void moog_reset(t_moog *x)
203{
204 x->x_1 = x->x_2 = x->x_3 = x->x_4 = 0;
205 x->y_1 = x->y_2 = x->y_3 = x->y_4 = 0;
206
207}
208
209
210
211static void *moog_new(t_symbol *s, int argc, t_atom *argv)
212{
213 if (argc > 1) post("moog~: extra arguments ignored");
214 {
215 t_moog *x = (t_moog *)pd_new(moog_class);
216 outlet_new(&x->x_obj, &s_signal);
217 inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
218 inlet_new(&x->x_obj, &x->in2, &s_signal, &s_signal);
219 moog_reset(x);
220 return (x);
221 }
222
223
224}
225
226
227
228static t_sample calc_k(t_sample f,t_sample k) {
229 if (k>itofix(4)) k = itofix(4);
230 if (k < 0) k = 0;
231 if (f <= itofix(3800)) return k;
232 k = k - mult(0.5,(f-idiv(itofix(3800),itofix(4300))));
233 return k;
234}
235
236t_int *moog_perform(t_int *w)
237{
238 t_moog* x = (t_moog*) (w[1]);
239 t_sample *in1 = (t_sample *)(w[2]);
240 t_sample *p = (t_sample *)(w[3]);
241 t_sample *k = (t_sample *)(w[4]);
242
243 t_sample *out = (t_sample *)(w[5]);
244 int n = (int)(w[6]);
245 t_sample in;
246 t_sample pt,pt1;
247
248 t_sample x1 = x->x_1;
249 t_sample x2 = x->x_2;
250 t_sample x3 = x->x_3;
251 t_sample x4 = x->x_4;
252 t_sample ys1 = x->y_1;
253 t_sample ys2 = x->y_2;
254 t_sample ys3 = x->y_3;
255 t_sample ys4 = x->y_4;
256
257
258 while (n--) {
259 if (*p > itofix(8140)) *p = itofix(8140);
260 *k = calc_k(*p,*k);
261 pt =*p;
262 pt1=mult((pt+1),ftofix(0.76923077));
263 in = *in1++ - mult(*k,ys4);
264 ys1 = mult(pt1,in) + mult(0.3,x1) - mult(pt,ys1);
265 x1 = in;
266 ys2 = mult(pt1,ys1) + mult(0.3,x2) - mult(pt,ys2);
267 x2 = ys1;
268 ys3 = mult(pt1,ys2) + mult(0.3,x3) - mult(pt,ys3);
269 x3 = ys2;
270 ys4 = mult(pt1,ys3) + mult(0.3,x4) - mult(pt,ys4);
271 x4 = ys3;
272 *out++ = ys4;
273 }
274
275
276 x->y_1 = ys1;
277 x->y_2 = ys2;
278 x->y_3 = ys3;
279 x->y_4 = ys4;
280 x->x_1 = x1;
281 x->x_2 = x2;
282 x->x_3 = x3;
283 x->x_4 = x4;
284
285 return (w+7);
286}
287
288
289#define CLIP(x) x = ((x) > 1.0 ? (1.0) : (x))
290
291t_int *moog_perf8(t_int *w)
292{
293 t_moog* x = (t_moog*) (w[1]);
294 t_sample *in1 = (t_sample *)(w[2]);
295 t_sample *p = (t_sample *)(w[3]);
296 t_sample *k = (t_sample *)(w[4]);
297 t_sample *out = (t_sample *)(w[5]);
298 int n = (int)(w[6]);
299
300 t_sample x1 = x->x_1;
301 t_sample x2 = x->x_2;
302 t_sample x3 = x->x_3;
303 t_sample x4 = x->x_4;
304 t_sample ys1 = x->y_1;
305 t_sample ys2 = x->y_2;
306 t_sample ys3 = x->y_3;
307 t_sample ys4 = x->y_4;
308
309 t_sample temp,temp2;
310 t_sample pt,pt1;
311 t_sample in;
312
313 while (n--) {
314 if (*p > itofix(8140)) *p = itofix(8140);
315 *k = calc_k(*p,*k);
316
317 pt =mult(*p, ftofix(0.01*0.0140845)) - ftofix(0.9999999f);
318 pt1=mult((pt+itofix(1)),ftofix(0.76923077));
319 in = *in1++ - mult(*k,ys4);
320 ys1 = mult(pt1,(in + mult(ftofix(0.3),x1))) - mult(pt,ys1);
321 x1 = in;
322 ys2 = mult(pt1,(ys1 + mult(0.3,x2))) - mult(pt,ys2);
323 x2 = ys1;
324 ys3 = mult(pt1,(ys2 + mult(0.3,x3))) - mult(pt,ys3);
325 x3 = ys2;
326 ys4 = mult(pt1,(ys3 + mult(0.3,x4))) - mult(pt,ys4);
327 x4 = ys3;
328 *out++ = ys4;
329
330 p++;k++;
331 }
332
333 x->y_1 = ys1;
334 x->y_2 = ys2;
335 x->y_3 = ys3;
336 x->y_4 = ys4;
337 x->x_1 = x1;
338 x->x_2 = x2;
339 x->x_3 = x3;
340 x->x_4 = x4;
341
342 return (w+7);
343}
344
345void dsp_add_moog(t_moog *x, t_sample *in1, t_sample *in2, t_sample *in3, t_sample *out, int n)
346{
347 if (n&7)
348 dsp_add(moog_perform, 6,(t_int)x, in1,in2,in3, out, n);
349 else
350 dsp_add(moog_perf8, 6,(t_int) x, in1, in2, in3, out, n);
351}
352
353static void moog_dsp(t_moog *x, t_signal **sp)
354{
355 dsp_add_moog(x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,sp[0]->s_n);
356}
357
358
359void moog_tilde_setup(void)
360{
361 moog_class = class_new(gensym("moog~"), (t_newmethod)moog_new, 0,
362 sizeof(t_moog), 0, A_GIMME, 0);
363 class_addmethod(moog_class, nullfn, gensym("signal"), 0);
364 class_addmethod(moog_class, (t_method)moog_reset, gensym("reset"), 0);
365 class_addmethod(moog_class, (t_method)moog_dsp, gensym("dsp"), A_NULL);
366}
diff --git a/apps/plugins/pdbox/PDa/extra/notch.c b/apps/plugins/pdbox/PDa/extra/notch.c
new file mode 100644
index 0000000000..49be753ff2
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/notch.c
@@ -0,0 +1,178 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3
4/*
5
6 These filter coefficients computations are taken from
7 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
8
9 written by Robert Bristow-Johnson
10
11*/
12
13#include "m_pd.h"
14#ifdef NT
15#pragma warning( disable : 4244 )
16#pragma warning( disable : 4305 )
17#endif
18#include <math.h>
19#include "filters.h"
20
21
22
23/* ------------------- notch ----------------------------*/
24
25static t_class *notch_class;
26
27void notch_bang(t_rbjfilter *x)
28{
29 t_atom at[5];
30 t_float omega = e_omega(x->x_freq,x->x_rate);
31 t_float alpha = e_alpha(x->x_bw* 0.01,omega);
32 t_float b1 = -2.*cos(omega);
33 t_float b0 = 1;
34 t_float b2 = b0;
35 t_float a0 = 1 + alpha;
36 t_float a1 = -2.*cos(omega);
37 t_float a2 = 1 - alpha;
38
39/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
40
41 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
42 post("notch: filter unstable -> resetting");
43 a0=1.;a1=0.;a2=0.;
44 b0=1.;b1=0.;b2=0.;
45 }
46
47 SETFLOAT(at,-a1/a0);
48 SETFLOAT(at+1,-a2/a0);
49 SETFLOAT(at+2,b0/a0);
50 SETFLOAT(at+3,b1/a0);
51 SETFLOAT(at+4,b2/a0);
52
53 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
54}
55
56
57void notch_float(t_rbjfilter *x,t_floatarg f)
58{
59 x->x_freq = f;
60 notch_bang(x);
61}
62
63
64static void *notch_new(t_floatarg f,t_floatarg bw)
65{
66 t_rbjfilter *x = (t_rbjfilter *)pd_new(notch_class);
67
68 x->x_rate = 44100.0;
69 outlet_new(&x->x_obj,&s_float);
70/* floatinlet_new(&x->x_obj, &x->x_gain); */
71 floatinlet_new(&x->x_obj, &x->x_bw);
72 if (f > 0.) x->x_freq = f;
73 if (bw > 0.) x->x_bw = bw;
74 return (x);
75}
76
77
78void notch_setup(void)
79{
80 notch_class = class_new(gensym("notch"), (t_newmethod)notch_new, 0,
81 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
82 class_addbang(notch_class,notch_bang);
83 class_addfloat(notch_class,notch_float);
84}
85
86
87
88
89
90/* (C) Guenter Geiger <geiger@epy.co.at> */
91
92
93/*
94
95 These filter coefficients computations are taken from
96 http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt
97
98 written by Robert Bristow-Johnson
99
100*/
101
102#include "m_pd.h"
103#ifdef NT
104#pragma warning( disable : 4244 )
105#pragma warning( disable : 4305 )
106#endif
107#include <math.h>
108#include "filters.h"
109
110
111
112/* ------------------- notch ----------------------------*/
113
114static t_class *notch_class;
115
116void notch_bang(t_rbjfilter *x)
117{
118 t_atom at[5];
119 t_float omega = e_omega(x->x_freq,x->x_rate);
120 t_float alpha = e_alpha(x->x_bw* 0.01,omega);
121 t_float b1 = -2.*cos(omega);
122 t_float b0 = 1;
123 t_float b2 = b0;
124 t_float a0 = 1 + alpha;
125 t_float a1 = -2.*cos(omega);
126 t_float a2 = 1 - alpha;
127
128/* post("bang %f %f %f",x->x_freq, x->x_gain, x->x_bw); */
129
130 if (!check_stability(-a1/a0,-a2/a0,b0/a0,b1/a0,b2/a0)) {
131 post("notch: filter unstable -> resetting");
132 a0=1.;a1=0.;a2=0.;
133 b0=1.;b1=0.;b2=0.;
134 }
135
136 SETFLOAT(at,-a1/a0);
137 SETFLOAT(at+1,-a2/a0);
138 SETFLOAT(at+2,b0/a0);
139 SETFLOAT(at+3,b1/a0);
140 SETFLOAT(at+4,b2/a0);
141
142 outlet_list(x->x_obj.ob_outlet,&s_list,5,at);
143}
144
145
146void notch_float(t_rbjfilter *x,t_floatarg f)
147{
148 x->x_freq = f;
149 notch_bang(x);
150}
151
152
153static void *notch_new(t_floatarg f,t_floatarg bw)
154{
155 t_rbjfilter *x = (t_rbjfilter *)pd_new(notch_class);
156
157 x->x_rate = 44100.0;
158 outlet_new(&x->x_obj,&s_float);
159/* floatinlet_new(&x->x_obj, &x->x_gain); */
160 floatinlet_new(&x->x_obj, &x->x_bw);
161 if (f > 0.) x->x_freq = f;
162 if (bw > 0.) x->x_bw = bw;
163 return (x);
164}
165
166
167void notch_setup(void)
168{
169 notch_class = class_new(gensym("notch"), (t_newmethod)notch_new, 0,
170 sizeof(t_rbjfilter), 0,A_DEFFLOAT,A_DEFFLOAT,0);
171 class_addbang(notch_class,notch_bang);
172 class_addfloat(notch_class,notch_float);
173}
174
175
176
177
178
diff --git a/apps/plugins/pdbox/PDa/extra/s_stuff.h b/apps/plugins/pdbox/PDa/extra/s_stuff.h
new file mode 100644
index 0000000000..6dc9a88c4b
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/s_stuff.h
@@ -0,0 +1,430 @@
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* Audio and MIDI I/O, and other scheduling and system stuff. */
6
7/* NOTE: this file describes Pd implementation details which may change
8in future releases. The public (stable) API is in m_pd.h. */
9
10/* in s_file.c */
11typedef struct _namelist
12{
13 struct _namelist *nl_next;
14 char *nl_string;
15} t_namelist;
16
17t_namelist *namelist_append(t_namelist *listwas, const char *s);
18void namelist_free(t_namelist *listwas);
19
20/* s_main.c */
21extern int sys_debuglevel;
22extern int sys_verbose;
23extern int sys_noloadbang;
24extern int sys_nogui;
25extern char *sys_guicmd;
26
27EXTERN int sys_nearestfontsize(int fontsize);
28EXTERN int sys_hostfontsize(int fontsize);
29
30extern int sys_defaultfont;
31extern t_symbol *sys_libdir; /* library directory for auxilliary files */
32
33/* s_loader.c */
34int sys_load_lib(char *dirname, char *filename);
35
36/* s_audio.c */
37
38#define SENDDACS_NO 0 /* return values for sys_send_dacs() */
39#define SENDDACS_YES 1
40#define SENDDACS_SLEPT 2
41
42#define DEFDACBLKSIZE 64
43extern int sys_schedblocksize; /* audio block size for scheduler */
44extern int sys_hipriority; /* real-time flag, true if priority boosted */
45extern t_sample *sys_soundout;
46extern t_sample *sys_soundin;
47extern int sys_inchannels;
48extern int sys_outchannels;
49extern int sys_advance_samples; /* scheduler advance in samples */
50extern int sys_blocksize; /* audio I/O block size in sample frames */
51extern float sys_dacsr;
52extern int sys_schedadvance;
53extern int sys_sleepgrain;
54void sys_open_audio(int naudioindev, int *audioindev,
55 int nchindev, int *chindev,
56 int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
57 int srate, int advance, int enable);
58void sys_close_audio(void);
59
60 /* s_midi.c */
61void sys_open_midi(int nmidiin, int *midiinvec, int nmidiout, int *midioutvec);
62
63 /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */
64void sys_do_open_midi(int nmidiin, int *midiinvec,
65 int nmidiout, int *midioutvec);
66void sys_close_midi(void);
67void midi_getdevs(char *indevlist, int *nindevs,
68 char *outdevlist, int *noutdevs, int maxndev, int devdescsize);
69
70int sys_send_dacs(void);
71void sys_reportidle(void);
72void sys_set_priority(int higher);
73void sys_audiobuf(int nbufs);
74void sys_getmeters(float *inmax, float *outmax);
75void sys_listdevs(void);
76void sys_setblocksize(int n);
77
78/* s_midi.c */
79#define MAXMIDIINDEV 16 /* max. number of input ports */
80#define MAXMIDIOUTDEV 16 /* max. number of output ports */
81extern int sys_nmidiin;
82extern int sys_nmidiout;
83extern int sys_midiindevlist[];
84extern int sys_midioutdevlist[];
85
86EXTERN void sys_putmidimess(int portno, int a, int b, int c);
87EXTERN void sys_putmidibyte(int portno, int a);
88EXTERN void sys_poll_midi(void);
89EXTERN void sys_setmiditimediff(double inbuftime, double outbuftime);
90EXTERN void sys_midibytein(int portno, int byte);
91
92/* m_sched.c */
93EXTERN void sys_log_error(int type);
94#define ERR_NOTHING 0
95#define ERR_ADCSLEPT 1
96#define ERR_DACSLEPT 2
97#define ERR_RESYNC 3
98#define ERR_DATALATE 4
99void sched_set_using_dacs(int flag);
100
101/* s_inter.c */
102
103EXTERN void sys_microsleep(int microsec);
104
105EXTERN void sys_bail(int exitcode);
106EXTERN int sys_pollgui(void);
107
108EXTERN_STRUCT _socketreceiver;
109#define t_socketreceiver struct _socketreceiver
110
111typedef void (*t_socketnotifier)(void *x);
112typedef void (*t_socketreceivefn)(void *x, t_binbuf *b);
113
114EXTERN t_socketreceiver *socketreceiver_new(void *owner,
115 t_socketnotifier notifier, t_socketreceivefn socketreceivefn, int udp);
116EXTERN void socketreceiver_read(t_socketreceiver *x, int fd);
117EXTERN void sys_sockerror(char *s);
118EXTERN void sys_closesocket(int fd);
119
120typedef void (*t_fdpollfn)(void *ptr, int fd);
121EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
122EXTERN void sys_rmpollfn(int fd);
123#ifdef UNIX
124void sys_setalarm(int microsec);
125void sys_setvirtualalarm( void);
126#endif
127
128#define API_ALSA 1
129#define API_OSS 2
130#define API_MMIO 3
131#define API_PORTAUDIO 4
132#define API_JACK 5
133
134#ifdef __linux__
135#define API_DEFAULT API_OSS
136#define API_DEFSTRING "OSS"
137#endif
138#ifdef MSW
139#define API_DEFAULT API_MMIO
140#define API_DEFSTRING "MMIO"
141#endif
142#ifdef MACOSX
143#define API_DEFAULT API_PORTAUDIO
144#define API_DEFSTRING "portaudio"
145#endif
146#define DEFAULTAUDIODEV 0
147
148#define MAXAUDIOINDEV 4
149#define MAXAUDIOOUTDEV 4
150
151#define DEFMIDIDEV 0
152
153#define DEFAULTSRATE 44100
154#ifdef MSW
155#define DEFAULTADVANCE 70
156#else
157#define DEFAULTADVANCE 50
158#endif
159
160int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
161 t_sample *soundout, int framesperbuf, int nbuffers,
162 int indeviceno, int outdeviceno);
163void pa_close_audio(void);
164int pa_send_dacs(void);
165void sys_reportidle(void);
166void pa_listdevs(void);
167void pa_getdevs(char *indevlist, int *nindevs,
168 char *outdevlist, int *noutdevs, int *canmulti,
169 int maxndev, int devdescsize);
170
171int oss_open_audio(int naudioindev, int *audioindev, int nchindev,
172 int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
173 int *choutdev, int rate); /* IOhannes */
174void oss_close_audio(void);
175int oss_send_dacs(void);
176void oss_reportidle(void);
177void oss_getdevs(char *indevlist, int *nindevs,
178 char *outdevlist, int *noutdevs, int *canmulti,
179 int maxndev, int devdescsize);
180
181int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
182 int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
183 int *choutdev, int rate);
184void alsa_close_audio(void);
185int alsa_send_dacs(void);
186void alsa_reportidle(void);
187void alsa_getdevs(char *indevlist, int *nindevs,
188 char *outdevlist, int *noutdevs, int *canmulti,
189 int maxndev, int devdescsize);
190
191int jack_open_audio(int wantinchans, int wantoutchans, int srate);
192void jack_close_audio(void);
193int jack_send_dacs(void);
194void jack_reportidle(void);
195void jack_listdevs(void);
196
197void mmio_open_audio(int naudioindev, int *audioindev,
198 int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
199 int nchoutdev, int *choutdev, int rate);
200void mmio_close_audio( void);
201void mmio_reportidle(void);
202int mmio_send_dacs(void);
203void mmio_getdevs(char *indevlist, int *nindevs,
204 char *outdevlist, int *noutdevs, int *canmulti,
205 int maxndev, int devdescsize);
206
207void sys_listmididevs(void);
208void sys_set_audio_api(int whichapi);
209void sys_get_audio_apis(char *buf);
210extern int sys_audioapi;
211void sys_set_audio_state(int onoff);
212
213/* API dependent audio flags and settings */
214void oss_set32bit( void);
215void linux_alsa_devname(char *devname);
216/* Copyright (c) 1997-1999 Miller Puckette.
217* For information on usage and redistribution, and for a DISCLAIMER OF ALL
218* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
219
220/* Audio and MIDI I/O, and other scheduling and system stuff. */
221
222/* NOTE: this file describes Pd implementation details which may change
223in future releases. The public (stable) API is in m_pd.h. */
224
225/* in s_file.c */
226typedef struct _namelist
227{
228 struct _namelist *nl_next;
229 char *nl_string;
230} t_namelist;
231
232t_namelist *namelist_append(t_namelist *listwas, const char *s);
233void namelist_free(t_namelist *listwas);
234
235/* s_main.c */
236extern int sys_debuglevel;
237extern int sys_verbose;
238extern int sys_noloadbang;
239extern int sys_nogui;
240extern char *sys_guicmd;
241
242EXTERN int sys_nearestfontsize(int fontsize);
243EXTERN int sys_hostfontsize(int fontsize);
244
245extern int sys_defaultfont;
246extern t_symbol *sys_libdir; /* library directory for auxilliary files */
247
248/* s_loader.c */
249int sys_load_lib(char *dirname, char *filename);
250
251/* s_audio.c */
252
253#define SENDDACS_NO 0 /* return values for sys_send_dacs() */
254#define SENDDACS_YES 1
255#define SENDDACS_SLEPT 2
256
257#define DEFDACBLKSIZE 64
258extern int sys_schedblocksize; /* audio block size for scheduler */
259extern int sys_hipriority; /* real-time flag, true if priority boosted */
260extern t_sample *sys_soundout;
261extern t_sample *sys_soundin;
262extern int sys_inchannels;
263extern int sys_outchannels;
264extern int sys_advance_samples; /* scheduler advance in samples */
265extern int sys_blocksize; /* audio I/O block size in sample frames */
266extern float sys_dacsr;
267extern int sys_schedadvance;
268extern int sys_sleepgrain;
269void sys_open_audio(int naudioindev, int *audioindev,
270 int nchindev, int *chindev,
271 int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
272 int srate, int advance, int enable);
273void sys_close_audio(void);
274
275 /* s_midi.c */
276void sys_open_midi(int nmidiin, int *midiinvec, int nmidiout, int *midioutvec);
277
278 /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */
279void sys_do_open_midi(int nmidiin, int *midiinvec,
280 int nmidiout, int *midioutvec);
281void sys_close_midi(void);
282void midi_getdevs(char *indevlist, int *nindevs,
283 char *outdevlist, int *noutdevs, int maxndev, int devdescsize);
284
285int sys_send_dacs(void);
286void sys_reportidle(void);
287void sys_set_priority(int higher);
288void sys_audiobuf(int nbufs);
289void sys_getmeters(float *inmax, float *outmax);
290void sys_listdevs(void);
291void sys_setblocksize(int n);
292
293/* s_midi.c */
294#define MAXMIDIINDEV 16 /* max. number of input ports */
295#define MAXMIDIOUTDEV 16 /* max. number of output ports */
296extern int sys_nmidiin;
297extern int sys_nmidiout;
298extern int sys_midiindevlist[];
299extern int sys_midioutdevlist[];
300
301EXTERN void sys_putmidimess(int portno, int a, int b, int c);
302EXTERN void sys_putmidibyte(int portno, int a);
303EXTERN void sys_poll_midi(void);
304EXTERN void sys_setmiditimediff(double inbuftime, double outbuftime);
305EXTERN void sys_midibytein(int portno, int byte);
306
307/* m_sched.c */
308EXTERN void sys_log_error(int type);
309#define ERR_NOTHING 0
310#define ERR_ADCSLEPT 1
311#define ERR_DACSLEPT 2
312#define ERR_RESYNC 3
313#define ERR_DATALATE 4
314void sched_set_using_dacs(int flag);
315
316/* s_inter.c */
317
318EXTERN void sys_microsleep(int microsec);
319
320EXTERN void sys_bail(int exitcode);
321EXTERN int sys_pollgui(void);
322
323EXTERN_STRUCT _socketreceiver;
324#define t_socketreceiver struct _socketreceiver
325
326typedef void (*t_socketnotifier)(void *x);
327typedef void (*t_socketreceivefn)(void *x, t_binbuf *b);
328
329EXTERN t_socketreceiver *socketreceiver_new(void *owner,
330 t_socketnotifier notifier, t_socketreceivefn socketreceivefn, int udp);
331EXTERN void socketreceiver_read(t_socketreceiver *x, int fd);
332EXTERN void sys_sockerror(char *s);
333EXTERN void sys_closesocket(int fd);
334
335typedef void (*t_fdpollfn)(void *ptr, int fd);
336EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr);
337EXTERN void sys_rmpollfn(int fd);
338#ifdef UNIX
339void sys_setalarm(int microsec);
340void sys_setvirtualalarm( void);
341#endif
342
343#define API_ALSA 1
344#define API_OSS 2
345#define API_MMIO 3
346#define API_PORTAUDIO 4
347#define API_JACK 5
348
349#ifdef __linux__
350#define API_DEFAULT API_OSS
351#define API_DEFSTRING "OSS"
352#endif
353#ifdef MSW
354#define API_DEFAULT API_MMIO
355#define API_DEFSTRING "MMIO"
356#endif
357#ifdef MACOSX
358#define API_DEFAULT API_PORTAUDIO
359#define API_DEFSTRING "portaudio"
360#endif
361#define DEFAULTAUDIODEV 0
362
363#define MAXAUDIOINDEV 4
364#define MAXAUDIOOUTDEV 4
365
366#define DEFMIDIDEV 0
367
368#define DEFAULTSRATE 44100
369#ifdef MSW
370#define DEFAULTADVANCE 70
371#else
372#define DEFAULTADVANCE 50
373#endif
374
375int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
376 t_sample *soundout, int framesperbuf, int nbuffers,
377 int indeviceno, int outdeviceno);
378void pa_close_audio(void);
379int pa_send_dacs(void);
380void sys_reportidle(void);
381void pa_listdevs(void);
382void pa_getdevs(char *indevlist, int *nindevs,
383 char *outdevlist, int *noutdevs, int *canmulti,
384 int maxndev, int devdescsize);
385
386int oss_open_audio(int naudioindev, int *audioindev, int nchindev,
387 int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
388 int *choutdev, int rate); /* IOhannes */
389void oss_close_audio(void);
390int oss_send_dacs(void);
391void oss_reportidle(void);
392void oss_getdevs(char *indevlist, int *nindevs,
393 char *outdevlist, int *noutdevs, int *canmulti,
394 int maxndev, int devdescsize);
395
396int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
397 int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
398 int *choutdev, int rate);
399void alsa_close_audio(void);
400int alsa_send_dacs(void);
401void alsa_reportidle(void);
402void alsa_getdevs(char *indevlist, int *nindevs,
403 char *outdevlist, int *noutdevs, int *canmulti,
404 int maxndev, int devdescsize);
405
406int jack_open_audio(int wantinchans, int wantoutchans, int srate);
407void jack_close_audio(void);
408int jack_send_dacs(void);
409void jack_reportidle(void);
410void jack_listdevs(void);
411
412void mmio_open_audio(int naudioindev, int *audioindev,
413 int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
414 int nchoutdev, int *choutdev, int rate);
415void mmio_close_audio( void);
416void mmio_reportidle(void);
417int mmio_send_dacs(void);
418void mmio_getdevs(char *indevlist, int *nindevs,
419 char *outdevlist, int *noutdevs, int *canmulti,
420 int maxndev, int devdescsize);
421
422void sys_listmididevs(void);
423void sys_set_audio_api(int whichapi);
424void sys_get_audio_apis(char *buf);
425extern int sys_audioapi;
426void sys_set_audio_state(int onoff);
427
428/* API dependent audio flags and settings */
429void oss_set32bit( void);
430void linux_alsa_devname(char *devname);
diff --git a/apps/plugins/pdbox/PDa/extra/sendOSC.c b/apps/plugins/pdbox/PDa/extra/sendOSC.c
new file mode 100644
index 0000000000..c00f693280
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/sendOSC.c
@@ -0,0 +1,2922 @@
1/*
2Written by Matt Wright, The Center for New Music and Audio Technologies,
3University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
4The Regents of the University of California (Regents).
5
6Permission to use, copy, modify, distribute, and distribute modified versions
7of this software and its documentation without fee and without a signed
8licensing agreement, is hereby granted, provided that the above copyright
9notice, this paragraph and the following two paragraphs appear in all copies,
10modifications, and distributions.
11
12IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
13SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
14OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
15BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
17REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
20HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
21MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22
23
24The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
25*/
26
27
28/* sendOSC.c
29
30 Matt Wright, 6/3/97
31 based on sendOSC.c, which was based on a version by Adrian Freed
32
33 Text-based OpenSoundControl client. User can enter messages via command
34 line arguments or standard input.
35
36 Version 0.1: "play" feature
37 Version 0.2: Message type tags.
38
39 pd version branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/sendOSC/sendOSC.c
40 -------------
41 -- added bundle stuff to send. jdl 20020416
42 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
43 -- ost_at_test.at + i22_at_test.at, 2000-2002
44 modified to compile as pd externel
45*/
46
47#define MAX_ARGS 2000
48#define SC_BUFFER_SIZE 64000
49
50#include "m_pd.h"
51#include "OSC-client.h"
52
53#include <string.h>
54#include <sys/types.h>
55#include <stdlib.h>
56#include <stdio.h>
57#include <sys/stat.h>
58#include <sys/types.h>
59
60#ifdef WIN32
61#include <winsock2.h>
62#include <io.h>
63#include <errno.h>
64#include <fcntl.h>
65#include <winsock2.h>
66#include <ctype.h>
67#include <signal.h>
68#else
69#include <sys/socket.h>
70#include <netinet/in.h>
71#include <rpc/rpc.h>
72#include <sys/times.h>
73#include <sys/param.h>
74#include <sys/time.h>
75#include <sys/ioctl.h>
76#include <netdb.h>
77#endif
78
79#ifdef __APPLE__
80 #include <string.h>
81#endif
82
83#define UNIXDG_PATH "/tmp/htm"
84#define UNIXDG_TMP "/tmp/htm.XXXXXX"
85
86
87
88OSCTimeTag OSCTT_Immediately(void) {
89 OSCTimeTag result;
90 result.seconds = 0;
91 result.fraction = 1;
92 return result;
93}
94
95
96OSCTimeTag OSCTT_CurrentTime(void) {
97 OSCTimeTag result;
98 result.seconds = 0;
99 result.fraction = 1;
100 return result;
101}
102
103OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
104 OSCTimeTag result;
105 result.seconds = 0;
106 result.fraction = 1;
107 return result;
108}
109
110
111typedef int bool;
112
113typedef struct
114{
115 float srate;
116
117 struct sockaddr_in serv_addr; /* udp socket */
118 #ifndef WIN32
119 struct sockaddr_un userv_addr; /* UNIX socket */
120 #endif
121 int sockfd; /* socket file descriptor */
122 int index, len,uservlen;
123 void *addr;
124 int id;
125} desc;
126
127
128/* open a socket for HTM communication to given host on given portnumber */
129/* if host is 0 then UNIX protocol is used (i.e. local communication */
130void *OpenHTMSocket(char *host, int portnumber)
131{
132 struct sockaddr_in cl_addr;
133 #ifndef WIN32
134 int sockfd;
135 struct sockaddr_un ucl_addr;
136 #else
137 unsigned int sockfd;
138 #endif
139
140 desc *o;
141 int oval = 1;
142 o = malloc(sizeof(*o));
143 if(!o) return 0;
144
145 #ifndef WIN32
146
147 if(!host)
148 {
149 char *mktemp(char *);
150 int clilen;
151 o->len = sizeof(ucl_addr);
152 /*
153 * Fill in the structure "userv_addr" with the address of the
154 * server that we want to send to.
155 */
156
157 bzero((char *) &o->userv_addr, sizeof(o->userv_addr));
158 o->userv_addr.sun_family = AF_UNIX;
159 strcpy(o->userv_addr.sun_path, UNIXDG_PATH);
160 sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber);
161 o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path);
162 o->addr = &(o->userv_addr);
163 /*
164 * Open a socket (a UNIX domain datagram socket).
165 */
166
167 if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0)
168 {
169 /*
170 * Bind a local address for us.
171 * In the UNIX domain we have to choose our own name (that
172 * should be unique). We'll use mktemp() to create a unique
173 * pathname, based on our process id.
174 */
175
176 bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */
177 ucl_addr.sun_family = AF_UNIX;
178 strcpy(ucl_addr.sun_path, UNIXDG_TMP);
179
180 mktemp(ucl_addr.sun_path);
181 clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path);
182
183 if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0)
184 {
185 perror("client: can't bind local address");
186 close(sockfd);
187 sockfd = -1;
188 }
189 }
190 else
191 perror("unable to make socket\n");
192
193 }else
194
195 #endif
196
197 {
198 /*
199 * Fill in the structure "serv_addr" with the address of the
200 * server that we want to send to.
201 */
202 o->len = sizeof(cl_addr);
203
204 #ifdef WIN32
205 ZeroMemory((char *)&o->serv_addr, sizeof(o->serv_addr));
206 #else
207 bzero((char *)&o->serv_addr, sizeof(o->serv_addr));
208 #endif
209
210 o->serv_addr.sin_family = AF_INET;
211
212 /* MW 6/6/96: Call gethostbyname() instead of inet_addr(),
213 so that host can be either an Internet host name (e.g.,
214 "les") or an Internet address in standard dot notation
215 (e.g., "128.32.122.13") */
216 {
217 struct hostent *hostsEntry;
218 unsigned long address;
219
220 hostsEntry = gethostbyname(host);
221 if (hostsEntry == NULL) {
222 fprintf(stderr, "Couldn't decipher host name \"%s\"\n", host);
223 #ifndef WIN32
224 herror(NULL);
225 #endif
226 return 0;
227 }
228 address = *((unsigned long *) hostsEntry->h_addr_list[0]);
229 o->serv_addr.sin_addr.s_addr = address;
230 }
231
232 /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */
233
234 /* End MW changes */
235
236 /*
237 * Open a socket (a UDP domain datagram socket).
238 */
239
240
241 #ifdef WIN32
242 o->serv_addr.sin_port = htons((USHORT)portnumber);
243 o->addr = &(o->serv_addr);
244 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) {
245 ZeroMemory((char *)&cl_addr, sizeof(cl_addr));
246 cl_addr.sin_family = AF_INET;
247 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
248 cl_addr.sin_port = htons(0);
249
250 // enable broadcast: jdl ~2003
251 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
252 perror("setsockopt");
253 }
254
255 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
256 perror("could not bind\n");
257 closesocket(sockfd);
258 sockfd = -1;
259 }
260 }
261 else { perror("unable to make socket\n");}
262 #else
263 o->serv_addr.sin_port = htons(portnumber);
264 o->addr = &(o->serv_addr);
265 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
266 bzero((char *)&cl_addr, sizeof(cl_addr));
267 cl_addr.sin_family = AF_INET;
268 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
269 cl_addr.sin_port = htons(0);
270
271 // enable broadcast: jdl ~2003
272 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
273 perror("setsockopt");
274 }
275
276 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
277 perror("could not bind\n");
278 close(sockfd);
279 sockfd = -1;
280 }
281 }
282 else { perror("unable to make socket\n");}
283 #endif
284 }
285 #ifdef WIN32
286 if(sockfd == INVALID_SOCKET) {
287 #else
288 if(sockfd < 0) {
289 #endif
290 free(o);
291 o = 0;
292 }
293 else
294 o->sockfd = sockfd;
295 return o;
296}
297
298static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b)
299{
300 int rcount;
301 if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count)
302 {
303 printf("sockfd %d count %d rcount %dlength %d\n", sockfd,count,rcount,length);
304 return FALSE;
305 }
306 return TRUE;
307}
308
309bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer)
310{
311 desc *o = (desc *)htmsendhandle;
312 return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer);
313}
314void CloseHTMSocket(void *htmsendhandle)
315{
316 desc *o = (desc *)htmsendhandle;
317 #ifdef WIN32
318 if(SOCKET_ERROR == closesocket(o->sockfd)) {
319 perror("CloseHTMSocket::closesocket failed\n");
320 return;
321 }
322 #else
323 if(close(o->sockfd) == -1)
324 {
325 perror("CloseHTMSocket::closesocket failed");
326 return;
327 }
328 #endif
329
330 free(o);
331}
332
333
334///////////////////////
335// from sendOSC
336
337typedef struct {
338 //enum {INT, FLOAT, STRING} type;
339 enum {INT_osc, FLOAT_osc, STRING_osc} type;
340 union {
341 int i;
342 float f;
343 char *s;
344 } datum;
345} typedArg;
346
347void CommandLineMode(int argc, char *argv[], void *htmsocket);
348OSCTimeTag ParseTimeTag(char *s);
349void ParseInteractiveLine(OSCbuf *buf, char *mesg);
350typedArg ParseToken(char *token);
351int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args);
352void SendBuffer(void *htmsocket, OSCbuf *buf);
353void SendData(void *htmsocket, int size, char *data);
354/* defined in OSC-system-dependent.c now */
355
356//static void *htmsocket;
357static int exitStatus = 0;
358static int useTypeTags = 0;
359
360static char bufferForOSCbuf[SC_BUFFER_SIZE];
361
362
363/////////
364// end from sendOSC
365
366static t_class *sendOSC_class;
367
368typedef struct _sendOSC
369{
370 t_object x_obj;
371 int x_protocol; // UDP/TCP (udp only atm)
372 t_int x_typetags; // typetag flag
373 void *x_htmsocket; // sending socket
374 int x_bundle; // bundle open flag
375 OSCbuf x_oscbuf[1]; // OSCbuffer
376 t_outlet *x_bdpthout;// bundle-depth floatoutlet
377} t_sendOSC;
378
379static void *sendOSC_new(t_floatarg udpflag)
380{
381 t_sendOSC *x = (t_sendOSC *)pd_new(sendOSC_class);
382 outlet_new(&x->x_obj, &s_float);
383 x->x_htmsocket = 0; // {{raf}}
384 // set udp
385 x->x_protocol = SOCK_STREAM;
386 // set typetags to 1 by default
387 x->x_typetags = 1;
388 // bunlde is closed
389 x->x_bundle = 0;
390 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
391 x->x_bdpthout = outlet_new(&x->x_obj, 0); // outlet_float();
392 //x->x_oscbuf =
393 return (x);
394}
395
396
397void sendOSC_openbundle(t_sendOSC *x)
398{
399 if (x->x_oscbuf->bundleDepth + 1 >= MAX_BUNDLE_NESTING ||
400 OSC_openBundle(x->x_oscbuf, OSCTT_Immediately()))
401 {
402 post("Problem opening bundle: %s\n", OSC_errorMessage);
403 return;
404 }
405 x->x_bundle = 1;
406 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
407}
408
409static void sendOSC_closebundle(t_sendOSC *x)
410{
411 if (OSC_closeBundle(x->x_oscbuf)) {
412 post("Problem closing bundle: %s\n", OSC_errorMessage);
413 return;
414 }
415 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
416 // in bundle mode we send when bundle is closed?
417 if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) {
418 // post("x_oscbuf: something inside me?");
419 if (x->x_htmsocket) {
420 SendBuffer(x->x_htmsocket, x->x_oscbuf);
421 } else {
422 post("sendOSC: not connected");
423 }
424 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
425 x->x_bundle = 0;
426 return;
427 }
428 // post("x_oscbuf: something went wrong");
429}
430
431static void sendOSC_settypetags(t_sendOSC *x, t_float *f)
432 {
433 x->x_typetags = (int)f;
434 post("sendOSC.c: setting typetags %d",x->x_typetags);
435 }
436
437
438static void sendOSC_connect(t_sendOSC *x, t_symbol *hostname,
439 t_floatarg fportno)
440{
441 int portno = fportno;
442 /* create a socket */
443
444 // make sure handle is available
445 if(x->x_htmsocket == 0) {
446 //
447 x->x_htmsocket = OpenHTMSocket(hostname->s_name, portno);
448 if (!x->x_htmsocket)
449 post("Couldn't open socket: ");
450 else {
451 post("connected to port %s:%d (hSock=%d)", hostname->s_name, portno, x->x_htmsocket);
452 outlet_float(x->x_obj.ob_outlet, 1);
453 }
454 }
455 else
456 perror("call to sendOSC_connect() against UNavailable socket handle");
457}
458
459void sendOSC_disconnect(t_sendOSC *x)
460{
461 if (x->x_htmsocket)
462 {
463 post("disconnecting htmsock (hSock=%d)...", x->x_htmsocket);
464 CloseHTMSocket(x->x_htmsocket);
465 x->x_htmsocket = 0; // {{raf}} semi-quasi-semaphorize this
466 outlet_float(x->x_obj.ob_outlet, 0);
467 }
468 else {
469 perror("call to sendOSC_disconnect() against unused socket handle");
470 }
471}
472
473void sendOSC_senduntyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
474{
475 char* targv[MAXPDARG];
476 char tmparg[MAXPDSTRING];
477 char* tmp = tmparg;
478 //char testarg[MAXPDSTRING];
479 int c;
480
481 post("sendOSC: use typetags 0/1 message and plain send method so send untypetagged...");
482 return;
483
484 //atom_string(argv,testarg, MAXPDSTRING);
485 for (c=0;c<argc;c++) {
486 atom_string(argv+c,tmp, 80);
487 targv[c] = tmp;
488 tmp += strlen(tmp)+1;
489 }
490
491 // this sock needs to be larger than 0, not >= ..
492 if (x->x_htmsocket)
493 {
494 CommandLineMode(argc, targv, x->x_htmsocket);
495 // post("test %d", c);
496 }
497 else {
498 post("sendOSC: not connected");
499 }
500}
501
502//////////////////////////////////////////////////////////////////////
503// this is the real and only sending routine now, for both typed and
504// undtyped mode.
505
506static void sendOSC_sendtyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
507{
508 char* targv[MAX_ARGS];
509 char tmparg[MAXPDSTRING];
510 char* tmp = tmparg;
511 int c;
512
513 char *messageName;
514 char *token;
515 typedArg args[MAX_ARGS];
516 int i,j;
517 int numArgs = 0;
518
519 messageName = "";
520#ifdef DEBUG
521 post ("sendOSC: messageName: %s", messageName);
522#endif
523
524
525
526 for (c=0;c<argc;c++) {
527 atom_string(argv+c,tmp, 80);
528
529#ifdef DEBUG
530 // post ("sendOSC: %d, %s",c, tmp);
531#endif
532
533 targv[c] = tmp;
534 tmp += strlen(tmp)+1;
535
536#ifdef DEBUG
537 // post ("sendOSC: %d, %s",c, targv[c]);
538#endif
539 }
540
541 // this sock needs to be larger than 0, not >= ..
542 if (x->x_htmsocket > 0)
543 {
544#ifdef DEBUG
545 post ("sendOSC: type tags? %d", useTypeTags);
546#endif
547
548 messageName = strtok(targv[0], ",");
549 j = 1;
550 for (i = j; i < argc; i++) {
551 token = strtok(targv[i],",");
552 args[i-j] = ParseToken(token);
553#ifdef DEBUG
554 printf("cell-cont: %s\n", targv[i]);
555 printf(" type-id: %d\n", args[i-j]);
556#endif
557 numArgs = i;
558 }
559
560
561 if(WriteMessage(x->x_oscbuf, messageName, numArgs, args)) {
562 post("sendOSC: usage error, write-msg failed: %s", OSC_errorMessage);
563 return;
564 }
565
566 if(!x->x_bundle) {
567 SendBuffer(x->x_htmsocket, x->x_oscbuf);
568 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
569 }
570
571 //CommandLineMode(argc, targv, x->x_htmsocket);
572 //useTypeTags = 0;
573 }
574 else {
575 post("sendOSC: not connected");
576 }
577}
578
579void sendOSC_send(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
580{
581 if(!argc) {
582 post("not sending empty message.");
583 return;
584 }
585 if(x->x_typetags) {
586 useTypeTags = 1;
587 sendOSC_sendtyped(x,s,argc,argv);
588 useTypeTags = 0;
589 } else {
590 sendOSC_sendtyped(x,s,argc,argv);
591 }
592}
593
594static void sendOSC_free(t_sendOSC *x)
595{
596 sendOSC_disconnect(x);
597}
598
599#ifdef WIN32
600 OSC_API void sendOSC_setup(void) {
601#else
602 void sendOSC_setup(void) {
603#endif
604 sendOSC_class = class_new(gensym("sendOSC"), (t_newmethod)sendOSC_new,
605 (t_method)sendOSC_free,
606 sizeof(t_sendOSC), 0, A_DEFFLOAT, 0);
607 class_addmethod(sendOSC_class, (t_method)sendOSC_connect,
608 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
609 class_addmethod(sendOSC_class, (t_method)sendOSC_disconnect,
610 gensym("disconnect"), 0);
611 class_addmethod(sendOSC_class, (t_method)sendOSC_settypetags,
612 gensym("typetags"),
613 A_FLOAT, 0);
614 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
615 gensym("send"),
616 A_GIMME, 0);
617 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
618 gensym("senduntyped"),
619 A_GIMME, 0);
620 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
621 gensym("sendtyped"),
622 A_GIMME, 0);
623 class_addmethod(sendOSC_class, (t_method)sendOSC_openbundle,
624 gensym("["),
625 0, 0);
626 class_addmethod(sendOSC_class, (t_method)sendOSC_closebundle,
627 gensym("]"),
628 0, 0);
629 class_sethelpsymbol(sendOSC_class, gensym("sendOSC-help.pd"));
630}
631
632
633
634
635
636/* Exit status codes:
637 0: successful
638 2: Message(s) dropped because of buffer overflow
639 3: Socket error
640 4: Usage error
641 5: Internal error
642*/
643
644void CommandLineMode(int argc, char *argv[], void *htmsocket) {
645 char *messageName;
646 char *token;
647 typedArg args[MAX_ARGS];
648 int i,j, numArgs;
649 OSCbuf buf[1];
650
651 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
652
653 if (argc > 1) {
654 post("argc (%d) > 1", argc);
655 }
656
657 // ParseInteractiveLine(buf, argv);
658 messageName = strtok(argv[0], ",");
659
660 j = 1;
661 for (i = j; i < argc; i++) {
662 token = strtok(argv[i],",");
663 args[i-j] = ParseToken(token);
664#ifdef DEBUG
665 printf("cell-cont: %s\n", argv[i]);
666 printf(" type-id: %d\n", args[i-j]);
667#endif
668 numArgs = i;
669 }
670
671 if(WriteMessage(buf, messageName, numArgs, args)) {
672 post("sendOSC: usage error. write-msg failed: %s", OSC_errorMessage);
673 return;
674 }
675
676 SendBuffer(htmsocket, buf);
677}
678
679#define MAXMESG 2048
680
681void InteractiveMode(void *htmsocket) {
682 char mesg[MAXMESG];
683 OSCbuf buf[1];
684 int bundleDepth = 0; /* At first, we haven't seen "[". */
685
686 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
687
688 while (fgets(mesg, MAXMESG, stdin) != NULL) {
689 if (mesg[0] == '\n') {
690 if (bundleDepth > 0) {
691 /* Ignore blank lines inside a group. */
692 } else {
693 /* blank line => repeat previous send */
694 SendBuffer(htmsocket, buf);
695 }
696 continue;
697 }
698
699 if (bundleDepth == 0) {
700 OSC_resetBuffer(buf);
701 }
702
703 if (mesg[0] == '[') {
704 OSCTimeTag tt = ParseTimeTag(mesg+1);
705 if (OSC_openBundle(buf, tt)) {
706 post("Problem opening bundle: %s\n", OSC_errorMessage);
707 OSC_resetBuffer(buf);
708 bundleDepth = 0;
709 continue;
710 }
711 bundleDepth++;
712 } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') {
713 if (bundleDepth == 0) {
714 post("Unexpected ']': not currently in a bundle.\n");
715 } else {
716 if (OSC_closeBundle(buf)) {
717 post("Problem closing bundle: %s\n", OSC_errorMessage);
718 OSC_resetBuffer(buf);
719 bundleDepth = 0;
720 continue;
721 }
722
723 bundleDepth--;
724 if (bundleDepth == 0) {
725 SendBuffer(htmsocket, buf);
726 }
727 }
728 } else {
729 ParseInteractiveLine(buf, mesg);
730 if (bundleDepth != 0) {
731 /* Don't send anything until we close all bundles */
732 } else {
733 SendBuffer(htmsocket, buf);
734 }
735 }
736 }
737}
738
739OSCTimeTag ParseTimeTag(char *s) {
740 char *p, *newline;
741 typedArg arg;
742
743 p = s;
744 while (isspace(*p)) p++;
745 if (*p == '\0') return OSCTT_Immediately();
746
747 if (*p == '+') {
748 /* Time tag is for some time in the future. It should be a
749 number of seconds as an int or float */
750
751 newline = strchr(s, '\n');
752 if (newline != NULL) *newline = '\0';
753
754 p++; /* Skip '+' */
755 while (isspace(*p)) p++;
756
757 arg = ParseToken(p);
758 if (arg.type == STRING_osc) {
759 post("warning: inscrutable time tag request: %s\n", s);
760 return OSCTT_Immediately();
761 } else if (arg.type == INT_osc) {
762 return OSCTT_PlusSeconds(OSCTT_CurrentTime(),
763 (float) arg.datum.i);
764 } else if (arg.type == FLOAT_osc) {
765 return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f);
766 } else {
767 error("This can't happen!");
768 }
769 }
770
771 if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) {
772 /* They specified the 8-byte tag in hex */
773 OSCTimeTag tt;
774 if (sscanf(p, "%llx", &tt) != 1) {
775 post("warning: couldn't parse time tag %s\n", s);
776 return OSCTT_Immediately();
777 }
778#ifndef HAS8BYTEINT
779 if (ntohl(1) != 1) {
780 /* tt is a struct of seconds and fractional part,
781 and this machine is little-endian, so sscanf
782 wrote each half of the time tag in the wrong half
783 of the struct. */
784 int temp;
785 temp = tt.seconds;
786 tt.seconds = tt.fraction ;
787 tt.fraction = temp;
788 }
789#endif
790 return tt;
791 }
792
793 post("warning: invalid time tag: %s\n", s);
794 return OSCTT_Immediately();
795}
796
797
798void ParseInteractiveLine(OSCbuf *buf, char *mesg) {
799 char *messageName, *token, *p;
800 typedArg args[MAX_ARGS];
801 int thisArg;
802
803 p = mesg;
804 while (isspace(*p)) p++;
805 if (*p == '\0') return;
806
807 messageName = p;
808
809 if (strcmp(messageName, "play\n") == 0) {
810 /* Special kludge feature to save typing */
811 typedArg arg;
812
813 if (OSC_openBundle(buf, OSCTT_Immediately())) {
814 post("Problem opening bundle: %s\n", OSC_errorMessage);
815 return;
816 }
817
818 arg.type = INT_osc;
819 arg.datum.i = 0;
820 WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg);
821
822 arg.type = FLOAT_osc;
823 arg.datum.i = 0.0f;
824 WriteMessage(buf, "/voices/0/tm/goto", 1, &arg);
825
826 if (OSC_closeBundle(buf)) {
827 post("Problem closing bundle: %s\n", OSC_errorMessage);
828 }
829
830 return;
831 }
832
833 while (!isspace(*p) && *p != '\0') p++;
834 if (isspace(*p)) {
835 *p = '\0';
836 p++;
837 }
838
839 thisArg = 0;
840 while (*p != '\0') {
841 /* flush leading whitespace */
842 while (isspace(*p)) p++;
843 if (*p == '\0') break;
844
845 if (*p == '"') {
846 /* A string argument: scan for close quotes */
847 p++;
848 args[thisArg].type = STRING_osc;
849 args[thisArg].datum.s = p;
850
851 while (*p != '"') {
852 if (*p == '\0') {
853 post("Unterminated quote mark: ignoring line\n");
854 return;
855 }
856 p++;
857 }
858 *p = '\0';
859 p++;
860 } else {
861 token = p;
862 while (!isspace(*p) && (*p != '\0')) p++;
863 if (isspace(*p)) {
864 *p = '\0';
865 p++;
866 }
867 args[thisArg] = ParseToken(token);
868 }
869 thisArg++;
870 if (thisArg >= MAX_ARGS) {
871 post("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n",
872 MAX_ARGS);
873 break;
874 }
875 }
876
877 if (WriteMessage(buf, messageName, thisArg, args) != 0) {
878 post("Problem sending message: %s\n", OSC_errorMessage);
879 }
880}
881
882typedArg ParseToken(char *token) {
883 char *p = token;
884 typedArg returnVal;
885
886 /* It might be an int, a float, or a string */
887
888 if (*p == '-') p++;
889
890 if (isdigit(*p) || *p == '.') {
891 while (isdigit(*p)) p++;
892 if (*p == '\0') {
893 returnVal.type = INT_osc;
894 returnVal.datum.i = atoi(token);
895 return returnVal;
896 }
897 if (*p == '.') {
898 p++;
899 while (isdigit(*p)) p++;
900 if (*p == '\0') {
901 returnVal.type = FLOAT_osc;
902 returnVal.datum.f = atof(token);
903 return returnVal;
904 }
905 }
906 }
907
908 returnVal.type = STRING_osc;
909 returnVal.datum.s = token;
910 return returnVal;
911}
912
913int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) {
914 int j, returnVal;
915 const int wmERROR = -1;
916
917 returnVal = 0;
918
919#ifdef DEBUG
920 printf("WriteMessage: %s ", messageName);
921
922 for (j = 0; j < numArgs; j++) {
923 switch (args[j].type) {
924 case INT_osc:
925 printf("%d ", args[j].datum.i);
926 break;
927
928 case FLOAT_osc:
929 printf("%f ", args[j].datum.f);
930 break;
931
932 case STRING_osc:
933 printf("%s ", args[j].datum.s);
934 break;
935
936 default:
937 error("Unrecognized arg type, (not exiting)");
938 return(wmERROR);
939 }
940 }
941 printf("\n");
942#endif
943
944 if (!useTypeTags) {
945 returnVal = OSC_writeAddress(buf, messageName);
946 if (returnVal) {
947 post("Problem writing address: %s\n", OSC_errorMessage);
948 }
949 } else {
950 /* First figure out the type tags */
951 char typeTags[MAX_ARGS+2];
952 int i;
953
954 typeTags[0] = ',';
955
956 for (i = 0; i < numArgs; ++i) {
957 switch (args[i].type) {
958 case INT_osc:
959 typeTags[i+1] = 'i';
960 break;
961
962 case FLOAT_osc:
963 typeTags[i+1] = 'f';
964 break;
965
966 case STRING_osc:
967 typeTags[i+1] = 's';
968 break;
969
970 default:
971 error("Unrecognized arg type (not exiting)");
972 return(wmERROR);
973 }
974 }
975 typeTags[i+1] = '\0';
976
977 returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags);
978 if (returnVal) {
979 post("Problem writing address: %s\n", OSC_errorMessage);
980 }
981 }
982
983 for (j = 0; j < numArgs; j++) {
984 switch (args[j].type) {
985 case INT_osc:
986 if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) {
987 return returnVal;
988 }
989 break;
990
991 case FLOAT_osc:
992 if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) {
993 return returnVal;
994 }
995 break;
996
997 case STRING_osc:
998 if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) {
999 return returnVal;
1000 }
1001 break;
1002
1003 default:
1004 error("Unrecognized arg type (not exiting)");
1005 returnVal = wmERROR;
1006 }
1007 }
1008 return returnVal;
1009}
1010
1011void SendBuffer(void *htmsocket, OSCbuf *buf) {
1012#ifdef DEBUG
1013 printf("Sending buffer...\n");
1014#endif
1015 if (OSC_isBufferEmpty(buf)) {
1016 post("SendBuffer() called but buffer empty");
1017 return;
1018 }
1019 if (!OSC_isBufferDone(buf)) {
1020 error("SendBuffer() called but buffer not ready!, not exiting");
1021 return; //{{raf}}
1022 }
1023 SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf));
1024}
1025
1026void SendData(void *htmsocket, int size, char *data) {
1027 if (!SendHTMSocket(htmsocket, size, data)) {
1028 post("SendData::SendHTMSocket()failure -- not connected");
1029 CloseHTMSocket(htmsocket);
1030 }
1031}
1032
1033
1034
1035/* ----------------------
1036 OSC-client code
1037
1038 */
1039
1040/* Here are the possible values of the state field: */
1041
1042#define EMPTY 0 /* Nothing written to packet yet */
1043#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
1044#define NEED_COUNT 2 /* Just opened a bundle; must write message name or
1045 open another bundle */
1046#define GET_ARGS 3 /* Getting arguments to a message. If we see a message
1047 name or a bundle open/close then the current message
1048 will end. */
1049#define DONE 4 /* All open bundles have been closed, so can't write
1050 anything else */
1051
1052#ifdef WIN32
1053 #include <winsock2.h>
1054 #include <io.h>
1055 #include <stdio.h>
1056 #include <errno.h>
1057 #include <fcntl.h>
1058 #include <sys/types.h>
1059 #include <sys/stat.h>
1060#endif
1061
1062#ifdef __APPLE__
1063 #include <sys/types.h>
1064#endif
1065
1066#ifdef unix
1067 #include <netinet/in.h>
1068 #include <stdio.h>
1069#endif
1070
1071
1072char *OSC_errorMessage;
1073
1074static int OSC_padString(char *dest, char *str);
1075static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
1076static int OSC_WritePadding(char *dest, int i);
1077static int CheckTypeTag(OSCbuf *buf, char expectedType);
1078
1079void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
1080 buf->buffer = byteArray;
1081 buf->size = size;
1082 OSC_resetBuffer(buf);
1083}
1084
1085void OSC_resetBuffer(OSCbuf *buf) {
1086 buf->bufptr = buf->buffer;
1087 buf->state = EMPTY;
1088 buf->bundleDepth = 0;
1089 buf->prevCounts[0] = 0;
1090 buf->gettingFirstUntypedArg = 0;
1091 buf->typeStringPtr = 0;
1092}
1093
1094int OSC_isBufferEmpty(OSCbuf *buf) {
1095 return buf->bufptr == buf->buffer;
1096}
1097
1098int OSC_freeSpaceInBuffer(OSCbuf *buf) {
1099 return buf->size - (buf->bufptr - buf->buffer);
1100}
1101
1102int OSC_isBufferDone(OSCbuf *buf) {
1103 return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
1104}
1105
1106char *OSC_getPacket(OSCbuf *buf) {
1107#ifdef ERROR_CHECK_GETPACKET
1108 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
1109 return buf->buffer;
1110 } else {
1111 OSC_errorMessage = "Packet has unterminated bundles";
1112 return 0;
1113 }
1114#else
1115 return buf->buffer;
1116#endif
1117}
1118
1119int OSC_packetSize(OSCbuf *buf) {
1120#ifdef ERROR_CHECK_PACKETSIZE
1121 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
1122 return (buf->bufptr - buf->buffer);
1123 } else {
1124 OSC_errorMessage = "Packet has unterminated bundles";
1125 return 0;
1126 }
1127#else
1128 return (buf->bufptr - buf->buffer);
1129#endif
1130}
1131
1132#define CheckOverflow(buf, bytesNeeded) { if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) {OSC_errorMessage = "buffer overflow"; return 1;}}
1133
1134static void PatchMessageSize(OSCbuf *buf) {
1135 int4byte size;
1136 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
1137 *(buf->thisMsgSize) = htonl(size);
1138}
1139
1140int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
1141 if (buf->state == ONE_MSG_ARGS) {
1142 OSC_errorMessage = "Can't open a bundle in a one-message packet";
1143 return 3;
1144 }
1145
1146 if (buf->state == DONE) {
1147 OSC_errorMessage = "This packet is finished; can't open a new bundle";
1148 return 4;
1149 }
1150
1151 if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
1152 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
1153 return 2;
1154 }
1155
1156 if (CheckTypeTag(buf, '\0')) return 9;
1157
1158 if (buf->state == GET_ARGS) {
1159 PatchMessageSize(buf);
1160 }
1161
1162 if (buf->state == EMPTY) {
1163 /* Need 16 bytes for "#bundle" and time tag */
1164 CheckOverflow(buf, 16);
1165 } else {
1166 /* This bundle is inside another bundle, so we need to leave
1167 a blank size count for the size of this current bundle. */
1168 CheckOverflow(buf, 20);
1169 *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
1170 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
1171
1172 buf->bufptr += 4;
1173 }
1174
1175 buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
1176
1177
1178 *((OSCTimeTag *) buf->bufptr) = tt;
1179
1180 if (htonl(1) != 1) {
1181 /* Byte swap the 8-byte integer time tag */
1182 int4byte *intp = (int4byte *)buf->bufptr;
1183 intp[0] = htonl(intp[0]);
1184 intp[1] = htonl(intp[1]);
1185
1186#ifdef HAS8BYTEINT
1187 { /* tt is a 64-bit int so we have to swap the two 32-bit words.
1188 (Otherwise tt is a struct of two 32-bit words, and even though
1189 each word was wrong-endian, they were in the right order
1190 in the struct.) */
1191 int4byte temp = intp[0];
1192 intp[0] = intp[1];
1193 intp[1] = temp;
1194 }
1195#endif
1196 }
1197
1198 buf->bufptr += sizeof(OSCTimeTag);
1199
1200 buf->state = NEED_COUNT;
1201
1202 buf->gettingFirstUntypedArg = 0;
1203 buf->typeStringPtr = 0;
1204 return 0;
1205}
1206
1207
1208int OSC_closeBundle(OSCbuf *buf) {
1209 if (buf->bundleDepth == 0) {
1210 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
1211 OSC_errorMessage = "Can't close bundle; no bundle is open!";
1212 return 5;
1213 }
1214
1215 if (CheckTypeTag(buf, '\0')) return 9;
1216
1217 if (buf->state == GET_ARGS) {
1218 PatchMessageSize(buf);
1219 }
1220
1221 if (buf->bundleDepth == 1) {
1222 /* Closing the last bundle: No bundle size to patch */
1223 buf->state = DONE;
1224 } else {
1225 /* Closing a sub-bundle: patch bundle size */
1226 int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
1227 *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
1228 buf->state = NEED_COUNT;
1229 }
1230
1231 --buf->bundleDepth;
1232 buf->gettingFirstUntypedArg = 0;
1233 buf->typeStringPtr = 0;
1234 return 0;
1235}
1236
1237
1238int OSC_closeAllBundles(OSCbuf *buf) {
1239 if (buf->bundleDepth == 0) {
1240 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
1241 OSC_errorMessage = "Can't close all bundles; no bundle is open!";
1242 return 6;
1243 }
1244
1245 if (CheckTypeTag(buf, '\0')) return 9;
1246
1247 while (buf->bundleDepth > 0) {
1248 OSC_closeBundle(buf);
1249 }
1250 buf->typeStringPtr = 0;
1251 return 0;
1252}
1253
1254int OSC_writeAddress(OSCbuf *buf, char *name) {
1255 int4byte paddedLength;
1256
1257 if (buf->state == ONE_MSG_ARGS) {
1258 OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
1259 return 7;
1260 }
1261
1262 if (buf->state == DONE) {
1263 OSC_errorMessage = "This packet is finished; can't write another address";
1264 return 8;
1265 }
1266
1267 if (CheckTypeTag(buf, '\0')) return 9;
1268
1269 paddedLength = OSC_effectiveStringLength(name);
1270
1271 if (buf->state == EMPTY) {
1272 /* This will be a one-message packet, so no sizes to worry about */
1273 CheckOverflow(buf, paddedLength);
1274 buf->state = ONE_MSG_ARGS;
1275 } else {
1276 /* GET_ARGS or NEED_COUNT */
1277 CheckOverflow(buf, 4+paddedLength);
1278 if (buf->state == GET_ARGS) {
1279 /* Close the old message */
1280 PatchMessageSize(buf);
1281 }
1282 buf->thisMsgSize = (int4byte *)buf->bufptr;
1283 *(buf->thisMsgSize) = 0xbbbbbbbb;
1284 buf->bufptr += 4;
1285 buf->state = GET_ARGS;
1286 }
1287
1288 /* Now write the name */
1289 buf->bufptr += OSC_padString(buf->bufptr, name);
1290 buf->typeStringPtr = 0;
1291 buf->gettingFirstUntypedArg = 1;
1292
1293 return 0;
1294}
1295
1296int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) {
1297 int result;
1298 int4byte paddedLength;
1299
1300 if (CheckTypeTag(buf, '\0')) return 9;
1301
1302 result = OSC_writeAddress(buf, name);
1303
1304 if (result) return result;
1305
1306 paddedLength = OSC_effectiveStringLength(types);
1307
1308 CheckOverflow(buf, paddedLength);
1309
1310 buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
1311 buf->bufptr += OSC_padString(buf->bufptr, types);
1312
1313 buf->gettingFirstUntypedArg = 0;
1314 return 0;
1315}
1316
1317static int CheckTypeTag(OSCbuf *buf, char expectedType) {
1318 if (buf->typeStringPtr) {
1319 if (*(buf->typeStringPtr) != expectedType) {
1320 if (expectedType == '\0') {
1321 OSC_errorMessage =
1322 "According to the type tag I expected more arguments.";
1323 } else if (*(buf->typeStringPtr) == '\0') {
1324 OSC_errorMessage =
1325 "According to the type tag I didn't expect any more arguments.";
1326 } else {
1327 OSC_errorMessage =
1328 "According to the type tag I expected an argument of a different type.";
1329 printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
1330 }
1331 return 9;
1332 }
1333 ++(buf->typeStringPtr);
1334 }
1335 return 0;
1336}
1337
1338
1339int OSC_writeFloatArg(OSCbuf *buf, float arg) {
1340 int4byte *intp;
1341 //int result;
1342
1343 CheckOverflow(buf, 4);
1344
1345 if (CheckTypeTag(buf, 'f')) return 9;
1346
1347 /* Pretend arg is a long int so we can use htonl() */
1348 intp = ((int4byte *) &arg);
1349 *((int4byte *) buf->bufptr) = htonl(*intp);
1350
1351 buf->bufptr += 4;
1352
1353 buf->gettingFirstUntypedArg = 0;
1354 return 0;
1355}
1356
1357
1358
1359int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
1360 int i;
1361 int4byte *intp;
1362
1363 CheckOverflow(buf, 4 * numFloats);
1364
1365 /* Pretend args are long ints so we can use htonl() */
1366 intp = ((int4byte *) args);
1367
1368 for (i = 0; i < numFloats; i++) {
1369 if (CheckTypeTag(buf, 'f')) return 9;
1370 *((int4byte *) buf->bufptr) = htonl(intp[i]);
1371 buf->bufptr += 4;
1372 }
1373
1374 buf->gettingFirstUntypedArg = 0;
1375 return 0;
1376}
1377
1378int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
1379 CheckOverflow(buf, 4);
1380 if (CheckTypeTag(buf, 'i')) return 9;
1381
1382 *((int4byte *) buf->bufptr) = htonl(arg);
1383 buf->bufptr += 4;
1384
1385 buf->gettingFirstUntypedArg = 0;
1386 return 0;
1387}
1388
1389int OSC_writeStringArg(OSCbuf *buf, char *arg) {
1390 int len;
1391
1392 if (CheckTypeTag(buf, 's')) return 9;
1393
1394 len = OSC_effectiveStringLength(arg);
1395
1396 if (buf->gettingFirstUntypedArg && arg[0] == ',') {
1397 /* This un-type-tagged message starts with a string
1398 that starts with a comma, so we have to escape it
1399 (with a double comma) so it won't look like a type
1400 tag string. */
1401
1402 CheckOverflow(buf, len+4); /* Too conservative */
1403 buf->bufptr +=
1404 OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
1405
1406 } else {
1407 CheckOverflow(buf, len);
1408 buf->bufptr += OSC_padString(buf->bufptr, arg);
1409 }
1410
1411 buf->gettingFirstUntypedArg = 0;
1412 return 0;
1413
1414}
1415
1416/* String utilities */
1417
1418#define STRING_ALIGN_PAD 4
1419int OSC_effectiveStringLength(char *string) {
1420 int len = strlen(string) + 1; /* We need space for the null char. */
1421
1422 /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
1423 if ((len % STRING_ALIGN_PAD) != 0) {
1424 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
1425 }
1426 return len;
1427}
1428
1429static int OSC_padString(char *dest, char *str) {
1430 int i;
1431
1432 for (i = 0; str[i] != '\0'; i++) {
1433 dest[i] = str[i];
1434 }
1435
1436 return OSC_WritePadding(dest, i);
1437}
1438
1439static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) {
1440 int i;
1441
1442 dest[0] = ',';
1443 for (i = 0; str[i] != '\0'; i++) {
1444 dest[i+1] = str[i];
1445 }
1446
1447 return OSC_WritePadding(dest, i+1);
1448}
1449
1450static int OSC_WritePadding(char *dest, int i) {
1451 dest[i] = '\0';
1452 i++;
1453
1454 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
1455 dest[i] = '\0';
1456 }
1457
1458 return i;
1459}
1460
1461
1462/*
1463Written by Matt Wright, The Center for New Music and Audio Technologies,
1464University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03
1465The Regents of the University of California (Regents).
1466
1467Permission to use, copy, modify, distribute, and distribute modified versions
1468of this software and its documentation without fee and without a signed
1469licensing agreement, is hereby granted, provided that the above copyright
1470notice, this paragraph and the following two paragraphs appear in all copies,
1471modifications, and distributions.
1472
1473IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
1474SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
1475OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
1476BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1477
1478REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1479THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1480PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
1481HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
1482MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1483
1484
1485The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
1486*/
1487
1488
1489/* sendOSC.c
1490
1491 Matt Wright, 6/3/97
1492 based on sendOSC.c, which was based on a version by Adrian Freed
1493
1494 Text-based OpenSoundControl client. User can enter messages via command
1495 line arguments or standard input.
1496
1497 Version 0.1: "play" feature
1498 Version 0.2: Message type tags.
1499
1500 pd version branched from http://www.cnmat.berkeley.edu/OpenSoundControl/src/sendOSC/sendOSC.c
1501 -------------
1502 -- added bundle stuff to send. jdl 20020416
1503 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
1504 -- ost_at_test.at + i22_at_test.at, 2000-2002
1505 modified to compile as pd externel
1506*/
1507
1508#define MAX_ARGS 2000
1509#define SC_BUFFER_SIZE 64000
1510
1511#include "m_pd.h"
1512#include "OSC-client.h"
1513
1514#include <string.h>
1515#include <sys/types.h>
1516#include <stdlib.h>
1517#include <stdio.h>
1518#include <sys/stat.h>
1519#include <sys/types.h>
1520
1521#ifdef WIN32
1522#include <winsock2.h>
1523#include <io.h>
1524#include <errno.h>
1525#include <fcntl.h>
1526#include <winsock2.h>
1527#include <ctype.h>
1528#include <signal.h>
1529#else
1530#include <sys/socket.h>
1531#include <netinet/in.h>
1532#include <rpc/rpc.h>
1533#include <sys/times.h>
1534#include <sys/param.h>
1535#include <sys/time.h>
1536#include <sys/ioctl.h>
1537#include <netdb.h>
1538#endif
1539
1540#ifdef __APPLE__
1541 #include <string.h>
1542#endif
1543
1544#define UNIXDG_PATH "/tmp/htm"
1545#define UNIXDG_TMP "/tmp/htm.XXXXXX"
1546
1547
1548
1549OSCTimeTag OSCTT_Immediately(void) {
1550 OSCTimeTag result;
1551 result.seconds = 0;
1552 result.fraction = 1;
1553 return result;
1554}
1555
1556
1557OSCTimeTag OSCTT_CurrentTime(void) {
1558 OSCTimeTag result;
1559 result.seconds = 0;
1560 result.fraction = 1;
1561 return result;
1562}
1563
1564OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
1565 OSCTimeTag result;
1566 result.seconds = 0;
1567 result.fraction = 1;
1568 return result;
1569}
1570
1571
1572typedef int bool;
1573
1574typedef struct
1575{
1576 float srate;
1577
1578 struct sockaddr_in serv_addr; /* udp socket */
1579 #ifndef WIN32
1580 struct sockaddr_un userv_addr; /* UNIX socket */
1581 #endif
1582 int sockfd; /* socket file descriptor */
1583 int index, len,uservlen;
1584 void *addr;
1585 int id;
1586} desc;
1587
1588
1589/* open a socket for HTM communication to given host on given portnumber */
1590/* if host is 0 then UNIX protocol is used (i.e. local communication */
1591void *OpenHTMSocket(char *host, int portnumber)
1592{
1593 struct sockaddr_in cl_addr;
1594 #ifndef WIN32
1595 int sockfd;
1596 struct sockaddr_un ucl_addr;
1597 #else
1598 unsigned int sockfd;
1599 #endif
1600
1601 desc *o;
1602 int oval = 1;
1603 o = malloc(sizeof(*o));
1604 if(!o) return 0;
1605
1606 #ifndef WIN32
1607
1608 if(!host)
1609 {
1610 char *mktemp(char *);
1611 int clilen;
1612 o->len = sizeof(ucl_addr);
1613 /*
1614 * Fill in the structure "userv_addr" with the address of the
1615 * server that we want to send to.
1616 */
1617
1618 bzero((char *) &o->userv_addr, sizeof(o->userv_addr));
1619 o->userv_addr.sun_family = AF_UNIX;
1620 strcpy(o->userv_addr.sun_path, UNIXDG_PATH);
1621 sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber);
1622 o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path);
1623 o->addr = &(o->userv_addr);
1624 /*
1625 * Open a socket (a UNIX domain datagram socket).
1626 */
1627
1628 if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0)
1629 {
1630 /*
1631 * Bind a local address for us.
1632 * In the UNIX domain we have to choose our own name (that
1633 * should be unique). We'll use mktemp() to create a unique
1634 * pathname, based on our process id.
1635 */
1636
1637 bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */
1638 ucl_addr.sun_family = AF_UNIX;
1639 strcpy(ucl_addr.sun_path, UNIXDG_TMP);
1640
1641 mktemp(ucl_addr.sun_path);
1642 clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path);
1643
1644 if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0)
1645 {
1646 perror("client: can't bind local address");
1647 close(sockfd);
1648 sockfd = -1;
1649 }
1650 }
1651 else
1652 perror("unable to make socket\n");
1653
1654 }else
1655
1656 #endif
1657
1658 {
1659 /*
1660 * Fill in the structure "serv_addr" with the address of the
1661 * server that we want to send to.
1662 */
1663 o->len = sizeof(cl_addr);
1664
1665 #ifdef WIN32
1666 ZeroMemory((char *)&o->serv_addr, sizeof(o->serv_addr));
1667 #else
1668 bzero((char *)&o->serv_addr, sizeof(o->serv_addr));
1669 #endif
1670
1671 o->serv_addr.sin_family = AF_INET;
1672
1673 /* MW 6/6/96: Call gethostbyname() instead of inet_addr(),
1674 so that host can be either an Internet host name (e.g.,
1675 "les") or an Internet address in standard dot notation
1676 (e.g., "128.32.122.13") */
1677 {
1678 struct hostent *hostsEntry;
1679 unsigned long address;
1680
1681 hostsEntry = gethostbyname(host);
1682 if (hostsEntry == NULL) {
1683 fprintf(stderr, "Couldn't decipher host name \"%s\"\n", host);
1684 #ifndef WIN32
1685 herror(NULL);
1686 #endif
1687 return 0;
1688 }
1689 address = *((unsigned long *) hostsEntry->h_addr_list[0]);
1690 o->serv_addr.sin_addr.s_addr = address;
1691 }
1692
1693 /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */
1694
1695 /* End MW changes */
1696
1697 /*
1698 * Open a socket (a UDP domain datagram socket).
1699 */
1700
1701
1702 #ifdef WIN32
1703 o->serv_addr.sin_port = htons((USHORT)portnumber);
1704 o->addr = &(o->serv_addr);
1705 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) {
1706 ZeroMemory((char *)&cl_addr, sizeof(cl_addr));
1707 cl_addr.sin_family = AF_INET;
1708 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1709 cl_addr.sin_port = htons(0);
1710
1711 // enable broadcast: jdl ~2003
1712 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
1713 perror("setsockopt");
1714 }
1715
1716 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
1717 perror("could not bind\n");
1718 closesocket(sockfd);
1719 sockfd = -1;
1720 }
1721 }
1722 else { perror("unable to make socket\n");}
1723 #else
1724 o->serv_addr.sin_port = htons(portnumber);
1725 o->addr = &(o->serv_addr);
1726 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
1727 bzero((char *)&cl_addr, sizeof(cl_addr));
1728 cl_addr.sin_family = AF_INET;
1729 cl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1730 cl_addr.sin_port = htons(0);
1731
1732 // enable broadcast: jdl ~2003
1733 if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) {
1734 perror("setsockopt");
1735 }
1736
1737 if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) {
1738 perror("could not bind\n");
1739 close(sockfd);
1740 sockfd = -1;
1741 }
1742 }
1743 else { perror("unable to make socket\n");}
1744 #endif
1745 }
1746 #ifdef WIN32
1747 if(sockfd == INVALID_SOCKET) {
1748 #else
1749 if(sockfd < 0) {
1750 #endif
1751 free(o);
1752 o = 0;
1753 }
1754 else
1755 o->sockfd = sockfd;
1756 return o;
1757}
1758
1759static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b)
1760{
1761 int rcount;
1762 if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count)
1763 {
1764 printf("sockfd %d count %d rcount %dlength %d\n", sockfd,count,rcount,length);
1765 return FALSE;
1766 }
1767 return TRUE;
1768}
1769
1770bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer)
1771{
1772 desc *o = (desc *)htmsendhandle;
1773 return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer);
1774}
1775void CloseHTMSocket(void *htmsendhandle)
1776{
1777 desc *o = (desc *)htmsendhandle;
1778 #ifdef WIN32
1779 if(SOCKET_ERROR == closesocket(o->sockfd)) {
1780 perror("CloseHTMSocket::closesocket failed\n");
1781 return;
1782 }
1783 #else
1784 if(close(o->sockfd) == -1)
1785 {
1786 perror("CloseHTMSocket::closesocket failed");
1787 return;
1788 }
1789 #endif
1790
1791 free(o);
1792}
1793
1794
1795///////////////////////
1796// from sendOSC
1797
1798typedef struct {
1799 //enum {INT, FLOAT, STRING} type;
1800 enum {INT_osc, FLOAT_osc, STRING_osc} type;
1801 union {
1802 int i;
1803 float f;
1804 char *s;
1805 } datum;
1806} typedArg;
1807
1808void CommandLineMode(int argc, char *argv[], void *htmsocket);
1809OSCTimeTag ParseTimeTag(char *s);
1810void ParseInteractiveLine(OSCbuf *buf, char *mesg);
1811typedArg ParseToken(char *token);
1812int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args);
1813void SendBuffer(void *htmsocket, OSCbuf *buf);
1814void SendData(void *htmsocket, int size, char *data);
1815/* defined in OSC-system-dependent.c now */
1816
1817//static void *htmsocket;
1818static int exitStatus = 0;
1819static int useTypeTags = 0;
1820
1821static char bufferForOSCbuf[SC_BUFFER_SIZE];
1822
1823
1824/////////
1825// end from sendOSC
1826
1827static t_class *sendOSC_class;
1828
1829typedef struct _sendOSC
1830{
1831 t_object x_obj;
1832 int x_protocol; // UDP/TCP (udp only atm)
1833 t_int x_typetags; // typetag flag
1834 void *x_htmsocket; // sending socket
1835 int x_bundle; // bundle open flag
1836 OSCbuf x_oscbuf[1]; // OSCbuffer
1837 t_outlet *x_bdpthout;// bundle-depth floatoutlet
1838} t_sendOSC;
1839
1840static void *sendOSC_new(t_floatarg udpflag)
1841{
1842 t_sendOSC *x = (t_sendOSC *)pd_new(sendOSC_class);
1843 outlet_new(&x->x_obj, &s_float);
1844 x->x_htmsocket = 0; // {{raf}}
1845 // set udp
1846 x->x_protocol = SOCK_STREAM;
1847 // set typetags to 1 by default
1848 x->x_typetags = 1;
1849 // bunlde is closed
1850 x->x_bundle = 0;
1851 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
1852 x->x_bdpthout = outlet_new(&x->x_obj, 0); // outlet_float();
1853 //x->x_oscbuf =
1854 return (x);
1855}
1856
1857
1858void sendOSC_openbundle(t_sendOSC *x)
1859{
1860 if (x->x_oscbuf->bundleDepth + 1 >= MAX_BUNDLE_NESTING ||
1861 OSC_openBundle(x->x_oscbuf, OSCTT_Immediately()))
1862 {
1863 post("Problem opening bundle: %s\n", OSC_errorMessage);
1864 return;
1865 }
1866 x->x_bundle = 1;
1867 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
1868}
1869
1870static void sendOSC_closebundle(t_sendOSC *x)
1871{
1872 if (OSC_closeBundle(x->x_oscbuf)) {
1873 post("Problem closing bundle: %s\n", OSC_errorMessage);
1874 return;
1875 }
1876 outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth);
1877 // in bundle mode we send when bundle is closed?
1878 if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) {
1879 // post("x_oscbuf: something inside me?");
1880 if (x->x_htmsocket) {
1881 SendBuffer(x->x_htmsocket, x->x_oscbuf);
1882 } else {
1883 post("sendOSC: not connected");
1884 }
1885 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
1886 x->x_bundle = 0;
1887 return;
1888 }
1889 // post("x_oscbuf: something went wrong");
1890}
1891
1892static void sendOSC_settypetags(t_sendOSC *x, t_float *f)
1893 {
1894 x->x_typetags = (int)f;
1895 post("sendOSC.c: setting typetags %d",x->x_typetags);
1896 }
1897
1898
1899static void sendOSC_connect(t_sendOSC *x, t_symbol *hostname,
1900 t_floatarg fportno)
1901{
1902 int portno = fportno;
1903 /* create a socket */
1904
1905 // make sure handle is available
1906 if(x->x_htmsocket == 0) {
1907 //
1908 x->x_htmsocket = OpenHTMSocket(hostname->s_name, portno);
1909 if (!x->x_htmsocket)
1910 post("Couldn't open socket: ");
1911 else {
1912 post("connected to port %s:%d (hSock=%d)", hostname->s_name, portno, x->x_htmsocket);
1913 outlet_float(x->x_obj.ob_outlet, 1);
1914 }
1915 }
1916 else
1917 perror("call to sendOSC_connect() against UNavailable socket handle");
1918}
1919
1920void sendOSC_disconnect(t_sendOSC *x)
1921{
1922 if (x->x_htmsocket)
1923 {
1924 post("disconnecting htmsock (hSock=%d)...", x->x_htmsocket);
1925 CloseHTMSocket(x->x_htmsocket);
1926 x->x_htmsocket = 0; // {{raf}} semi-quasi-semaphorize this
1927 outlet_float(x->x_obj.ob_outlet, 0);
1928 }
1929 else {
1930 perror("call to sendOSC_disconnect() against unused socket handle");
1931 }
1932}
1933
1934void sendOSC_senduntyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
1935{
1936 char* targv[MAXPDARG];
1937 char tmparg[MAXPDSTRING];
1938 char* tmp = tmparg;
1939 //char testarg[MAXPDSTRING];
1940 int c;
1941
1942 post("sendOSC: use typetags 0/1 message and plain send method so send untypetagged...");
1943 return;
1944
1945 //atom_string(argv,testarg, MAXPDSTRING);
1946 for (c=0;c<argc;c++) {
1947 atom_string(argv+c,tmp, 80);
1948 targv[c] = tmp;
1949 tmp += strlen(tmp)+1;
1950 }
1951
1952 // this sock needs to be larger than 0, not >= ..
1953 if (x->x_htmsocket)
1954 {
1955 CommandLineMode(argc, targv, x->x_htmsocket);
1956 // post("test %d", c);
1957 }
1958 else {
1959 post("sendOSC: not connected");
1960 }
1961}
1962
1963//////////////////////////////////////////////////////////////////////
1964// this is the real and only sending routine now, for both typed and
1965// undtyped mode.
1966
1967static void sendOSC_sendtyped(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
1968{
1969 char* targv[MAX_ARGS];
1970 char tmparg[MAXPDSTRING];
1971 char* tmp = tmparg;
1972 int c;
1973
1974 char *messageName;
1975 char *token;
1976 typedArg args[MAX_ARGS];
1977 int i,j;
1978 int numArgs = 0;
1979
1980 messageName = "";
1981#ifdef DEBUG
1982 post ("sendOSC: messageName: %s", messageName);
1983#endif
1984
1985
1986
1987 for (c=0;c<argc;c++) {
1988 atom_string(argv+c,tmp, 80);
1989
1990#ifdef DEBUG
1991 // post ("sendOSC: %d, %s",c, tmp);
1992#endif
1993
1994 targv[c] = tmp;
1995 tmp += strlen(tmp)+1;
1996
1997#ifdef DEBUG
1998 // post ("sendOSC: %d, %s",c, targv[c]);
1999#endif
2000 }
2001
2002 // this sock needs to be larger than 0, not >= ..
2003 if (x->x_htmsocket > 0)
2004 {
2005#ifdef DEBUG
2006 post ("sendOSC: type tags? %d", useTypeTags);
2007#endif
2008
2009 messageName = strtok(targv[0], ",");
2010 j = 1;
2011 for (i = j; i < argc; i++) {
2012 token = strtok(targv[i],",");
2013 args[i-j] = ParseToken(token);
2014#ifdef DEBUG
2015 printf("cell-cont: %s\n", targv[i]);
2016 printf(" type-id: %d\n", args[i-j]);
2017#endif
2018 numArgs = i;
2019 }
2020
2021
2022 if(WriteMessage(x->x_oscbuf, messageName, numArgs, args)) {
2023 post("sendOSC: usage error, write-msg failed: %s", OSC_errorMessage);
2024 return;
2025 }
2026
2027 if(!x->x_bundle) {
2028 SendBuffer(x->x_htmsocket, x->x_oscbuf);
2029 OSC_initBuffer(x->x_oscbuf, SC_BUFFER_SIZE, bufferForOSCbuf);
2030 }
2031
2032 //CommandLineMode(argc, targv, x->x_htmsocket);
2033 //useTypeTags = 0;
2034 }
2035 else {
2036 post("sendOSC: not connected");
2037 }
2038}
2039
2040void sendOSC_send(t_sendOSC *x, t_symbol *s, int argc, t_atom *argv)
2041{
2042 if(!argc) {
2043 post("not sending empty message.");
2044 return;
2045 }
2046 if(x->x_typetags) {
2047 useTypeTags = 1;
2048 sendOSC_sendtyped(x,s,argc,argv);
2049 useTypeTags = 0;
2050 } else {
2051 sendOSC_sendtyped(x,s,argc,argv);
2052 }
2053}
2054
2055static void sendOSC_free(t_sendOSC *x)
2056{
2057 sendOSC_disconnect(x);
2058}
2059
2060#ifdef WIN32
2061 OSC_API void sendOSC_setup(void) {
2062#else
2063 void sendOSC_setup(void) {
2064#endif
2065 sendOSC_class = class_new(gensym("sendOSC"), (t_newmethod)sendOSC_new,
2066 (t_method)sendOSC_free,
2067 sizeof(t_sendOSC), 0, A_DEFFLOAT, 0);
2068 class_addmethod(sendOSC_class, (t_method)sendOSC_connect,
2069 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
2070 class_addmethod(sendOSC_class, (t_method)sendOSC_disconnect,
2071 gensym("disconnect"), 0);
2072 class_addmethod(sendOSC_class, (t_method)sendOSC_settypetags,
2073 gensym("typetags"),
2074 A_FLOAT, 0);
2075 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
2076 gensym("send"),
2077 A_GIMME, 0);
2078 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
2079 gensym("senduntyped"),
2080 A_GIMME, 0);
2081 class_addmethod(sendOSC_class, (t_method)sendOSC_send,
2082 gensym("sendtyped"),
2083 A_GIMME, 0);
2084 class_addmethod(sendOSC_class, (t_method)sendOSC_openbundle,
2085 gensym("["),
2086 0, 0);
2087 class_addmethod(sendOSC_class, (t_method)sendOSC_closebundle,
2088 gensym("]"),
2089 0, 0);
2090 class_sethelpsymbol(sendOSC_class, gensym("sendOSC-help.pd"));
2091}
2092
2093
2094
2095
2096
2097/* Exit status codes:
2098 0: successful
2099 2: Message(s) dropped because of buffer overflow
2100 3: Socket error
2101 4: Usage error
2102 5: Internal error
2103*/
2104
2105void CommandLineMode(int argc, char *argv[], void *htmsocket) {
2106 char *messageName;
2107 char *token;
2108 typedArg args[MAX_ARGS];
2109 int i,j, numArgs;
2110 OSCbuf buf[1];
2111
2112 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
2113
2114 if (argc > 1) {
2115 post("argc (%d) > 1", argc);
2116 }
2117
2118 // ParseInteractiveLine(buf, argv);
2119 messageName = strtok(argv[0], ",");
2120
2121 j = 1;
2122 for (i = j; i < argc; i++) {
2123 token = strtok(argv[i],",");
2124 args[i-j] = ParseToken(token);
2125#ifdef DEBUG
2126 printf("cell-cont: %s\n", argv[i]);
2127 printf(" type-id: %d\n", args[i-j]);
2128#endif
2129 numArgs = i;
2130 }
2131
2132 if(WriteMessage(buf, messageName, numArgs, args)) {
2133 post("sendOSC: usage error. write-msg failed: %s", OSC_errorMessage);
2134 return;
2135 }
2136
2137 SendBuffer(htmsocket, buf);
2138}
2139
2140#define MAXMESG 2048
2141
2142void InteractiveMode(void *htmsocket) {
2143 char mesg[MAXMESG];
2144 OSCbuf buf[1];
2145 int bundleDepth = 0; /* At first, we haven't seen "[". */
2146
2147 OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf);
2148
2149 while (fgets(mesg, MAXMESG, stdin) != NULL) {
2150 if (mesg[0] == '\n') {
2151 if (bundleDepth > 0) {
2152 /* Ignore blank lines inside a group. */
2153 } else {
2154 /* blank line => repeat previous send */
2155 SendBuffer(htmsocket, buf);
2156 }
2157 continue;
2158 }
2159
2160 if (bundleDepth == 0) {
2161 OSC_resetBuffer(buf);
2162 }
2163
2164 if (mesg[0] == '[') {
2165 OSCTimeTag tt = ParseTimeTag(mesg+1);
2166 if (OSC_openBundle(buf, tt)) {
2167 post("Problem opening bundle: %s\n", OSC_errorMessage);
2168 OSC_resetBuffer(buf);
2169 bundleDepth = 0;
2170 continue;
2171 }
2172 bundleDepth++;
2173 } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') {
2174 if (bundleDepth == 0) {
2175 post("Unexpected ']': not currently in a bundle.\n");
2176 } else {
2177 if (OSC_closeBundle(buf)) {
2178 post("Problem closing bundle: %s\n", OSC_errorMessage);
2179 OSC_resetBuffer(buf);
2180 bundleDepth = 0;
2181 continue;
2182 }
2183
2184 bundleDepth--;
2185 if (bundleDepth == 0) {
2186 SendBuffer(htmsocket, buf);
2187 }
2188 }
2189 } else {
2190 ParseInteractiveLine(buf, mesg);
2191 if (bundleDepth != 0) {
2192 /* Don't send anything until we close all bundles */
2193 } else {
2194 SendBuffer(htmsocket, buf);
2195 }
2196 }
2197 }
2198}
2199
2200OSCTimeTag ParseTimeTag(char *s) {
2201 char *p, *newline;
2202 typedArg arg;
2203
2204 p = s;
2205 while (isspace(*p)) p++;
2206 if (*p == '\0') return OSCTT_Immediately();
2207
2208 if (*p == '+') {
2209 /* Time tag is for some time in the future. It should be a
2210 number of seconds as an int or float */
2211
2212 newline = strchr(s, '\n');
2213 if (newline != NULL) *newline = '\0';
2214
2215 p++; /* Skip '+' */
2216 while (isspace(*p)) p++;
2217
2218 arg = ParseToken(p);
2219 if (arg.type == STRING_osc) {
2220 post("warning: inscrutable time tag request: %s\n", s);
2221 return OSCTT_Immediately();
2222 } else if (arg.type == INT_osc) {
2223 return OSCTT_PlusSeconds(OSCTT_CurrentTime(),
2224 (float) arg.datum.i);
2225 } else if (arg.type == FLOAT_osc) {
2226 return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f);
2227 } else {
2228 error("This can't happen!");
2229 }
2230 }
2231
2232 if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) {
2233 /* They specified the 8-byte tag in hex */
2234 OSCTimeTag tt;
2235 if (sscanf(p, "%llx", &tt) != 1) {
2236 post("warning: couldn't parse time tag %s\n", s);
2237 return OSCTT_Immediately();
2238 }
2239#ifndef HAS8BYTEINT
2240 if (ntohl(1) != 1) {
2241 /* tt is a struct of seconds and fractional part,
2242 and this machine is little-endian, so sscanf
2243 wrote each half of the time tag in the wrong half
2244 of the struct. */
2245 int temp;
2246 temp = tt.seconds;
2247 tt.seconds = tt.fraction ;
2248 tt.fraction = temp;
2249 }
2250#endif
2251 return tt;
2252 }
2253
2254 post("warning: invalid time tag: %s\n", s);
2255 return OSCTT_Immediately();
2256}
2257
2258
2259void ParseInteractiveLine(OSCbuf *buf, char *mesg) {
2260 char *messageName, *token, *p;
2261 typedArg args[MAX_ARGS];
2262 int thisArg;
2263
2264 p = mesg;
2265 while (isspace(*p)) p++;
2266 if (*p == '\0') return;
2267
2268 messageName = p;
2269
2270 if (strcmp(messageName, "play\n") == 0) {
2271 /* Special kludge feature to save typing */
2272 typedArg arg;
2273
2274 if (OSC_openBundle(buf, OSCTT_Immediately())) {
2275 post("Problem opening bundle: %s\n", OSC_errorMessage);
2276 return;
2277 }
2278
2279 arg.type = INT_osc;
2280 arg.datum.i = 0;
2281 WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg);
2282
2283 arg.type = FLOAT_osc;
2284 arg.datum.i = 0.0f;
2285 WriteMessage(buf, "/voices/0/tm/goto", 1, &arg);
2286
2287 if (OSC_closeBundle(buf)) {
2288 post("Problem closing bundle: %s\n", OSC_errorMessage);
2289 }
2290
2291 return;
2292 }
2293
2294 while (!isspace(*p) && *p != '\0') p++;
2295 if (isspace(*p)) {
2296 *p = '\0';
2297 p++;
2298 }
2299
2300 thisArg = 0;
2301 while (*p != '\0') {
2302 /* flush leading whitespace */
2303 while (isspace(*p)) p++;
2304 if (*p == '\0') break;
2305
2306 if (*p == '"') {
2307 /* A string argument: scan for close quotes */
2308 p++;
2309 args[thisArg].type = STRING_osc;
2310 args[thisArg].datum.s = p;
2311
2312 while (*p != '"') {
2313 if (*p == '\0') {
2314 post("Unterminated quote mark: ignoring line\n");
2315 return;
2316 }
2317 p++;
2318 }
2319 *p = '\0';
2320 p++;
2321 } else {
2322 token = p;
2323 while (!isspace(*p) && (*p != '\0')) p++;
2324 if (isspace(*p)) {
2325 *p = '\0';
2326 p++;
2327 }
2328 args[thisArg] = ParseToken(token);
2329 }
2330 thisArg++;
2331 if (thisArg >= MAX_ARGS) {
2332 post("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n",
2333 MAX_ARGS);
2334 break;
2335 }
2336 }
2337
2338 if (WriteMessage(buf, messageName, thisArg, args) != 0) {
2339 post("Problem sending message: %s\n", OSC_errorMessage);
2340 }
2341}
2342
2343typedArg ParseToken(char *token) {
2344 char *p = token;
2345 typedArg returnVal;
2346
2347 /* It might be an int, a float, or a string */
2348
2349 if (*p == '-') p++;
2350
2351 if (isdigit(*p) || *p == '.') {
2352 while (isdigit(*p)) p++;
2353 if (*p == '\0') {
2354 returnVal.type = INT_osc;
2355 returnVal.datum.i = atoi(token);
2356 return returnVal;
2357 }
2358 if (*p == '.') {
2359 p++;
2360 while (isdigit(*p)) p++;
2361 if (*p == '\0') {
2362 returnVal.type = FLOAT_osc;
2363 returnVal.datum.f = atof(token);
2364 return returnVal;
2365 }
2366 }
2367 }
2368
2369 returnVal.type = STRING_osc;
2370 returnVal.datum.s = token;
2371 return returnVal;
2372}
2373
2374int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) {
2375 int j, returnVal;
2376 const int wmERROR = -1;
2377
2378 returnVal = 0;
2379
2380#ifdef DEBUG
2381 printf("WriteMessage: %s ", messageName);
2382
2383 for (j = 0; j < numArgs; j++) {
2384 switch (args[j].type) {
2385 case INT_osc:
2386 printf("%d ", args[j].datum.i);
2387 break;
2388
2389 case FLOAT_osc:
2390 printf("%f ", args[j].datum.f);
2391 break;
2392
2393 case STRING_osc:
2394 printf("%s ", args[j].datum.s);
2395 break;
2396
2397 default:
2398 error("Unrecognized arg type, (not exiting)");
2399 return(wmERROR);
2400 }
2401 }
2402 printf("\n");
2403#endif
2404
2405 if (!useTypeTags) {
2406 returnVal = OSC_writeAddress(buf, messageName);
2407 if (returnVal) {
2408 post("Problem writing address: %s\n", OSC_errorMessage);
2409 }
2410 } else {
2411 /* First figure out the type tags */
2412 char typeTags[MAX_ARGS+2];
2413 int i;
2414
2415 typeTags[0] = ',';
2416
2417 for (i = 0; i < numArgs; ++i) {
2418 switch (args[i].type) {
2419 case INT_osc:
2420 typeTags[i+1] = 'i';
2421 break;
2422
2423 case FLOAT_osc:
2424 typeTags[i+1] = 'f';
2425 break;
2426
2427 case STRING_osc:
2428 typeTags[i+1] = 's';
2429 break;
2430
2431 default:
2432 error("Unrecognized arg type (not exiting)");
2433 return(wmERROR);
2434 }
2435 }
2436 typeTags[i+1] = '\0';
2437
2438 returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags);
2439 if (returnVal) {
2440 post("Problem writing address: %s\n", OSC_errorMessage);
2441 }
2442 }
2443
2444 for (j = 0; j < numArgs; j++) {
2445 switch (args[j].type) {
2446 case INT_osc:
2447 if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) {
2448 return returnVal;
2449 }
2450 break;
2451
2452 case FLOAT_osc:
2453 if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) {
2454 return returnVal;
2455 }
2456 break;
2457
2458 case STRING_osc:
2459 if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) {
2460 return returnVal;
2461 }
2462 break;
2463
2464 default:
2465 error("Unrecognized arg type (not exiting)");
2466 returnVal = wmERROR;
2467 }
2468 }
2469 return returnVal;
2470}
2471
2472void SendBuffer(void *htmsocket, OSCbuf *buf) {
2473#ifdef DEBUG
2474 printf("Sending buffer...\n");
2475#endif
2476 if (OSC_isBufferEmpty(buf)) {
2477 post("SendBuffer() called but buffer empty");
2478 return;
2479 }
2480 if (!OSC_isBufferDone(buf)) {
2481 error("SendBuffer() called but buffer not ready!, not exiting");
2482 return; //{{raf}}
2483 }
2484 SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf));
2485}
2486
2487void SendData(void *htmsocket, int size, char *data) {
2488 if (!SendHTMSocket(htmsocket, size, data)) {
2489 post("SendData::SendHTMSocket()failure -- not connected");
2490 CloseHTMSocket(htmsocket);
2491 }
2492}
2493
2494
2495
2496/* ----------------------
2497 OSC-client code
2498
2499 */
2500
2501/* Here are the possible values of the state field: */
2502
2503#define EMPTY 0 /* Nothing written to packet yet */
2504#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
2505#define NEED_COUNT 2 /* Just opened a bundle; must write message name or
2506 open another bundle */
2507#define GET_ARGS 3 /* Getting arguments to a message. If we see a message
2508 name or a bundle open/close then the current message
2509 will end. */
2510#define DONE 4 /* All open bundles have been closed, so can't write
2511 anything else */
2512
2513#ifdef WIN32
2514 #include <winsock2.h>
2515 #include <io.h>
2516 #include <stdio.h>
2517 #include <errno.h>
2518 #include <fcntl.h>
2519 #include <sys/types.h>
2520 #include <sys/stat.h>
2521#endif
2522
2523#ifdef __APPLE__
2524 #include <sys/types.h>
2525#endif
2526
2527#ifdef unix
2528 #include <netinet/in.h>
2529 #include <stdio.h>
2530#endif
2531
2532
2533char *OSC_errorMessage;
2534
2535static int OSC_padString(char *dest, char *str);
2536static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str);
2537static int OSC_WritePadding(char *dest, int i);
2538static int CheckTypeTag(OSCbuf *buf, char expectedType);
2539
2540void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
2541 buf->buffer = byteArray;
2542 buf->size = size;
2543 OSC_resetBuffer(buf);
2544}
2545
2546void OSC_resetBuffer(OSCbuf *buf) {
2547 buf->bufptr = buf->buffer;
2548 buf->state = EMPTY;
2549 buf->bundleDepth = 0;
2550 buf->prevCounts[0] = 0;
2551 buf->gettingFirstUntypedArg = 0;
2552 buf->typeStringPtr = 0;
2553}
2554
2555int OSC_isBufferEmpty(OSCbuf *buf) {
2556 return buf->bufptr == buf->buffer;
2557}
2558
2559int OSC_freeSpaceInBuffer(OSCbuf *buf) {
2560 return buf->size - (buf->bufptr - buf->buffer);
2561}
2562
2563int OSC_isBufferDone(OSCbuf *buf) {
2564 return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
2565}
2566
2567char *OSC_getPacket(OSCbuf *buf) {
2568#ifdef ERROR_CHECK_GETPACKET
2569 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
2570 return buf->buffer;
2571 } else {
2572 OSC_errorMessage = "Packet has unterminated bundles";
2573 return 0;
2574 }
2575#else
2576 return buf->buffer;
2577#endif
2578}
2579
2580int OSC_packetSize(OSCbuf *buf) {
2581#ifdef ERROR_CHECK_PACKETSIZE
2582 if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
2583 return (buf->bufptr - buf->buffer);
2584 } else {
2585 OSC_errorMessage = "Packet has unterminated bundles";
2586 return 0;
2587 }
2588#else
2589 return (buf->bufptr - buf->buffer);
2590#endif
2591}
2592
2593#define CheckOverflow(buf, bytesNeeded) { if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) {OSC_errorMessage = "buffer overflow"; return 1;}}
2594
2595static void PatchMessageSize(OSCbuf *buf) {
2596 int4byte size;
2597 size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
2598 *(buf->thisMsgSize) = htonl(size);
2599}
2600
2601int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
2602 if (buf->state == ONE_MSG_ARGS) {
2603 OSC_errorMessage = "Can't open a bundle in a one-message packet";
2604 return 3;
2605 }
2606
2607 if (buf->state == DONE) {
2608 OSC_errorMessage = "This packet is finished; can't open a new bundle";
2609 return 4;
2610 }
2611
2612 if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
2613 OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
2614 return 2;
2615 }
2616
2617 if (CheckTypeTag(buf, '\0')) return 9;
2618
2619 if (buf->state == GET_ARGS) {
2620 PatchMessageSize(buf);
2621 }
2622
2623 if (buf->state == EMPTY) {
2624 /* Need 16 bytes for "#bundle" and time tag */
2625 CheckOverflow(buf, 16);
2626 } else {
2627 /* This bundle is inside another bundle, so we need to leave
2628 a blank size count for the size of this current bundle. */
2629 CheckOverflow(buf, 20);
2630 *((int4byte *)buf->bufptr) = 0xaaaaaaaa;
2631 buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
2632
2633 buf->bufptr += 4;
2634 }
2635
2636 buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
2637
2638
2639 *((OSCTimeTag *) buf->bufptr) = tt;
2640
2641 if (htonl(1) != 1) {
2642 /* Byte swap the 8-byte integer time tag */
2643 int4byte *intp = (int4byte *)buf->bufptr;
2644 intp[0] = htonl(intp[0]);
2645 intp[1] = htonl(intp[1]);
2646
2647#ifdef HAS8BYTEINT
2648 { /* tt is a 64-bit int so we have to swap the two 32-bit words.
2649 (Otherwise tt is a struct of two 32-bit words, and even though
2650 each word was wrong-endian, they were in the right order
2651 in the struct.) */
2652 int4byte temp = intp[0];
2653 intp[0] = intp[1];
2654 intp[1] = temp;
2655 }
2656#endif
2657 }
2658
2659 buf->bufptr += sizeof(OSCTimeTag);
2660
2661 buf->state = NEED_COUNT;
2662
2663 buf->gettingFirstUntypedArg = 0;
2664 buf->typeStringPtr = 0;
2665 return 0;
2666}
2667
2668
2669int OSC_closeBundle(OSCbuf *buf) {
2670 if (buf->bundleDepth == 0) {
2671 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
2672 OSC_errorMessage = "Can't close bundle; no bundle is open!";
2673 return 5;
2674 }
2675
2676 if (CheckTypeTag(buf, '\0')) return 9;
2677
2678 if (buf->state == GET_ARGS) {
2679 PatchMessageSize(buf);
2680 }
2681
2682 if (buf->bundleDepth == 1) {
2683 /* Closing the last bundle: No bundle size to patch */
2684 buf->state = DONE;
2685 } else {
2686 /* Closing a sub-bundle: patch bundle size */
2687 int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
2688 *(buf->prevCounts[buf->bundleDepth]) = htonl(size);
2689 buf->state = NEED_COUNT;
2690 }
2691
2692 --buf->bundleDepth;
2693 buf->gettingFirstUntypedArg = 0;
2694 buf->typeStringPtr = 0;
2695 return 0;
2696}
2697
2698
2699int OSC_closeAllBundles(OSCbuf *buf) {
2700 if (buf->bundleDepth == 0) {
2701 /* This handles EMPTY, ONE_MSG, ARGS, and DONE */
2702 OSC_errorMessage = "Can't close all bundles; no bundle is open!";
2703 return 6;
2704 }
2705
2706 if (CheckTypeTag(buf, '\0')) return 9;
2707
2708 while (buf->bundleDepth > 0) {
2709 OSC_closeBundle(buf);
2710 }
2711 buf->typeStringPtr = 0;
2712 return 0;
2713}
2714
2715int OSC_writeAddress(OSCbuf *buf, char *name) {
2716 int4byte paddedLength;
2717
2718 if (buf->state == ONE_MSG_ARGS) {
2719 OSC_errorMessage = "This packet is not a bundle, so you can't write another address";
2720 return 7;
2721 }
2722
2723 if (buf->state == DONE) {
2724 OSC_errorMessage = "This packet is finished; can't write another address";
2725 return 8;
2726 }
2727
2728 if (CheckTypeTag(buf, '\0')) return 9;
2729
2730 paddedLength = OSC_effectiveStringLength(name);
2731
2732 if (buf->state == EMPTY) {
2733 /* This will be a one-message packet, so no sizes to worry about */
2734 CheckOverflow(buf, paddedLength);
2735 buf->state = ONE_MSG_ARGS;
2736 } else {
2737 /* GET_ARGS or NEED_COUNT */
2738 CheckOverflow(buf, 4+paddedLength);
2739 if (buf->state == GET_ARGS) {
2740 /* Close the old message */
2741 PatchMessageSize(buf);
2742 }
2743 buf->thisMsgSize = (int4byte *)buf->bufptr;
2744 *(buf->thisMsgSize) = 0xbbbbbbbb;
2745 buf->bufptr += 4;
2746 buf->state = GET_ARGS;
2747 }
2748
2749 /* Now write the name */
2750 buf->bufptr += OSC_padString(buf->bufptr, name);
2751 buf->typeStringPtr = 0;
2752 buf->gettingFirstUntypedArg = 1;
2753
2754 return 0;
2755}
2756
2757int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) {
2758 int result;
2759 int4byte paddedLength;
2760
2761 if (CheckTypeTag(buf, '\0')) return 9;
2762
2763 result = OSC_writeAddress(buf, name);
2764
2765 if (result) return result;
2766
2767 paddedLength = OSC_effectiveStringLength(types);
2768
2769 CheckOverflow(buf, paddedLength);
2770
2771 buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
2772 buf->bufptr += OSC_padString(buf->bufptr, types);
2773
2774 buf->gettingFirstUntypedArg = 0;
2775 return 0;
2776}
2777
2778static int CheckTypeTag(OSCbuf *buf, char expectedType) {
2779 if (buf->typeStringPtr) {
2780 if (*(buf->typeStringPtr) != expectedType) {
2781 if (expectedType == '\0') {
2782 OSC_errorMessage =
2783 "According to the type tag I expected more arguments.";
2784 } else if (*(buf->typeStringPtr) == '\0') {
2785 OSC_errorMessage =
2786 "According to the type tag I didn't expect any more arguments.";
2787 } else {
2788 OSC_errorMessage =
2789 "According to the type tag I expected an argument of a different type.";
2790 printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
2791 }
2792 return 9;
2793 }
2794 ++(buf->typeStringPtr);
2795 }
2796 return 0;
2797}
2798
2799
2800int OSC_writeFloatArg(OSCbuf *buf, float arg) {
2801 int4byte *intp;
2802 //int result;
2803
2804 CheckOverflow(buf, 4);
2805
2806 if (CheckTypeTag(buf, 'f')) return 9;
2807
2808 /* Pretend arg is a long int so we can use htonl() */
2809 intp = ((int4byte *) &arg);
2810 *((int4byte *) buf->bufptr) = htonl(*intp);
2811
2812 buf->bufptr += 4;
2813
2814 buf->gettingFirstUntypedArg = 0;
2815 return 0;
2816}
2817
2818
2819
2820int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
2821 int i;
2822 int4byte *intp;
2823
2824 CheckOverflow(buf, 4 * numFloats);
2825
2826 /* Pretend args are long ints so we can use htonl() */
2827 intp = ((int4byte *) args);
2828
2829 for (i = 0; i < numFloats; i++) {
2830 if (CheckTypeTag(buf, 'f')) return 9;
2831 *((int4byte *) buf->bufptr) = htonl(intp[i]);
2832 buf->bufptr += 4;
2833 }
2834
2835 buf->gettingFirstUntypedArg = 0;
2836 return 0;
2837}
2838
2839int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
2840 CheckOverflow(buf, 4);
2841 if (CheckTypeTag(buf, 'i')) return 9;
2842
2843 *((int4byte *) buf->bufptr) = htonl(arg);
2844 buf->bufptr += 4;
2845
2846 buf->gettingFirstUntypedArg = 0;
2847 return 0;
2848}
2849
2850int OSC_writeStringArg(OSCbuf *buf, char *arg) {
2851 int len;
2852
2853 if (CheckTypeTag(buf, 's')) return 9;
2854
2855 len = OSC_effectiveStringLength(arg);
2856
2857 if (buf->gettingFirstUntypedArg && arg[0] == ',') {
2858 /* This un-type-tagged message starts with a string
2859 that starts with a comma, so we have to escape it
2860 (with a double comma) so it won't look like a type
2861 tag string. */
2862
2863 CheckOverflow(buf, len+4); /* Too conservative */
2864 buf->bufptr +=
2865 OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg);
2866
2867 } else {
2868 CheckOverflow(buf, len);
2869 buf->bufptr += OSC_padString(buf->bufptr, arg);
2870 }
2871
2872 buf->gettingFirstUntypedArg = 0;
2873 return 0;
2874
2875}
2876
2877/* String utilities */
2878
2879#define STRING_ALIGN_PAD 4
2880int OSC_effectiveStringLength(char *string) {
2881 int len = strlen(string) + 1; /* We need space for the null char. */
2882
2883 /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
2884 if ((len % STRING_ALIGN_PAD) != 0) {
2885 len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
2886 }
2887 return len;
2888}
2889
2890static int OSC_padString(char *dest, char *str) {
2891 int i;
2892
2893 for (i = 0; str[i] != '\0'; i++) {
2894 dest[i] = str[i];
2895 }
2896
2897 return OSC_WritePadding(dest, i);
2898}
2899
2900static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) {
2901 int i;
2902
2903 dest[0] = ',';
2904 for (i = 0; str[i] != '\0'; i++) {
2905 dest[i+1] = str[i];
2906 }
2907
2908 return OSC_WritePadding(dest, i+1);
2909}
2910
2911static int OSC_WritePadding(char *dest, int i) {
2912 dest[i] = '\0';
2913 i++;
2914
2915 for (; (i % STRING_ALIGN_PAD) != 0; i++) {
2916 dest[i] = '\0';
2917 }
2918
2919 return i;
2920}
2921
2922
diff --git a/apps/plugins/pdbox/PDa/extra/sformat.h b/apps/plugins/pdbox/PDa/extra/sformat.h
new file mode 100644
index 0000000000..b75ef98c9a
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/sformat.h
@@ -0,0 +1,110 @@
1
2#ifndef SFORMAT_H__
3#define SFORMAT_H__
4
5typedef unsigned short uint16;
6typedef unsigned long uint32;
7
8#define FORMAT_WAVE 0
9#define FORMAT_AIFF 1
10#define FORMAT_NEXT 2
11
12/* the NeXTStep sound header structure; can be big or little endian */
13
14typedef struct _nextstep
15{
16 char ns_fileid[4]; /* magic number '.snd' if file is big-endian */
17 uint32 ns_onset; /* byte offset of first sample */
18 uint32 ns_length; /* length of sound in bytes */
19 uint32 ns_format; /* format; see below */
20 uint32 ns_sr; /* sample rate */
21 uint32 ns_nchans; /* number of channels */
22 char ns_info[4]; /* comment */
23} t_nextstep;
24
25#define NS_FORMAT_LINEAR_16 3
26#define NS_FORMAT_LINEAR_24 4
27#define NS_FORMAT_FLOAT 6
28#define SCALE (1./(1024. * 1024. * 1024. * 2.))
29
30/* the WAVE header. All Wave files are little endian. We assume
31 the "fmt" chunk comes first which is usually the case but perhaps not
32 always; same for AIFF and the "COMM" chunk. */
33
34typedef unsigned word;
35typedef unsigned long dword;
36
37typedef struct _wave
38{
39 char w_fileid[4]; /* chunk id 'RIFF' */
40 uint32 w_chunksize; /* chunk size */
41 char w_waveid[4]; /* wave chunk id 'WAVE' */
42 char w_fmtid[4]; /* format chunk id 'fmt ' */
43 uint32 w_fmtchunksize; /* format chunk size */
44 uint16 w_fmttag; /* format tag, 1 for PCM */
45 uint16 w_nchannels; /* number of channels */
46 uint32 w_samplespersec; /* sample rate in hz */
47 uint32 w_navgbytespersec; /* average bytes per second */
48 uint16 w_nblockalign; /* number of bytes per sample */
49 uint16 w_nbitspersample; /* number of bits in a sample */
50 char w_datachunkid[4]; /* data chunk id 'data' */
51 uint32 w_datachunksize; /* length of data chunk */
52} t_wave;
53
54
55#endif
56
57#ifndef SFORMAT_H__
58#define SFORMAT_H__
59
60typedef unsigned short uint16;
61typedef unsigned long uint32;
62
63#define FORMAT_WAVE 0
64#define FORMAT_AIFF 1
65#define FORMAT_NEXT 2
66
67/* the NeXTStep sound header structure; can be big or little endian */
68
69typedef struct _nextstep
70{
71 char ns_fileid[4]; /* magic number '.snd' if file is big-endian */
72 uint32 ns_onset; /* byte offset of first sample */
73 uint32 ns_length; /* length of sound in bytes */
74 uint32 ns_format; /* format; see below */
75 uint32 ns_sr; /* sample rate */
76 uint32 ns_nchans; /* number of channels */
77 char ns_info[4]; /* comment */
78} t_nextstep;
79
80#define NS_FORMAT_LINEAR_16 3
81#define NS_FORMAT_LINEAR_24 4
82#define NS_FORMAT_FLOAT 6
83#define SCALE (1./(1024. * 1024. * 1024. * 2.))
84
85/* the WAVE header. All Wave files are little endian. We assume
86 the "fmt" chunk comes first which is usually the case but perhaps not
87 always; same for AIFF and the "COMM" chunk. */
88
89typedef unsigned word;
90typedef unsigned long dword;
91
92typedef struct _wave
93{
94 char w_fileid[4]; /* chunk id 'RIFF' */
95 uint32 w_chunksize; /* chunk size */
96 char w_waveid[4]; /* wave chunk id 'WAVE' */
97 char w_fmtid[4]; /* format chunk id 'fmt ' */
98 uint32 w_fmtchunksize; /* format chunk size */
99 uint16 w_fmttag; /* format tag, 1 for PCM */
100 uint16 w_nchannels; /* number of channels */
101 uint32 w_samplespersec; /* sample rate in hz */
102 uint32 w_navgbytespersec; /* average bytes per second */
103 uint16 w_nblockalign; /* number of bytes per sample */
104 uint16 w_nbitspersample; /* number of bits in a sample */
105 char w_datachunkid[4]; /* data chunk id 'data' */
106 uint32 w_datachunksize; /* length of data chunk */
107} t_wave;
108
109
110#endif
diff --git a/apps/plugins/pdbox/PDa/extra/shell.c b/apps/plugins/pdbox/PDa/extra/shell.c
new file mode 100644
index 0000000000..a0b6cef5b5
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/shell.c
@@ -0,0 +1,624 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3#include "m_pd.h"
4#ifdef NT
5#pragma warning( disable : 4244 )
6#pragma warning( disable : 4305 )
7#endif
8
9#include <unistd.h>
10#include <stdlib.h>
11#include <string.h>
12#include <stdio.h>
13#include <sys/types.h>
14#include <sys/wait.h>
15#include <signal.h>
16#include <sched.h>
17
18void sys_rmpollfn(int fd);
19void sys_addpollfn(int fd, void* fn, void *ptr);
20
21/* ------------------------ shell ----------------------------- */
22
23#define INBUFSIZE 1024
24
25static t_class *shell_class;
26
27
28static void drop_priority(void)
29{
30#ifdef _POSIX_PRIORITY_SCHEDULING
31 struct sched_param par;
32 int p1 ,p2, p3;
33 par.sched_priority = 0;
34 sched_setscheduler(0,SCHED_OTHER,&par);
35#endif
36}
37
38
39typedef struct _shell
40{
41 t_object x_obj;
42 int x_echo;
43 char *sr_inbuf;
44 int sr_inhead;
45 int sr_intail;
46 void* x_binbuf;
47 int fdpipe[2];
48 int fdinpipe[2];
49 int pid;
50 int x_del;
51 t_outlet* x_done;
52 t_clock* x_clock;
53} t_shell;
54
55static int shell_pid;
56
57
58void shell_cleanup(t_shell* x)
59{
60 sys_rmpollfn(x->fdpipe[0]);
61
62 if (x->fdpipe[0]>0) close(x->fdpipe[0]);
63 if (x->fdpipe[1]>0) close(x->fdpipe[1]);
64 if (x->fdinpipe[0]>0) close(x->fdinpipe[0]);
65 if (x->fdinpipe[1]>0) close(x->fdinpipe[1]);
66
67 x->fdpipe[0] = -1;
68 x->fdpipe[1] = -1;
69 x->fdinpipe[0] = -1;
70 x->fdinpipe[1] = -1;
71 clock_unset(x->x_clock);
72}
73
74void shell_check(t_shell* x)
75{
76 int ret;
77 int status;
78 ret = waitpid(x->pid,&status,WNOHANG);
79 if (ret == x->pid) {
80 shell_cleanup(x);
81 if (WIFEXITED(status)) {
82 outlet_float(x->x_done,WEXITSTATUS(status));
83 }
84 else outlet_float(x->x_done,0);
85 }
86 else {
87 if (x->x_del < 100) x->x_del+=2; /* increment poll times */
88 clock_delay(x->x_clock,x->x_del);
89 }
90}
91
92
93void shell_bang(t_shell *x)
94{
95 post("bang");
96}
97
98/* snippet from pd's code */
99static void shell_doit(void *z, t_binbuf *b)
100{
101 t_shell *x = (t_shell *)z;
102 int msg, natom = binbuf_getnatom(b);
103 t_atom *at = binbuf_getvec(b);
104
105 for (msg = 0; msg < natom;)
106 {
107 int emsg;
108 for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
109 && at[emsg].a_type != A_SEMI; emsg++)
110 ;
111 if (emsg > msg)
112 {
113 int i;
114 for (i = msg; i < emsg; i++)
115 if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
116 {
117 pd_error(x, "netreceive: got dollar sign in message");
118 goto nodice;
119 }
120 if (at[msg].a_type == A_FLOAT)
121 {
122 if (emsg > msg + 1)
123 outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
124 else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
125 }
126 else if (at[msg].a_type == A_SYMBOL)
127 outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
128 emsg-msg-1, at + msg + 1);
129 }
130 nodice:
131 msg = emsg + 1;
132 }
133}
134
135
136void shell_read(t_shell *x, int fd)
137{
138 char buf[INBUFSIZE];
139 t_binbuf* bbuf = binbuf_new();
140 int i;
141 int readto =
142 (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
143 int ret;
144
145 ret = read(fd, buf,INBUFSIZE-1);
146 buf[ret] = '\0';
147
148 for (i=0;i<ret;i++)
149 if (buf[i] == '\n') buf[i] = ';';
150 if (ret < 0)
151 {
152 error("shell: pipe read error");
153 sys_rmpollfn(fd);
154 x->fdpipe[0] = -1;
155 close(fd);
156 return;
157 }
158 else if (ret == 0)
159 {
160 post("EOF on socket %d\n", fd);
161 sys_rmpollfn(fd);
162 x->fdpipe[0] = -1;
163 close(fd);
164 return;
165 }
166 else
167 {
168 int natom;
169 t_atom *at;
170 binbuf_text(bbuf, buf, strlen(buf));
171
172 natom = binbuf_getnatom(bbuf);
173 at = binbuf_getvec(bbuf);
174 shell_doit(x,bbuf);
175 }
176 binbuf_free(bbuf);
177}
178
179
180static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at)
181{
182 int i;
183 char tmp[MAXPDSTRING];
184 int size = 0;
185
186 if (x->fdinpipe[0] == -1) return; /* nothing to send to */
187
188 for (i=0;i<ac;i++) {
189 atom_string(at,tmp+size,MAXPDSTRING - size);
190 at++;
191 size=strlen(tmp);
192 tmp[size++] = ' ';
193 }
194 tmp[size-1] = '\0';
195 post("sending %s",tmp);
196 write(x->fdinpipe[0],tmp,strlen(tmp));
197}
198
199static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
200{
201 int i;
202 char* argv[20];
203 t_symbol* sym;
204
205 if (!strcmp(s->s_name,"send")) {
206 post("send");
207 shell_send(x,s,ac,at);
208 return;
209 }
210
211 argv[0] = s->s_name;
212
213 if (x->fdpipe[0] != -1) {
214 post("shell: old process still running");
215 kill(x->pid,SIGKILL);
216 shell_cleanup(x);
217 }
218
219
220 if (pipe(x->fdpipe) < 0) {
221 error("unable to create pipe");
222 return;
223 }
224
225 if (pipe(x->fdinpipe) < 0) {
226 error("unable to create input pipe");
227 return;
228 }
229
230
231 sys_addpollfn(x->fdpipe[0],shell_read,x);
232
233 if (!(x->pid = fork())) {
234 int status;
235 char* cmd = getbytes(1024);
236 char* tcmd = getbytes(1024);
237 strcpy(cmd,s->s_name);
238
239#if 0
240 for (i=1;i<=ac;i++) {
241 argv[i] = getbytes(255);
242 atom_string(at,argv[i],255);
243/* post("argument %s",argv[i]); */
244 at++;
245 }
246 argv[i] = 0;
247#endif
248 for (i=1;i<=ac;i++) {
249 atom_string(at,tcmd,255);
250 strcat(cmd," ");
251 strcat(cmd,tcmd);
252 at++;
253 }
254
255
256 /* reassign stdout */
257 dup2(x->fdpipe[1],1);
258 dup2(x->fdinpipe[1],0);
259
260 /* drop privileges */
261 drop_priority();
262 seteuid(getuid()); /* lose setuid priveliges */
263
264 post("executing %s",cmd);
265 system(cmd);
266// execvp(s->s_name,argv);
267 exit(0);
268 }
269 x->x_del = 4;
270 clock_delay(x->x_clock,x->x_del);
271
272 if (x->x_echo)
273 outlet_anything(x->x_obj.ob_outlet, s, ac, at);
274}
275
276
277
278void shell_free(t_shell* x)
279{
280 binbuf_free(x->x_binbuf);
281}
282
283static void *shell_new(void)
284{
285 t_shell *x = (t_shell *)pd_new(shell_class);
286
287 x->x_echo = 0;
288 x->fdpipe[0] = -1;
289 x->fdpipe[1] = -1;
290 x->fdinpipe[0] = -1;
291 x->fdinpipe[1] = -1;
292
293 x->sr_inhead = x->sr_intail = 0;
294 if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
295
296 x->x_binbuf = binbuf_new();
297
298 outlet_new(&x->x_obj, &s_list);
299 x->x_done = outlet_new(&x->x_obj, &s_bang);
300 x->x_clock = clock_new(x, (t_method) shell_check);
301 return (x);
302}
303
304void shell_setup(void)
305{
306 shell_class = class_new(gensym("shell"), (t_newmethod)shell_new,
307 (t_method)shell_free,sizeof(t_shell), 0,0);
308 class_addbang(shell_class,shell_bang);
309 class_addanything(shell_class, shell_anything);
310}
311
312
313/* (C) Guenter Geiger <geiger@epy.co.at> */
314
315#include "m_pd.h"
316#ifdef NT
317#pragma warning( disable : 4244 )
318#pragma warning( disable : 4305 )
319#endif
320
321#include <unistd.h>
322#include <stdlib.h>
323#include <string.h>
324#include <stdio.h>
325#include <sys/types.h>
326#include <sys/wait.h>
327#include <signal.h>
328#include <sched.h>
329
330void sys_rmpollfn(int fd);
331void sys_addpollfn(int fd, void* fn, void *ptr);
332
333/* ------------------------ shell ----------------------------- */
334
335#define INBUFSIZE 1024
336
337static t_class *shell_class;
338
339
340static void drop_priority(void)
341{
342#ifdef _POSIX_PRIORITY_SCHEDULING
343 struct sched_param par;
344 int p1 ,p2, p3;
345 par.sched_priority = 0;
346 sched_setscheduler(0,SCHED_OTHER,&par);
347#endif
348}
349
350
351typedef struct _shell
352{
353 t_object x_obj;
354 int x_echo;
355 char *sr_inbuf;
356 int sr_inhead;
357 int sr_intail;
358 void* x_binbuf;
359 int fdpipe[2];
360 int fdinpipe[2];
361 int pid;
362 int x_del;
363 t_outlet* x_done;
364 t_clock* x_clock;
365} t_shell;
366
367static int shell_pid;
368
369
370void shell_cleanup(t_shell* x)
371{
372 sys_rmpollfn(x->fdpipe[0]);
373
374 if (x->fdpipe[0]>0) close(x->fdpipe[0]);
375 if (x->fdpipe[1]>0) close(x->fdpipe[1]);
376 if (x->fdinpipe[0]>0) close(x->fdinpipe[0]);
377 if (x->fdinpipe[1]>0) close(x->fdinpipe[1]);
378
379 x->fdpipe[0] = -1;
380 x->fdpipe[1] = -1;
381 x->fdinpipe[0] = -1;
382 x->fdinpipe[1] = -1;
383 clock_unset(x->x_clock);
384}
385
386void shell_check(t_shell* x)
387{
388 int ret;
389 int status;
390 ret = waitpid(x->pid,&status,WNOHANG);
391 if (ret == x->pid) {
392 shell_cleanup(x);
393 if (WIFEXITED(status)) {
394 outlet_float(x->x_done,WEXITSTATUS(status));
395 }
396 else outlet_float(x->x_done,0);
397 }
398 else {
399 if (x->x_del < 100) x->x_del+=2; /* increment poll times */
400 clock_delay(x->x_clock,x->x_del);
401 }
402}
403
404
405void shell_bang(t_shell *x)
406{
407 post("bang");
408}
409
410/* snippet from pd's code */
411static void shell_doit(void *z, t_binbuf *b)
412{
413 t_shell *x = (t_shell *)z;
414 int msg, natom = binbuf_getnatom(b);
415 t_atom *at = binbuf_getvec(b);
416
417 for (msg = 0; msg < natom;)
418 {
419 int emsg;
420 for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
421 && at[emsg].a_type != A_SEMI; emsg++)
422 ;
423 if (emsg > msg)
424 {
425 int i;
426 for (i = msg; i < emsg; i++)
427 if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
428 {
429 pd_error(x, "netreceive: got dollar sign in message");
430 goto nodice;
431 }
432 if (at[msg].a_type == A_FLOAT)
433 {
434 if (emsg > msg + 1)
435 outlet_list(x->x_obj.ob_outlet, 0, emsg-msg, at + msg);
436 else outlet_float(x->x_obj.ob_outlet, at[msg].a_w.w_float);
437 }
438 else if (at[msg].a_type == A_SYMBOL)
439 outlet_anything(x->x_obj.ob_outlet, at[msg].a_w.w_symbol,
440 emsg-msg-1, at + msg + 1);
441 }
442 nodice:
443 msg = emsg + 1;
444 }
445}
446
447
448void shell_read(t_shell *x, int fd)
449{
450 char buf[INBUFSIZE];
451 t_binbuf* bbuf = binbuf_new();
452 int i;
453 int readto =
454 (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
455 int ret;
456
457 ret = read(fd, buf,INBUFSIZE-1);
458 buf[ret] = '\0';
459
460 for (i=0;i<ret;i++)
461 if (buf[i] == '\n') buf[i] = ';';
462 if (ret < 0)
463 {
464 error("shell: pipe read error");
465 sys_rmpollfn(fd);
466 x->fdpipe[0] = -1;
467 close(fd);
468 return;
469 }
470 else if (ret == 0)
471 {
472 post("EOF on socket %d\n", fd);
473 sys_rmpollfn(fd);
474 x->fdpipe[0] = -1;
475 close(fd);
476 return;
477 }
478 else
479 {
480 int natom;
481 t_atom *at;
482 binbuf_text(bbuf, buf, strlen(buf));
483
484 natom = binbuf_getnatom(bbuf);
485 at = binbuf_getvec(bbuf);
486 shell_doit(x,bbuf);
487 }
488 binbuf_free(bbuf);
489}
490
491
492static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at)
493{
494 int i;
495 char tmp[MAXPDSTRING];
496 int size = 0;
497
498 if (x->fdinpipe[0] == -1) return; /* nothing to send to */
499
500 for (i=0;i<ac;i++) {
501 atom_string(at,tmp+size,MAXPDSTRING - size);
502 at++;
503 size=strlen(tmp);
504 tmp[size++] = ' ';
505 }
506 tmp[size-1] = '\0';
507 post("sending %s",tmp);
508 write(x->fdinpipe[0],tmp,strlen(tmp));
509}
510
511static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
512{
513 int i;
514 char* argv[20];
515 t_symbol* sym;
516
517 if (!strcmp(s->s_name,"send")) {
518 post("send");
519 shell_send(x,s,ac,at);
520 return;
521 }
522
523 argv[0] = s->s_name;
524
525 if (x->fdpipe[0] != -1) {
526 post("shell: old process still running");
527 kill(x->pid,SIGKILL);
528 shell_cleanup(x);
529 }
530
531
532 if (pipe(x->fdpipe) < 0) {
533 error("unable to create pipe");
534 return;
535 }
536
537 if (pipe(x->fdinpipe) < 0) {
538 error("unable to create input pipe");
539 return;
540 }
541
542
543 sys_addpollfn(x->fdpipe[0],shell_read,x);
544
545 if (!(x->pid = fork())) {
546 int status;
547 char* cmd = getbytes(1024);
548 char* tcmd = getbytes(1024);
549 strcpy(cmd,s->s_name);
550
551#if 0
552 for (i=1;i<=ac;i++) {
553 argv[i] = getbytes(255);
554 atom_string(at,argv[i],255);
555/* post("argument %s",argv[i]); */
556 at++;
557 }
558 argv[i] = 0;
559#endif
560 for (i=1;i<=ac;i++) {
561 atom_string(at,tcmd,255);
562 strcat(cmd," ");
563 strcat(cmd,tcmd);
564 at++;
565 }
566
567
568 /* reassign stdout */
569 dup2(x->fdpipe[1],1);
570 dup2(x->fdinpipe[1],0);
571
572 /* drop privileges */
573 drop_priority();
574 seteuid(getuid()); /* lose setuid priveliges */
575
576 post("executing %s",cmd);
577 system(cmd);
578// execvp(s->s_name,argv);
579 exit(0);
580 }
581 x->x_del = 4;
582 clock_delay(x->x_clock,x->x_del);
583
584 if (x->x_echo)
585 outlet_anything(x->x_obj.ob_outlet, s, ac, at);
586}
587
588
589
590void shell_free(t_shell* x)
591{
592 binbuf_free(x->x_binbuf);
593}
594
595static void *shell_new(void)
596{
597 t_shell *x = (t_shell *)pd_new(shell_class);
598
599 x->x_echo = 0;
600 x->fdpipe[0] = -1;
601 x->fdpipe[1] = -1;
602 x->fdinpipe[0] = -1;
603 x->fdinpipe[1] = -1;
604
605 x->sr_inhead = x->sr_intail = 0;
606 if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
607
608 x->x_binbuf = binbuf_new();
609
610 outlet_new(&x->x_obj, &s_list);
611 x->x_done = outlet_new(&x->x_obj, &s_bang);
612 x->x_clock = clock_new(x, (t_method) shell_check);
613 return (x);
614}
615
616void shell_setup(void)
617{
618 shell_class = class_new(gensym("shell"), (t_newmethod)shell_new,
619 (t_method)shell_free,sizeof(t_shell), 0,0);
620 class_addbang(shell_class,shell_bang);
621 class_addanything(shell_class, shell_anything);
622}
623
624
diff --git a/apps/plugins/pdbox/PDa/extra/slider.c b/apps/plugins/pdbox/PDa/extra/slider.c
new file mode 100644
index 0000000000..4650050006
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/slider.c
@@ -0,0 +1,106 @@
1#include <stdio.h>
2#include "m_pd.h"
3#include "g_canvas.h" /* for widgetbehaviour */
4#include "fatom.h"
5
6static t_class *slider_class;
7
8static void slider_save(t_gobj *z, t_binbuf *b)
9{
10 t_fatom *x = (t_fatom *)z;
11
12 binbuf_addv(b, "ssiisiiisss", gensym("#X"),gensym("obj"),
13 x->x_obj.te_xpix, x->x_obj.te_ypix ,
14 gensym("slider"),x->x_max,x->x_min,x->x_width,x->x_send,x->x_color,x->x_bgcolor);
15 binbuf_addv(b, ";");
16}
17
18
19static void *slider_new(t_symbol* s,t_int argc, t_atom* argv)
20{
21 t_fatom *x = (t_fatom *)pd_new(slider_class);
22 x->x_type = gensym("vslider");
23 return fatom_new(x,argc,argv);
24}
25
26
27t_widgetbehavior slider_widgetbehavior;
28
29
30void slider_setup(void) {
31 slider_class = class_new(gensym("slider"), (t_newmethod)slider_new, 0,
32 sizeof(t_fatom),0,A_GIMME,0);
33
34 slider_widgetbehavior.w_getrectfn = fatom_getrect;
35 slider_widgetbehavior.w_displacefn = fatom_displace;
36 slider_widgetbehavior.w_selectfn = fatom_select;
37 slider_widgetbehavior.w_activatefn = fatom_activate;
38 slider_widgetbehavior.w_deletefn = fatom_delete;
39 slider_widgetbehavior.w_visfn= fatom_vis;
40 slider_widgetbehavior.w_clickfn = NULL;
41
42 fatom_setup_common(slider_class);
43 class_setwidget(slider_class,&slider_widgetbehavior);
44
45#if PD_MINOR_VERSION < 37
46 slider_widgetbehavior.w_savefn = slider_save;
47 slider_widgetbehavior.w_propertiesfn = NULL;
48#else
49 class_setsavefn(slider_class,&slider_save);
50 class_setpropertiesfn(slider_class,&fatom_properties);
51#endif
52
53}
54#include <stdio.h>
55#include "m_pd.h"
56#include "g_canvas.h" /* for widgetbehaviour */
57#include "fatom.h"
58
59static t_class *slider_class;
60
61static void slider_save(t_gobj *z, t_binbuf *b)
62{
63 t_fatom *x = (t_fatom *)z;
64
65 binbuf_addv(b, "ssiisiiisss", gensym("#X"),gensym("obj"),
66 x->x_obj.te_xpix, x->x_obj.te_ypix ,
67 gensym("slider"),x->x_max,x->x_min,x->x_width,x->x_send,x->x_color,x->x_bgcolor);
68 binbuf_addv(b, ";");
69}
70
71
72static void *slider_new(t_symbol* s,t_int argc, t_atom* argv)
73{
74 t_fatom *x = (t_fatom *)pd_new(slider_class);
75 x->x_type = gensym("vslider");
76 return fatom_new(x,argc,argv);
77}
78
79
80t_widgetbehavior slider_widgetbehavior;
81
82
83void slider_setup(void) {
84 slider_class = class_new(gensym("slider"), (t_newmethod)slider_new, 0,
85 sizeof(t_fatom),0,A_GIMME,0);
86
87 slider_widgetbehavior.w_getrectfn = fatom_getrect;
88 slider_widgetbehavior.w_displacefn = fatom_displace;
89 slider_widgetbehavior.w_selectfn = fatom_select;
90 slider_widgetbehavior.w_activatefn = fatom_activate;
91 slider_widgetbehavior.w_deletefn = fatom_delete;
92 slider_widgetbehavior.w_visfn= fatom_vis;
93 slider_widgetbehavior.w_clickfn = NULL;
94
95 fatom_setup_common(slider_class);
96 class_setwidget(slider_class,&slider_widgetbehavior);
97
98#if PD_MINOR_VERSION < 37
99 slider_widgetbehavior.w_savefn = slider_save;
100 slider_widgetbehavior.w_propertiesfn = NULL;
101#else
102 class_setsavefn(slider_class,&slider_save);
103 class_setpropertiesfn(slider_class,&fatom_properties);
104#endif
105
106}
diff --git a/apps/plugins/pdbox/PDa/extra/sliderh.c b/apps/plugins/pdbox/PDa/extra/sliderh.c
new file mode 100644
index 0000000000..23a6d256e0
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/sliderh.c
@@ -0,0 +1,126 @@
1#include "m_pd.h"
2#include "g_canvas.h"
3
4
5#ifdef NT
6#pragma warning( disable : 4244 )
7#pragma warning( disable : 4305 )
8#endif
9
10#include "fatom.h"
11
12/* can we use the normal text save function ?? */
13
14static t_class *sliderh_class;
15
16static void sliderh_save(t_gobj *z, t_binbuf *b)
17{
18
19 t_fatom *x = (t_fatom *)z;
20
21 binbuf_addv(b, "ssiisiiisss", gensym("#X"),gensym("obj"),
22 x->x_obj.te_xpix, x->x_obj.te_ypix ,
23 gensym("sliderh"),x->x_max,x->x_min,x->x_width,x->x_send,x->x_color,x->x_bgcolor);
24 binbuf_addv(b, ";");
25}
26
27
28static void *sliderh_new(t_symbol* s, int argc, t_atom* argv)
29{
30 t_fatom *x = (t_fatom *)pd_new(sliderh_class);
31 x->x_type = gensym("hslider");
32 return fatom_new(x,argc,argv);
33}
34
35
36t_widgetbehavior sliderh_widgetbehavior;
37
38
39
40
41void sliderh_setup(void) {
42 sliderh_class = class_new(gensym("sliderh"), (t_newmethod)sliderh_new, 0,
43 sizeof(t_fatom),0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
44
45 fatom_setup_common(sliderh_class);
46
47 sliderh_widgetbehavior.w_getrectfn = fatom_getrect;
48 sliderh_widgetbehavior.w_displacefn= fatom_displace;
49 sliderh_widgetbehavior.w_selectfn= fatom_select;
50 sliderh_widgetbehavior.w_activatefn=fatom_activate;
51 sliderh_widgetbehavior.w_deletefn= fatom_delete;
52 sliderh_widgetbehavior.w_visfn= fatom_vis;
53#if PD_MINOR_VERSION < 37
54 sliderh_widgetbehavior.w_savefn= sliderh_save;
55 sliderh_widgetbehavior.w_propertiesfn= NULL;
56#endif
57 sliderh_widgetbehavior.w_clickfn= NULL;
58
59 class_setwidget(sliderh_class,&sliderh_widgetbehavior);
60#if PD_MINOR_VERSION >= 37
61 class_setsavefn(sliderh_class,&sliderh_save);
62#endif
63}
64#include "m_pd.h"
65#include "g_canvas.h"
66
67
68#ifdef NT
69#pragma warning( disable : 4244 )
70#pragma warning( disable : 4305 )
71#endif
72
73#include "fatom.h"
74
75/* can we use the normal text save function ?? */
76
77static t_class *sliderh_class;
78
79static void sliderh_save(t_gobj *z, t_binbuf *b)
80{
81
82 t_fatom *x = (t_fatom *)z;
83
84 binbuf_addv(b, "ssiisiiisss", gensym("#X"),gensym("obj"),
85 x->x_obj.te_xpix, x->x_obj.te_ypix ,
86 gensym("sliderh"),x->x_max,x->x_min,x->x_width,x->x_send,x->x_color,x->x_bgcolor);
87 binbuf_addv(b, ";");
88}
89
90
91static void *sliderh_new(t_symbol* s, int argc, t_atom* argv)
92{
93 t_fatom *x = (t_fatom *)pd_new(sliderh_class);
94 x->x_type = gensym("hslider");
95 return fatom_new(x,argc,argv);
96}
97
98
99t_widgetbehavior sliderh_widgetbehavior;
100
101
102
103
104void sliderh_setup(void) {
105 sliderh_class = class_new(gensym("sliderh"), (t_newmethod)sliderh_new, 0,
106 sizeof(t_fatom),0,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,0);
107
108 fatom_setup_common(sliderh_class);
109
110 sliderh_widgetbehavior.w_getrectfn = fatom_getrect;
111 sliderh_widgetbehavior.w_displacefn= fatom_displace;
112 sliderh_widgetbehavior.w_selectfn= fatom_select;
113 sliderh_widgetbehavior.w_activatefn=fatom_activate;
114 sliderh_widgetbehavior.w_deletefn= fatom_delete;
115 sliderh_widgetbehavior.w_visfn= fatom_vis;
116#if PD_MINOR_VERSION < 37
117 sliderh_widgetbehavior.w_savefn= sliderh_save;
118 sliderh_widgetbehavior.w_propertiesfn= NULL;
119#endif
120 sliderh_widgetbehavior.w_clickfn= NULL;
121
122 class_setwidget(sliderh_class,&sliderh_widgetbehavior);
123#if PD_MINOR_VERSION >= 37
124 class_setsavefn(sliderh_class,&sliderh_save);
125#endif
126}
diff --git a/apps/plugins/pdbox/PDa/extra/test-clip.pd b/apps/plugins/pdbox/PDa/extra/test-clip.pd
new file mode 100644
index 0000000000..c682e31845
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/test-clip.pd
@@ -0,0 +1,26 @@
1#N canvas 0 0 240 300 10;
2#X obj 57 84 clip~ -0.1 0.1;
3#X obj 58 61 sig~;
4#X obj 57 111 snapshot~;
5#X floatatom 58 19 5 0 0 0 - - -;
6#X floatatom 57 144 5 0 0 0 - - -;
7#X obj 58 37 t f b;
8#X connect 0 0 2 0;
9#X connect 1 0 0 0;
10#X connect 2 0 4 0;
11#X connect 3 0 5 0;
12#X connect 5 0 1 0;
13#X connect 5 1 2 0;
14#N canvas 0 0 240 300 10;
15#X obj 57 84 clip~ -0.1 0.1;
16#X obj 58 61 sig~;
17#X obj 57 111 snapshot~;
18#X floatatom 58 19 5 0 0 0 - - -;
19#X floatatom 57 144 5 0 0 0 - - -;
20#X obj 58 37 t f b;
21#X connect 0 0 2 0;
22#X connect 1 0 0 0;
23#X connect 2 0 4 0;
24#X connect 3 0 5 0;
25#X connect 5 0 1 0;
26#X connect 5 1 2 0;
diff --git a/apps/plugins/pdbox/PDa/extra/test-vcf.pd b/apps/plugins/pdbox/PDa/extra/test-vcf.pd
new file mode 100644
index 0000000000..099d3d7958
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/test-vcf.pd
@@ -0,0 +1,36 @@
1#N canvas 0 0 240 300 10;
2#X obj 38 93 noise~;
3#X obj 44 161 vcf~;
4#X obj 48 191 dac~;
5#X floatatom 138 33 5 0 0 0 - - -;
6#X obj 44 18 osc~ 1;
7#X obj 46 75 *~ 800;
8#X obj 48 48 +~ 2;
9#X obj 106 125 sig~;
10#X floatatom 132 77 5 0 0 0 - - -;
11#X connect 0 0 1 0;
12#X connect 1 0 2 0;
13#X connect 1 0 2 1;
14#X connect 3 0 1 2;
15#X connect 4 0 6 0;
16#X connect 6 0 5 0;
17#X connect 7 0 1 1;
18#X connect 8 0 7 0;
19#N canvas 0 0 240 300 10;
20#X obj 38 93 noise~;
21#X obj 44 161 vcf~;
22#X obj 48 191 dac~;
23#X floatatom 138 33 5 0 0 0 - - -;
24#X obj 44 18 osc~ 1;
25#X obj 46 75 *~ 800;
26#X obj 48 48 +~ 2;
27#X obj 106 125 sig~;
28#X floatatom 132 77 5 0 0 0 - - -;
29#X connect 0 0 1 0;
30#X connect 1 0 2 0;
31#X connect 1 0 2 1;
32#X connect 3 0 1 2;
33#X connect 4 0 6 0;
34#X connect 6 0 5 0;
35#X connect 7 0 1 1;
36#X connect 8 0 7 0;
diff --git a/apps/plugins/pdbox/PDa/extra/zerox~.c b/apps/plugins/pdbox/PDa/extra/zerox~.c
new file mode 100644
index 0000000000..f97f412308
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/zerox~.c
@@ -0,0 +1,114 @@
1#include "m_pd.h"
2
3static t_class *zerox_class;
4
5typedef struct _zerox
6{
7 t_object x_obj;
8 t_sample x_f;
9 t_int x_zeros;
10} t_zerox;
11
12
13static t_int *zerox_perform(t_int *w)
14{
15 t_zerox* x = (t_zerox*)w[1];
16 t_sample *in = (t_sample *)(w[2]);
17 int n = (int)(w[3]) ;
18
19 if (*in * x->x_f < 0) x->x_zeros++;
20 n--;
21 while (n--)
22 {
23 float f = *(in++);
24 x->x_zeros += f * *in < 0;
25 }
26 return (w+4);
27}
28
29static void zerox_dsp(t_zerox *x, t_signal **sp)
30{
31 dsp_add(zerox_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
32}
33
34
35static void zerox_bang(t_zerox* x)
36{
37 outlet_float(x->x_obj.ob_outlet,x->x_zeros);
38 x->x_zeros=0;
39}
40
41static void *zerox_new(void)
42{
43 t_zerox *x = (t_zerox *)pd_new(zerox_class);
44 outlet_new(&x->x_obj, gensym("float"));
45 x->x_f = 0;
46 x->x_zeros=0;
47 return (x);
48}
49
50void zerox_tilde_setup(void)
51{
52 zerox_class = class_new(gensym("zerox~"), (t_newmethod)zerox_new, 0,
53 sizeof(t_zerox), 0, A_DEFFLOAT, 0);
54 CLASS_MAINSIGNALIN(zerox_class, t_zerox, x_f);
55 class_addmethod(zerox_class, (t_method)zerox_dsp, gensym("dsp"), 0);
56 class_addbang(zerox_class, (t_method)zerox_bang);
57}
58#include "m_pd.h"
59
60static t_class *zerox_class;
61
62typedef struct _zerox
63{
64 t_object x_obj;
65 t_sample x_f;
66 t_int x_zeros;
67} t_zerox;
68
69
70static t_int *zerox_perform(t_int *w)
71{
72 t_zerox* x = (t_zerox*)w[1];
73 t_sample *in = (t_sample *)(w[2]);
74 int n = (int)(w[3]) ;
75
76 if (*in * x->x_f < 0) x->x_zeros++;
77 n--;
78 while (n--)
79 {
80 float f = *(in++);
81 x->x_zeros += f * *in < 0;
82 }
83 return (w+4);
84}
85
86static void zerox_dsp(t_zerox *x, t_signal **sp)
87{
88 dsp_add(zerox_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
89}
90
91
92static void zerox_bang(t_zerox* x)
93{
94 outlet_float(x->x_obj.ob_outlet,x->x_zeros);
95 x->x_zeros=0;
96}
97
98static void *zerox_new(void)
99{
100 t_zerox *x = (t_zerox *)pd_new(zerox_class);
101 outlet_new(&x->x_obj, gensym("float"));
102 x->x_f = 0;
103 x->x_zeros=0;
104 return (x);
105}
106
107void zerox_tilde_setup(void)
108{
109 zerox_class = class_new(gensym("zerox~"), (t_newmethod)zerox_new, 0,
110 sizeof(t_zerox), 0, A_DEFFLOAT, 0);
111 CLASS_MAINSIGNALIN(zerox_class, t_zerox, x_f);
112 class_addmethod(zerox_class, (t_method)zerox_dsp, gensym("dsp"), 0);
113 class_addbang(zerox_class, (t_method)zerox_bang);
114}