summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/x_midi.c
diff options
context:
space:
mode:
authorPeter D'Hoye <peter.dhoye@gmail.com>2009-05-22 21:58:48 +0000
committerPeter D'Hoye <peter.dhoye@gmail.com>2009-05-22 21:58:48 +0000
commit513389b4c1bc8afe4b2dc9947c534bfeb105e3da (patch)
tree10e673b35651ac567fed2eda0c679c7ade64cbc6 /apps/plugins/pdbox/PDa/src/x_midi.c
parent95fa7f6a2ef466444fbe3fe87efc6d5db6b77b36 (diff)
downloadrockbox-513389b4c1bc8afe4b2dc9947c534bfeb105e3da.tar.gz
rockbox-513389b4c1bc8afe4b2dc9947c534bfeb105e3da.zip
Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin project of Wincent Balin. Stripped some non-sourcefiles and added a rockbox readme that needs a bit more info from Wincent. Is added to CATEGORIES and viewers, but not yet to SUBDIRS (ie doesn't build yet)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21044 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/x_midi.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/x_midi.c2626
1 files changed, 2626 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/x_midi.c b/apps/plugins/pdbox/PDa/src/x_midi.c
new file mode 100644
index 0000000000..a71000f121
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/x_midi.c
@@ -0,0 +1,2626 @@
1/* Copyright (c) 1997-2001 Miller Puckette and others.
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/* MIDI. */
6
7#include "m_pd.h"
8void outmidi_noteon(int portno, int channel, int pitch, int velo);
9void outmidi_controlchange(int portno, int channel, int ctlno, int value);
10void outmidi_programchange(int portno, int channel, int value);
11void outmidi_pitchbend(int portno, int channel, int value);
12void outmidi_aftertouch(int portno, int channel, int value);
13void outmidi_polyaftertouch(int portno, int channel, int pitch, int value);
14void outmidi_mclk(int portno);
15
16/* ----------------------- midiin and sysexin ------------------------- */
17
18static t_symbol *midiin_sym, *sysexin_sym;
19
20static t_class *midiin_class, *sysexin_class;
21
22typedef struct _midiin
23{
24 t_object x_obj;
25 t_outlet *x_outlet1;
26 t_outlet *x_outlet2;
27} t_midiin;
28
29static void *midiin_new( void)
30{
31 t_midiin *x = (t_midiin *)pd_new(midiin_class);
32 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
33 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
34 pd_bind(&x->x_obj.ob_pd, midiin_sym);
35#ifndef __linux__
36 pd_error(x, "midiin: works under Linux only");
37#endif
38 return (x);
39}
40
41static void midiin_list(t_midiin *x, t_symbol *s, int ac, t_atom *av)
42{
43 outlet_float(x->x_outlet2, atom_getfloatarg(1, ac, av) + 1);
44 outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av));
45}
46
47static void midiin_free(t_midiin *x)
48{
49 pd_unbind(&x->x_obj.ob_pd, midiin_sym);
50}
51
52static void *sysexin_new( void)
53{
54 t_midiin *x = (t_midiin *)pd_new(sysexin_class);
55 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
56 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
57 pd_bind(&x->x_obj.ob_pd, sysexin_sym);
58#ifndef __linux__
59 pd_error(x, "sysexin: works under Linux only");
60#endif
61 return (x);
62}
63
64static void sysexin_free(t_midiin *x)
65{
66 pd_unbind(&x->x_obj.ob_pd, sysexin_sym);
67}
68
69static void midiin_setup(void)
70{
71 midiin_class = class_new(gensym("midiin"), (t_newmethod)midiin_new,
72 (t_method)midiin_free, sizeof(t_midiin),
73 CLASS_NOINLET, A_DEFFLOAT, 0);
74 class_addlist(midiin_class, midiin_list);
75 class_sethelpsymbol(midiin_class, gensym("midi"));
76 midiin_sym = gensym("#midiin");
77
78 sysexin_class = class_new(gensym("sysexin"), (t_newmethod)sysexin_new,
79 (t_method)sysexin_free, sizeof(t_midiin),
80 CLASS_NOINLET, A_DEFFLOAT, 0);
81 class_addlist(sysexin_class, midiin_list);
82 class_sethelpsymbol(sysexin_class, gensym("midi"));
83 sysexin_sym = gensym("#sysexin");
84}
85
86void inmidi_byte(int portno, int byte)
87{
88 t_atom at[2];
89 if (midiin_sym->s_thing)
90 {
91 SETFLOAT(at, byte);
92 SETFLOAT(at+1, portno + 1);
93 pd_list(midiin_sym->s_thing, 0, 2, at);
94 }
95}
96
97void inmidi_sysex(int portno, int byte)
98{
99 t_atom at[2];
100 if (sysexin_sym->s_thing)
101 {
102 SETFLOAT(at, byte);
103 SETFLOAT(at+1, portno + 1);
104 pd_list(sysexin_sym->s_thing, 0, 2, at);
105 }
106}
107
108/* ----------------------- notein ------------------------- */
109
110static t_symbol *notein_sym;
111
112static t_class *notein_class;
113
114typedef struct _notein
115{
116 t_object x_obj;
117 t_float x_channel;
118 t_outlet *x_outlet1;
119 t_outlet *x_outlet2;
120 t_outlet *x_outlet3;
121} t_notein;
122
123static void *notein_new(t_floatarg f)
124{
125 t_notein *x = (t_notein *)pd_new(notein_class);
126 x->x_channel = f;
127 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
128 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
129 if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
130 pd_bind(&x->x_obj.ob_pd, notein_sym);
131 return (x);
132}
133
134static void notein_list(t_notein *x, t_symbol *s, int argc, t_atom *argv)
135{
136 float pitch = atom_getfloatarg(0, argc, argv);
137 float velo = atom_getfloatarg(1, argc, argv);
138 float channel = atom_getfloatarg(2, argc, argv);
139 if (x->x_channel != 0)
140 {
141 if (channel != x->x_channel) return;
142 outlet_float(x->x_outlet2, velo);
143 outlet_float(x->x_outlet1, pitch);
144 }
145 else
146 {
147 outlet_float(x->x_outlet3, channel);
148 outlet_float(x->x_outlet2, velo);
149 outlet_float(x->x_outlet1, pitch);
150 }
151}
152
153static void notein_free(t_notein *x)
154{
155 pd_unbind(&x->x_obj.ob_pd, notein_sym);
156}
157
158static void notein_setup(void)
159{
160 notein_class = class_new(gensym("notein"), (t_newmethod)notein_new,
161 (t_method)notein_free, sizeof(t_notein), CLASS_NOINLET, A_DEFFLOAT, 0);
162 class_addlist(notein_class, notein_list);
163 class_sethelpsymbol(notein_class, gensym("midi"));
164 notein_sym = gensym("#notein");
165}
166
167void inmidi_noteon(int portno, int channel, int pitch, int velo)
168{
169 if (notein_sym->s_thing)
170 {
171 t_atom at[3];
172 SETFLOAT(at, pitch);
173 SETFLOAT(at+1, velo);
174 SETFLOAT(at+2, (channel + (portno << 4) + 1));
175 pd_list(notein_sym->s_thing, &s_list, 3, at);
176 }
177}
178
179/* ----------------------- ctlin ------------------------- */
180
181static t_symbol *ctlin_sym;
182
183static t_class *ctlin_class;
184
185typedef struct _ctlin
186{
187 t_object x_obj;
188 t_float x_channel;
189 t_float x_ctlno;
190 t_outlet *x_outlet1;
191 t_outlet *x_outlet2;
192 t_outlet *x_outlet3;
193} t_ctlin;
194
195static void *ctlin_new(t_symbol *s, int argc, t_atom *argv)
196{
197 int ctlno, channel;
198 t_ctlin *x = (t_ctlin *)pd_new(ctlin_class);
199 if (!argc) ctlno = -1;
200 else ctlno = atom_getfloatarg(0, argc, argv);
201 channel = atom_getfloatarg(1, argc, argv);
202 x->x_channel = channel;
203 x->x_ctlno = ctlno;
204 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
205 if (!channel)
206 {
207 if (x->x_ctlno < 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
208 x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
209 }
210 pd_bind(&x->x_obj.ob_pd, ctlin_sym);
211 return (x);
212}
213
214static void ctlin_list(t_ctlin *x, t_symbol *s, int argc, t_atom *argv)
215{
216 t_float ctlnumber = atom_getfloatarg(0, argc, argv);
217 t_float value = atom_getfloatarg(1, argc, argv);
218 t_float channel = atom_getfloatarg(2, argc, argv);
219 if (x->x_ctlno >= 0 && x->x_ctlno != ctlnumber) return;
220 if (x->x_channel > 0 && x->x_channel != channel) return;
221 if (x->x_channel == 0) outlet_float(x->x_outlet3, channel);
222 if (x->x_ctlno < 0) outlet_float(x->x_outlet2, ctlnumber);
223 outlet_float(x->x_outlet1, value);
224}
225
226static void ctlin_free(t_ctlin *x)
227{
228 pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
229}
230
231static void ctlin_setup(void)
232{
233 ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new,
234 (t_method)ctlin_free, sizeof(t_ctlin),
235 CLASS_NOINLET, A_GIMME, 0);
236 class_addlist(ctlin_class, ctlin_list);
237 class_sethelpsymbol(ctlin_class, gensym("midi"));
238 ctlin_sym = gensym("#ctlin");
239}
240
241void inmidi_controlchange(int portno, int channel, int ctlnumber, int value)
242{
243 if (ctlin_sym->s_thing)
244 {
245 t_atom at[3];
246 SETFLOAT(at, ctlnumber);
247 SETFLOAT(at+1, value);
248 SETFLOAT(at+2, (channel + (portno << 4) + 1));
249 pd_list(ctlin_sym->s_thing, &s_list, 3, at);
250 }
251}
252
253/* ----------------------- pgmin ------------------------- */
254
255static t_symbol *pgmin_sym;
256
257static t_class *pgmin_class;
258
259typedef struct _pgmin
260{
261 t_object x_obj;
262 t_float x_channel;
263 t_outlet *x_outlet1;
264 t_outlet *x_outlet2;
265} t_pgmin;
266
267static void *pgmin_new(t_floatarg f)
268{
269 t_pgmin *x = (t_pgmin *)pd_new(pgmin_class);
270 x->x_channel = f;
271 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
272 if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
273 pd_bind(&x->x_obj.ob_pd, pgmin_sym);
274 return (x);
275}
276
277static void pgmin_list(t_pgmin *x, t_symbol *s, int argc, t_atom *argv)
278{
279 float value = atom_getfloatarg(0, argc, argv);
280 float channel = atom_getfloatarg(1, argc, argv);
281 if (x->x_channel != 0)
282 {
283 if (channel != x->x_channel) return;
284 outlet_float(x->x_outlet1, value);
285 }
286 else
287 {
288 outlet_float(x->x_outlet2, channel);
289 outlet_float(x->x_outlet1, value);
290 }
291}
292
293static void pgmin_free(t_pgmin *x)
294{
295 pd_unbind(&x->x_obj.ob_pd, pgmin_sym);
296}
297
298static void pgmin_setup(void)
299{
300 pgmin_class = class_new(gensym("pgmin"), (t_newmethod)pgmin_new,
301 (t_method)pgmin_free, sizeof(t_pgmin),
302 CLASS_NOINLET, A_DEFFLOAT, 0);
303 class_addlist(pgmin_class, pgmin_list);
304 class_sethelpsymbol(pgmin_class, gensym("midi"));
305 pgmin_sym = gensym("#pgmin");
306}
307
308void inmidi_programchange(int portno, int channel, int value)
309{
310 if (pgmin_sym->s_thing)
311 {
312 t_atom at[2];
313 SETFLOAT(at, value + 1);
314 SETFLOAT(at+1, (channel + (portno << 4) + 1));
315 pd_list(pgmin_sym->s_thing, &s_list, 2, at);
316 }
317}
318
319/* ----------------------- bendin ------------------------- */
320
321static t_symbol *bendin_sym;
322
323static t_class *bendin_class;
324
325typedef struct _bendin
326{
327 t_object x_obj;
328 t_float x_channel;
329 t_outlet *x_outlet1;
330 t_outlet *x_outlet2;
331} t_bendin;
332
333static void *bendin_new(t_floatarg f)
334{
335 t_bendin *x = (t_bendin *)pd_new(bendin_class);
336 x->x_channel = f;
337 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
338 if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
339 pd_bind(&x->x_obj.ob_pd, bendin_sym);
340 return (x);
341}
342
343static void bendin_list(t_bendin *x, t_symbol *s, int argc, t_atom *argv)
344{
345 t_float value = atom_getfloatarg(0, argc, argv);
346 t_float channel = atom_getfloatarg(1, argc, argv);
347 if (x->x_channel != 0)
348 {
349 if (channel != x->x_channel) return;
350 outlet_float(x->x_outlet1, value);
351 }
352 else
353 {
354 outlet_float(x->x_outlet2, channel);
355 outlet_float(x->x_outlet1, value);
356 }
357}
358
359static void bendin_free(t_bendin *x)
360{
361 pd_unbind(&x->x_obj.ob_pd, bendin_sym);
362}
363
364static void bendin_setup(void)
365{
366 bendin_class = class_new(gensym("bendin"), (t_newmethod)bendin_new,
367 (t_method)bendin_free, sizeof(t_bendin), CLASS_NOINLET, A_DEFFLOAT, 0);
368 class_addlist(bendin_class, bendin_list);
369 class_sethelpsymbol(bendin_class, gensym("midi"));
370 bendin_sym = gensym("#bendin");
371}
372
373void inmidi_pitchbend(int portno, int channel, int value)
374{
375 if (bendin_sym->s_thing)
376 {
377 t_atom at[2];
378 SETFLOAT(at, value);
379 SETFLOAT(at+1, (channel + (portno << 4) + 1));
380 pd_list(bendin_sym->s_thing, &s_list, 2, at);
381 }
382}
383
384/* ----------------------- touchin ------------------------- */
385
386static t_symbol *touchin_sym;
387
388static t_class *touchin_class;
389
390typedef struct _touchin
391{
392 t_object x_obj;
393 t_float x_channel;
394 t_outlet *x_outlet1;
395 t_outlet *x_outlet2;
396} t_touchin;
397
398static void *touchin_new(t_floatarg f)
399{
400 t_touchin *x = (t_touchin *)pd_new(touchin_class);
401 x->x_channel = f;
402 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
403 if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
404 pd_bind(&x->x_obj.ob_pd, touchin_sym);
405 return (x);
406}
407
408static void touchin_list(t_touchin *x, t_symbol *s, int argc, t_atom *argv)
409{
410 t_float value = atom_getfloatarg(0, argc, argv);
411 t_float channel = atom_getfloatarg(1, argc, argv);
412 if (x->x_channel)
413 {
414 if (channel != x->x_channel) return;
415 outlet_float(x->x_outlet1, value);
416 }
417 else
418 {
419 outlet_float(x->x_outlet2, channel);
420 outlet_float(x->x_outlet1, value);
421 }
422}
423
424static void touchin_free(t_touchin *x)
425{
426 pd_unbind(&x->x_obj.ob_pd, touchin_sym);
427}
428
429static void touchin_setup(void)
430{
431 touchin_class = class_new(gensym("touchin"), (t_newmethod)touchin_new,
432 (t_method)touchin_free, sizeof(t_touchin),
433 CLASS_NOINLET, A_DEFFLOAT, 0);
434 class_addlist(touchin_class, touchin_list);
435 class_sethelpsymbol(touchin_class, gensym("midi"));
436 touchin_sym = gensym("#touchin");
437}
438
439void inmidi_aftertouch(int portno, int channel, int value)
440{
441 if (touchin_sym->s_thing)
442 {
443 t_atom at[2];
444 SETFLOAT(at, value);
445 SETFLOAT(at+1, (channel + (portno << 4) + 1));
446 pd_list(touchin_sym->s_thing, &s_list, 2, at);
447 }
448}
449
450/* ----------------------- polytouchin ------------------------- */
451
452static t_symbol *polytouchin_sym;
453
454static t_class *polytouchin_class;
455
456typedef struct _polytouchin
457{
458 t_object x_obj;
459 t_float x_channel;
460 t_outlet *x_outlet1;
461 t_outlet *x_outlet2;
462 t_outlet *x_outlet3;
463} t_polytouchin;
464
465static void *polytouchin_new(t_floatarg f)
466{
467 t_polytouchin *x = (t_polytouchin *)pd_new(polytouchin_class);
468 x->x_channel = f;
469 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
470 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
471 if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
472 pd_bind(&x->x_obj.ob_pd, polytouchin_sym);
473 return (x);
474}
475
476static void polytouchin_list(t_polytouchin *x, t_symbol *s, int argc,
477 t_atom *argv)
478{
479 t_float pitch = atom_getfloatarg(0, argc, argv);
480 t_float value = atom_getfloatarg(1, argc, argv);
481 t_float channel = atom_getfloatarg(2, argc, argv);
482 if (x->x_channel != 0)
483 {
484 if (channel != x->x_channel) return;
485 outlet_float(x->x_outlet2, pitch);
486 outlet_float(x->x_outlet1, value);
487 }
488 else
489 {
490 outlet_float(x->x_outlet3, channel);
491 outlet_float(x->x_outlet2, pitch);
492 outlet_float(x->x_outlet1, value);
493 }
494}
495
496static void polytouchin_free(t_polytouchin *x)
497{
498 pd_unbind(&x->x_obj.ob_pd, polytouchin_sym);
499}
500
501static void polytouchin_setup(void)
502{
503 polytouchin_class = class_new(gensym("polytouchin"),
504 (t_newmethod)polytouchin_new, (t_method)polytouchin_free,
505 sizeof(t_polytouchin), CLASS_NOINLET, A_DEFFLOAT, 0);
506 class_addlist(polytouchin_class, polytouchin_list);
507 class_sethelpsymbol(polytouchin_class, gensym("midi"));
508 polytouchin_sym = gensym("#polytouchin");
509}
510
511void inmidi_polyaftertouch(int portno, int channel, int pitch, int value)
512{
513 if (polytouchin_sym->s_thing)
514 {
515 t_atom at[3];
516 SETFLOAT(at, pitch);
517 SETFLOAT(at+1, value);
518 SETFLOAT(at+2, (channel + (portno << 4) + 1));
519 pd_list(polytouchin_sym->s_thing, &s_list, 3, at);
520 }
521}
522
523/*----------------------- midiclkin--(midi F8 message )---------------------*/
524static t_symbol *midiclkin_sym;
525
526static t_class *midiclkin_class;
527
528
529typedef struct _midiclkin
530{
531 t_object x_obj;
532 t_outlet *x_outlet1;
533 t_outlet *x_outlet2;
534} t_midiclkin;
535
536static void *midiclkin_new(t_floatarg f)
537{
538 t_midiclkin *x = (t_midiclkin *)pd_new(midiclkin_class);
539 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
540 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
541 pd_bind(&x->x_obj.ob_pd, midiclkin_sym);
542 return (x);
543}
544
545static void midiclkin_list(t_midiclkin *x, t_symbol *s, int argc, t_atom *argv)
546{
547 float value = atom_getfloatarg(0, argc, argv);
548 float count = atom_getfloatarg(1, argc, argv);
549 outlet_float(x->x_outlet2, count);
550 outlet_float(x->x_outlet1, value);
551}
552
553static void midiclkin_free(t_midiclkin *x)
554{
555 pd_unbind(&x->x_obj.ob_pd, midiclkin_sym);
556}
557
558static void midiclkin_setup(void)
559{
560 midiclkin_class = class_new(gensym("midiclkin"),
561 (t_newmethod)midiclkin_new, (t_method)midiclkin_free,
562 sizeof(t_midiclkin), CLASS_NOINLET, A_DEFFLOAT, 0);
563 class_addlist(midiclkin_class, midiclkin_list);
564 class_sethelpsymbol(midiclkin_class, gensym("midi"));
565 midiclkin_sym = gensym("#midiclkin");
566}
567
568void inmidi_clk(double timing)
569{
570
571 static float prev = 0;
572 static float count = 0;
573 float cur,diff;
574
575 if (midiclkin_sym->s_thing)
576 {
577 t_atom at[2];
578 diff =timing - prev;
579 count++;
580
581 if (count == 3)
582 { /* 24 count per quoter note */
583 SETFLOAT(at, 1 );
584 count = 0;
585 }
586 else SETFLOAT(at, 0);
587
588 SETFLOAT(at+1, diff);
589 pd_list(midiclkin_sym->s_thing, &s_list, 2, at);
590 prev = timing;
591 }
592}
593
594/*----------midirealtimein (midi FA,FB,FC,FF message )-----------------*/
595
596static t_symbol *midirealtimein_sym;
597
598static t_class *midirealtimein_class;
599
600typedef struct _midirealtimein
601{
602 t_object x_obj;
603 t_outlet *x_outlet1;
604 t_outlet *x_outlet2;
605} t_midirealtimein;
606
607static void *midirealtimein_new( void)
608{
609 t_midirealtimein *x = (t_midirealtimein *)pd_new(midirealtimein_class);
610 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
611 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
612 pd_bind(&x->x_obj.ob_pd, midirealtimein_sym);
613#ifndef MSW
614 pd_error(x, "midirealtimein: works under MSW only");
615#endif
616 return (x);
617}
618
619static void midirealtimein_list(t_midirealtimein *x, t_symbol *s,
620 int argc, t_atom *argv)
621{
622 float portno = atom_getfloatarg(0, argc, argv);
623 float byte = atom_getfloatarg(1, argc, argv);
624
625 outlet_float(x->x_outlet2, portno);
626 outlet_float(x->x_outlet1, byte);
627}
628
629static void midirealtimein_free(t_midirealtimein *x)
630{
631 pd_unbind(&x->x_obj.ob_pd, midirealtimein_sym);
632}
633
634static void midirealtimein_setup(void)
635{
636 midirealtimein_class = class_new(gensym("midirealtimein"),
637 (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free,
638 sizeof(t_midirealtimein), CLASS_NOINLET, A_DEFFLOAT, 0);
639 class_addlist(midirealtimein_class, midirealtimein_list);
640 class_sethelpsymbol(midirealtimein_class, gensym("midi"));
641 midirealtimein_sym = gensym("#midirealtimein");
642}
643
644void inmidi_realtimein(int portno, int SysMsg)
645{
646 if (midirealtimein_sym->s_thing)
647 {
648 t_atom at[2];
649 SETFLOAT(at, portno);
650 SETFLOAT(at+1, SysMsg);
651 pd_list(midirealtimein_sym->s_thing, &s_list, 1, at);
652 }
653}
654
655/* -------------------------- midiout -------------------------- */
656
657static t_class *midiout_class;
658
659void sys_putmidibyte(int portno, int byte);
660
661typedef struct _midiout
662{
663 t_object x_obj;
664 t_float x_portno;
665} t_midiout;
666
667static void *midiout_new(t_floatarg portno)
668{
669 t_midiout *x = (t_midiout *)pd_new(midiout_class);
670 if (portno <= 0) portno = 1;
671 x->x_portno = portno;
672 floatinlet_new(&x->x_obj, &x->x_portno);
673#ifdef __irix__
674 post("midiout: unimplemented in IRIX");
675#endif
676 return (x);
677}
678
679static void midiout_float(t_midiout *x, t_floatarg f)
680{
681 sys_putmidibyte(x->x_portno - 1, f);
682}
683
684static void midiout_setup(void)
685{
686 midiout_class = class_new(gensym("midiout"), (t_newmethod)midiout_new, 0,
687 sizeof(t_midiout), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
688 class_addfloat(midiout_class, midiout_float);
689 class_sethelpsymbol(midiout_class, gensym("midi"));
690}
691
692/* -------------------------- noteout -------------------------- */
693
694static t_class *noteout_class;
695
696typedef struct _noteout
697{
698 t_object x_obj;
699 t_float x_velo;
700 t_float x_channel;
701} t_noteout;
702
703static void *noteout_new(t_floatarg channel)
704{
705 t_noteout *x = (t_noteout *)pd_new(noteout_class);
706 x->x_velo = 0;
707 if (channel < 1) channel = 1;
708 x->x_channel = channel;
709 floatinlet_new(&x->x_obj, &x->x_velo);
710 floatinlet_new(&x->x_obj, &x->x_channel);
711 return (x);
712}
713
714static void noteout_float(t_noteout *x, t_float f)
715{
716 int binchan = x->x_channel - 1;
717 if (binchan < 0)
718 binchan = 0;
719 outmidi_noteon((binchan >> 4),
720 (binchan & 15), (int)f, (int)x->x_velo);
721}
722
723static void noteout_setup(void)
724{
725 noteout_class = class_new(gensym("noteout"), (t_newmethod)noteout_new, 0,
726 sizeof(t_noteout), 0, A_DEFFLOAT, 0);
727 class_addfloat(noteout_class, noteout_float);
728 class_sethelpsymbol(noteout_class, gensym("midi"));
729}
730
731
732/* -------------------------- ctlout -------------------------- */
733
734static t_class *ctlout_class;
735
736typedef struct _ctlout
737{
738 t_object x_obj;
739 t_float x_ctl;
740 t_float x_channel;
741} t_ctlout;
742
743static void *ctlout_new(t_floatarg ctl, t_floatarg channel)
744{
745 t_ctlout *x = (t_ctlout *)pd_new(ctlout_class);
746 x->x_ctl = ctl;
747 if (channel <= 0) channel = 1;
748 x->x_channel = channel;
749 floatinlet_new(&x->x_obj, &x->x_ctl);
750 floatinlet_new(&x->x_obj, &x->x_channel);
751 return (x);
752}
753
754static void ctlout_float(t_ctlout *x, t_float f)
755{
756 int binchan = x->x_channel - 1;
757 if (binchan < 0)
758 binchan = 0;
759 outmidi_controlchange((binchan >> 4),
760 (binchan & 15), (int)(x->x_ctl), (int)f);
761}
762
763static void ctlout_setup(void)
764{
765 ctlout_class = class_new(gensym("ctlout"), (t_newmethod)ctlout_new, 0,
766 sizeof(t_ctlout), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
767 class_addfloat(ctlout_class, ctlout_float);
768 class_sethelpsymbol(ctlout_class, gensym("midi"));
769}
770
771
772/* -------------------------- pgmout -------------------------- */
773
774static t_class *pgmout_class;
775
776typedef struct _pgmout
777{
778 t_object x_obj;
779 t_float x_channel;
780} t_pgmout;
781
782static void *pgmout_new(t_floatarg channel)
783{
784 t_pgmout *x = (t_pgmout *)pd_new(pgmout_class);
785 if (channel <= 0) channel = 1;
786 x->x_channel = channel;
787 floatinlet_new(&x->x_obj, &x->x_channel);
788 return (x);
789}
790
791static void pgmout_float(t_pgmout *x, t_floatarg f)
792{
793 int binchan = x->x_channel - 1;
794 int n = f - 1;
795 if (binchan < 0)
796 binchan = 0;
797 if (n < 0) n = 0;
798 else if (n > 127) n = 127;
799 outmidi_programchange((binchan >> 4),
800 (binchan & 15), n);
801}
802
803static void pgmout_setup(void)
804{
805 pgmout_class = class_new(gensym("pgmout"), (t_newmethod)pgmout_new, 0,
806 sizeof(t_pgmout), 0, A_DEFFLOAT, 0);
807 class_addfloat(pgmout_class, pgmout_float);
808 class_sethelpsymbol(pgmout_class, gensym("midi"));
809}
810
811
812/* -------------------------- bendout -------------------------- */
813
814static t_class *bendout_class;
815
816typedef struct _bendout
817{
818 t_object x_obj;
819 t_float x_channel;
820} t_bendout;
821
822static void *bendout_new(t_floatarg channel)
823{
824 t_bendout *x = (t_bendout *)pd_new(bendout_class);
825 if (channel <= 0) channel = 1;
826 x->x_channel = channel;
827 floatinlet_new(&x->x_obj, &x->x_channel);
828 return (x);
829}
830
831static void bendout_float(t_bendout *x, t_float f)
832{
833 int binchan = x->x_channel - 1;
834 int n = (int)f + 8192;
835 if (binchan < 0)
836 binchan = 0;
837 outmidi_pitchbend((binchan >> 4), (binchan & 15), n);
838}
839
840static void bendout_setup(void)
841{
842 bendout_class = class_new(gensym("bendout"), (t_newmethod)bendout_new, 0,
843 sizeof(t_bendout), 0, A_DEFFLOAT, 0);
844 class_addfloat(bendout_class, bendout_float);
845 class_sethelpsymbol(bendout_class, gensym("midi"));
846}
847
848/* -------------------------- touch -------------------------- */
849
850static t_class *touchout_class;
851
852typedef struct _touchout
853{
854 t_object x_obj;
855 t_float x_channel;
856} t_touchout;
857
858static void *touchout_new(t_floatarg channel)
859{
860 t_touchout *x = (t_touchout *)pd_new(touchout_class);
861 if (channel <= 0) channel = 1;
862 x->x_channel = channel;
863 floatinlet_new(&x->x_obj, &x->x_channel);
864 return (x);
865}
866
867static void touchout_float(t_touchout *x, t_float f)
868{
869 int binchan = x->x_channel - 1;
870 if (binchan < 0)
871 binchan = 0;
872 outmidi_aftertouch((binchan >> 4), (binchan & 15), (int)f);
873}
874
875static void touchout_setup(void)
876{
877 touchout_class = class_new(gensym("touchout"), (t_newmethod)touchout_new, 0,
878 sizeof(t_touchout), 0, A_DEFFLOAT, 0);
879 class_addfloat(touchout_class, touchout_float);
880 class_sethelpsymbol(touchout_class, gensym("midi"));
881}
882
883/* -------------------------- polytouch -------------------------- */
884
885static t_class *polytouchout_class;
886
887typedef struct _polytouchout
888{
889 t_object x_obj;
890 t_float x_channel;
891 t_float x_pitch;
892} t_polytouchout;
893
894static void *polytouchout_new(t_floatarg channel)
895{
896 t_polytouchout *x = (t_polytouchout *)pd_new(polytouchout_class);
897 if (channel <= 0) channel = 1;
898 x->x_channel = channel;
899 x->x_pitch = 0;
900 floatinlet_new(&x->x_obj, &x->x_pitch);
901 floatinlet_new(&x->x_obj, &x->x_channel);
902 return (x);
903}
904
905static void polytouchout_float(t_polytouchout *x, t_float n)
906{
907 int binchan = x->x_channel - 1;
908 if (binchan < 0)
909 binchan = 0;
910 outmidi_polyaftertouch((binchan >> 4), (binchan & 15), x->x_pitch, n);
911}
912
913static void polytouchout_setup(void)
914{
915 polytouchout_class = class_new(gensym("polytouchout"),
916 (t_newmethod)polytouchout_new, 0,
917 sizeof(t_polytouchout), 0, A_DEFFLOAT, 0);
918 class_addfloat(polytouchout_class, polytouchout_float);
919 class_sethelpsymbol(polytouchout_class, gensym("midi"));
920}
921
922/* -------------------------- makenote -------------------------- */
923
924static t_class *makenote_class;
925
926typedef struct _hang
927{
928 t_clock *h_clock;
929 struct _hang *h_next;
930 t_float h_pitch;
931 struct _makenote *h_owner;
932} t_hang;
933
934typedef struct _makenote
935{
936 t_object x_obj;
937 t_float x_velo;
938 t_float x_dur;
939 t_outlet *x_pitchout;
940 t_outlet *x_velout;
941 t_hang *x_hang;
942} t_makenote;
943
944static void *makenote_new(t_floatarg velo, t_floatarg dur)
945{
946 t_makenote *x = (t_makenote *)pd_new(makenote_class);
947 x->x_velo = velo;
948 x->x_dur = dur;
949 floatinlet_new(&x->x_obj, &x->x_velo);
950 floatinlet_new(&x->x_obj, &x->x_dur);
951 x->x_pitchout = outlet_new(&x->x_obj, &s_float);
952 x->x_velout = outlet_new(&x->x_obj, &s_float);
953 x->x_hang = 0;
954 return (x);
955}
956
957static void makenote_tick(t_hang *hang)
958{
959 t_makenote *x = hang->h_owner;
960 t_hang *h2, *h3;
961 outlet_float(x->x_velout, 0);
962 outlet_float(x->x_pitchout, hang->h_pitch);
963 if (x->x_hang == hang) x->x_hang = hang->h_next;
964 else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3)
965 {
966 if (h3 == hang)
967 {
968 h2->h_next = h3->h_next;
969 break;
970 }
971 }
972 clock_free(hang->h_clock);
973 freebytes(hang, sizeof(*hang));
974}
975
976static void makenote_float(t_makenote *x, t_float f)
977{
978 t_hang *hang;
979 if (!x->x_velo) return;
980 outlet_float(x->x_velout, x->x_velo);
981 outlet_float(x->x_pitchout, f);
982 hang = (t_hang *)getbytes(sizeof *hang);
983 hang->h_next = x->x_hang;
984 x->x_hang = hang;
985 hang->h_pitch = f;
986 hang->h_owner = x;
987 hang->h_clock = clock_new(hang, (t_method)makenote_tick);
988 clock_delay(hang->h_clock, (x->x_dur >= 0 ? x->x_dur : 0));
989}
990
991static void makenote_stop(t_makenote *x)
992{
993 t_hang *hang;
994 while (hang = x->x_hang)
995 {
996 outlet_float(x->x_velout, 0);
997 outlet_float(x->x_pitchout, hang->h_pitch);
998 x->x_hang = hang->h_next;
999 clock_free(hang->h_clock);
1000 freebytes(hang, sizeof(*hang));
1001 }
1002}
1003
1004static void makenote_clear(t_makenote *x)
1005{
1006 t_hang *hang;
1007 while (hang = x->x_hang)
1008 {
1009 x->x_hang = hang->h_next;
1010 clock_free(hang->h_clock);
1011 freebytes(hang, sizeof(*hang));
1012 }
1013}
1014
1015static void makenote_setup(void)
1016{
1017 makenote_class = class_new(gensym("makenote"),
1018 (t_newmethod)makenote_new, (t_method)makenote_clear,
1019 sizeof(t_makenote), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
1020 class_addfloat(makenote_class, makenote_float);
1021 class_addmethod(makenote_class, (t_method)makenote_stop, gensym("stop"),
1022 0);
1023 class_addmethod(makenote_class, (t_method)makenote_clear, gensym("clear"),
1024 0);
1025}
1026
1027/* -------------------------- stripnote -------------------------- */
1028
1029static t_class *stripnote_class;
1030
1031typedef struct _stripnote
1032{
1033 t_object x_obj;
1034 t_float x_velo;
1035 t_outlet *x_pitchout;
1036 t_outlet *x_velout;
1037} t_stripnote;
1038
1039static void *stripnote_new(void )
1040{
1041 t_stripnote *x = (t_stripnote *)pd_new(stripnote_class);
1042 floatinlet_new(&x->x_obj, &x->x_velo);
1043 x->x_pitchout = outlet_new(&x->x_obj, &s_float);
1044 x->x_velout = outlet_new(&x->x_obj, &s_float);
1045 return (x);
1046}
1047
1048static void stripnote_float(t_stripnote *x, t_float f)
1049{
1050 t_hang *hang;
1051 if (!x->x_velo) return;
1052 outlet_float(x->x_velout, x->x_velo);
1053 outlet_float(x->x_pitchout, f);
1054}
1055
1056static void stripnote_setup(void)
1057{
1058 stripnote_class = class_new(gensym("stripnote"),
1059 (t_newmethod)stripnote_new, 0, sizeof(t_stripnote), 0, 0);
1060 class_addfloat(stripnote_class, stripnote_float);
1061}
1062
1063/* -------------------------- poly -------------------------- */
1064
1065static t_class *poly_class;
1066
1067typedef struct voice
1068{
1069 float v_pitch;
1070 int v_used;
1071 unsigned long v_serial;
1072} t_voice;
1073
1074typedef struct poly
1075{
1076 t_object x_obj;
1077 int x_n;
1078 t_voice *x_vec;
1079 float x_vel;
1080 t_outlet *x_pitchout;
1081 t_outlet *x_velout;
1082 unsigned long x_serial;
1083 int x_steal;
1084} t_poly;
1085
1086static void *poly_new(float fnvoice, float fsteal)
1087{
1088 int i, n = fnvoice;
1089 t_poly *x = (t_poly *)pd_new(poly_class);
1090 t_voice *v;
1091 if (n < 1) n = 1;
1092 x->x_n = n;
1093 x->x_vec = (t_voice *)getbytes(n * sizeof(*x->x_vec));
1094 for (v = x->x_vec, i = n; i--; v++)
1095 v->v_pitch = v->v_used = v->v_serial = 0;
1096 x->x_vel = 0;
1097 x->x_steal = (fsteal != 0);
1098 floatinlet_new(&x->x_obj, &x->x_vel);
1099 outlet_new(&x->x_obj, &s_float);
1100 x->x_pitchout = outlet_new(&x->x_obj, &s_float);
1101 x->x_velout = outlet_new(&x->x_obj, &s_float);
1102 x->x_serial = 0;
1103 return (x);
1104}
1105
1106static void poly_float(t_poly *x, t_float f)
1107{
1108 int i;
1109 t_voice *v;
1110 t_voice *firston, *firstoff;
1111 unsigned int serialon, serialoff, onindex = 0, offindex = 0;
1112 if (x->x_vel > 0)
1113 {
1114 /* note on. Look for a vacant voice */
1115 for (v = x->x_vec, i = 0, firston = firstoff = 0,
1116 serialon = serialoff = 0xffffffff; i < x->x_n; v++, i++)
1117 {
1118 if (v->v_used && v->v_serial < serialon)
1119 firston = v, serialon = v->v_serial, onindex = i;
1120 else if (!v->v_used && v->v_serial < serialoff)
1121 firstoff = v, serialoff = v->v_serial, offindex = i;
1122 }
1123 if (firstoff)
1124 {
1125 outlet_float(x->x_velout, x->x_vel);
1126 outlet_float(x->x_pitchout, firstoff->v_pitch = f);
1127 outlet_float(x->x_obj.ob_outlet, offindex+1);
1128 firstoff->v_used = 1;
1129 firstoff->v_serial = x->x_serial++;
1130 }
1131 /* if none, steal one */
1132 else if (firston && x->x_steal)
1133 {
1134 outlet_float(x->x_velout, 0);
1135 outlet_float(x->x_pitchout, firston->v_pitch);
1136 outlet_float(x->x_obj.ob_outlet, onindex+1);
1137 outlet_float(x->x_velout, x->x_vel);
1138 outlet_float(x->x_pitchout, firston->v_pitch = f);
1139 outlet_float(x->x_obj.ob_outlet, onindex+1);
1140 firston->v_serial = x->x_serial++;
1141 }
1142 }
1143 else /* note off. Turn off oldest match */
1144 {
1145 for (v = x->x_vec, i = 0, firston = 0, serialon = 0xffffffff;
1146 i < x->x_n; v++, i++)
1147 if (v->v_used && v->v_pitch == f && v->v_serial < serialon)
1148 firston = v, serialon = v->v_serial, onindex = i;
1149 if (firston)
1150 {
1151 firston->v_used = 0;
1152 firston->v_serial = x->x_serial++;
1153 outlet_float(x->x_velout, 0);
1154 outlet_float(x->x_pitchout, firston->v_pitch);
1155 outlet_float(x->x_obj.ob_outlet, onindex+1);
1156 }
1157 }
1158}
1159
1160static void poly_stop(t_poly *x)
1161{
1162 int i;
1163 t_voice *v;
1164 for (i = 0, v = x->x_vec; i < x->x_n; i++, v++)
1165 if (v->v_used)
1166 {
1167 outlet_float(x->x_velout, 0L);
1168 outlet_float(x->x_pitchout, v->v_pitch);
1169 outlet_float(x->x_obj.ob_outlet, i+1);
1170 v->v_used = 0;
1171 v->v_serial = x->x_serial++;
1172 }
1173}
1174
1175static void poly_clear(t_poly *x)
1176{
1177 int i;
1178 t_voice *v;
1179 for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0;
1180}
1181
1182static void poly_free(t_poly *x)
1183{
1184 freebytes(x->x_vec, x->x_n * sizeof (*x->x_vec));
1185}
1186
1187static void poly_setup(void)
1188{
1189 poly_class = class_new(gensym("poly"),
1190 (t_newmethod)poly_new, (t_method)poly_clear,
1191 sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
1192 class_addfloat(poly_class, poly_float);
1193 class_addmethod(poly_class, (t_method)poly_stop, gensym("stop"), 0);
1194 class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), 0);
1195}
1196
1197/* -------------------------- bag -------------------------- */
1198
1199static t_class *bag_class;
1200
1201typedef struct _bagelem
1202{
1203 struct _bagelem *e_next;
1204 t_float e_value;
1205} t_bagelem;
1206
1207typedef struct _bag
1208{
1209 t_object x_obj;
1210 t_float x_velo;
1211 t_bagelem *x_first;
1212} t_bag;
1213
1214static void *bag_new(void )
1215{
1216 t_bag *x = (t_bag *)pd_new(bag_class);
1217 x->x_velo = 0;
1218 floatinlet_new(&x->x_obj, &x->x_velo);
1219 outlet_new(&x->x_obj, &s_float);
1220 x->x_first = 0;
1221 return (x);
1222}
1223
1224static void bag_float(t_bag *x, t_float f)
1225{
1226 t_bagelem *bagelem, *e2, *e3;
1227 if (x->x_velo != 0)
1228 {
1229 bagelem = (t_bagelem *)getbytes(sizeof *bagelem);
1230 bagelem->e_next = 0;
1231 bagelem->e_value = f;
1232 if (!x->x_first) x->x_first = bagelem;
1233 else /* LATER replace with a faster algorithm */
1234 {
1235 for (e2 = x->x_first; e3 = e2->e_next; e2 = e3)
1236 ;
1237 e2->e_next = bagelem;
1238 }
1239 }
1240 else
1241 {
1242 if (!x->x_first) return;
1243 if (x->x_first->e_value == f)
1244 {
1245 bagelem = x->x_first;
1246 x->x_first = x->x_first->e_next;
1247 freebytes(bagelem, sizeof(*bagelem));
1248 return;
1249 }
1250 for (e2 = x->x_first; e3 = e2->e_next; e2 = e3)
1251 if (e3->e_value == f)
1252 {
1253 e2->e_next = e3->e_next;
1254 freebytes(e3, sizeof(*e3));
1255 return;
1256 }
1257 }
1258}
1259
1260static void bag_flush(t_bag *x)
1261{
1262 t_bagelem *bagelem;
1263 while (bagelem = x->x_first)
1264 {
1265 outlet_float(x->x_obj.ob_outlet, bagelem->e_value);
1266 x->x_first = bagelem->e_next;
1267 freebytes(bagelem, sizeof(*bagelem));
1268 }
1269}
1270
1271static void bag_clear(t_bag *x)
1272{
1273 t_bagelem *bagelem;
1274 while (bagelem = x->x_first)
1275 {
1276 x->x_first = bagelem->e_next;
1277 freebytes(bagelem, sizeof(*bagelem));
1278 }
1279}
1280
1281static void bag_setup(void)
1282{
1283 bag_class = class_new(gensym("bag"),
1284 (t_newmethod)bag_new, (t_method)bag_clear,
1285 sizeof(t_bag), 0, 0);
1286 class_addfloat(bag_class, bag_float);
1287 class_addmethod(bag_class, (t_method)bag_flush, gensym("flush"), 0);
1288 class_addmethod(bag_class, (t_method)bag_clear, gensym("clear"), 0);
1289}
1290
1291void x_midi_setup(void)
1292{
1293 midiin_setup();
1294 midirealtimein_setup();
1295 notein_setup();
1296 ctlin_setup();
1297 pgmin_setup();
1298 bendin_setup();
1299 touchin_setup();
1300 polytouchin_setup();
1301 midiclkin_setup();
1302 midiout_setup();
1303 noteout_setup();
1304 ctlout_setup();
1305 pgmout_setup();
1306 bendout_setup();
1307 touchout_setup();
1308 polytouchout_setup();
1309 makenote_setup();
1310 stripnote_setup();
1311 poly_setup();
1312 bag_setup();
1313}
1314/* Copyright (c) 1997-2001 Miller Puckette and others.
1315* For information on usage and redistribution, and for a DISCLAIMER OF ALL
1316* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1317
1318/* MIDI. */
1319
1320#include "m_pd.h"
1321void outmidi_noteon(int portno, int channel, int pitch, int velo);
1322void outmidi_controlchange(int portno, int channel, int ctlno, int value);
1323void outmidi_programchange(int portno, int channel, int value);
1324void outmidi_pitchbend(int portno, int channel, int value);
1325void outmidi_aftertouch(int portno, int channel, int value);
1326void outmidi_polyaftertouch(int portno, int channel, int pitch, int value);
1327void outmidi_mclk(int portno);
1328
1329/* ----------------------- midiin and sysexin ------------------------- */
1330
1331static t_symbol *midiin_sym, *sysexin_sym;
1332
1333static t_class *midiin_class, *sysexin_class;
1334
1335typedef struct _midiin
1336{
1337 t_object x_obj;
1338 t_outlet *x_outlet1;
1339 t_outlet *x_outlet2;
1340} t_midiin;
1341
1342static void *midiin_new( void)
1343{
1344 t_midiin *x = (t_midiin *)pd_new(midiin_class);
1345 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1346 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1347 pd_bind(&x->x_obj.ob_pd, midiin_sym);
1348#ifndef __linux__
1349 pd_error(x, "midiin: works under Linux only");
1350#endif
1351 return (x);
1352}
1353
1354static void midiin_list(t_midiin *x, t_symbol *s, int ac, t_atom *av)
1355{
1356 outlet_float(x->x_outlet2, atom_getfloatarg(1, ac, av) + 1);
1357 outlet_float(x->x_outlet1, atom_getfloatarg(0, ac, av));
1358}
1359
1360static void midiin_free(t_midiin *x)
1361{
1362 pd_unbind(&x->x_obj.ob_pd, midiin_sym);
1363}
1364
1365static void *sysexin_new( void)
1366{
1367 t_midiin *x = (t_midiin *)pd_new(sysexin_class);
1368 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1369 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1370 pd_bind(&x->x_obj.ob_pd, sysexin_sym);
1371#ifndef __linux__
1372 pd_error(x, "sysexin: works under Linux only");
1373#endif
1374 return (x);
1375}
1376
1377static void sysexin_free(t_midiin *x)
1378{
1379 pd_unbind(&x->x_obj.ob_pd, sysexin_sym);
1380}
1381
1382static void midiin_setup(void)
1383{
1384 midiin_class = class_new(gensym("midiin"), (t_newmethod)midiin_new,
1385 (t_method)midiin_free, sizeof(t_midiin),
1386 CLASS_NOINLET, A_DEFFLOAT, 0);
1387 class_addlist(midiin_class, midiin_list);
1388 class_sethelpsymbol(midiin_class, gensym("midi"));
1389 midiin_sym = gensym("#midiin");
1390
1391 sysexin_class = class_new(gensym("sysexin"), (t_newmethod)sysexin_new,
1392 (t_method)sysexin_free, sizeof(t_midiin),
1393 CLASS_NOINLET, A_DEFFLOAT, 0);
1394 class_addlist(sysexin_class, midiin_list);
1395 class_sethelpsymbol(sysexin_class, gensym("midi"));
1396 sysexin_sym = gensym("#sysexin");
1397}
1398
1399void inmidi_byte(int portno, int byte)
1400{
1401 t_atom at[2];
1402 if (midiin_sym->s_thing)
1403 {
1404 SETFLOAT(at, byte);
1405 SETFLOAT(at+1, portno + 1);
1406 pd_list(midiin_sym->s_thing, 0, 2, at);
1407 }
1408}
1409
1410void inmidi_sysex(int portno, int byte)
1411{
1412 t_atom at[2];
1413 if (sysexin_sym->s_thing)
1414 {
1415 SETFLOAT(at, byte);
1416 SETFLOAT(at+1, portno + 1);
1417 pd_list(sysexin_sym->s_thing, 0, 2, at);
1418 }
1419}
1420
1421/* ----------------------- notein ------------------------- */
1422
1423static t_symbol *notein_sym;
1424
1425static t_class *notein_class;
1426
1427typedef struct _notein
1428{
1429 t_object x_obj;
1430 t_float x_channel;
1431 t_outlet *x_outlet1;
1432 t_outlet *x_outlet2;
1433 t_outlet *x_outlet3;
1434} t_notein;
1435
1436static void *notein_new(t_floatarg f)
1437{
1438 t_notein *x = (t_notein *)pd_new(notein_class);
1439 x->x_channel = f;
1440 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1441 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1442 if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
1443 pd_bind(&x->x_obj.ob_pd, notein_sym);
1444 return (x);
1445}
1446
1447static void notein_list(t_notein *x, t_symbol *s, int argc, t_atom *argv)
1448{
1449 float pitch = atom_getfloatarg(0, argc, argv);
1450 float velo = atom_getfloatarg(1, argc, argv);
1451 float channel = atom_getfloatarg(2, argc, argv);
1452 if (x->x_channel != 0)
1453 {
1454 if (channel != x->x_channel) return;
1455 outlet_float(x->x_outlet2, velo);
1456 outlet_float(x->x_outlet1, pitch);
1457 }
1458 else
1459 {
1460 outlet_float(x->x_outlet3, channel);
1461 outlet_float(x->x_outlet2, velo);
1462 outlet_float(x->x_outlet1, pitch);
1463 }
1464}
1465
1466static void notein_free(t_notein *x)
1467{
1468 pd_unbind(&x->x_obj.ob_pd, notein_sym);
1469}
1470
1471static void notein_setup(void)
1472{
1473 notein_class = class_new(gensym("notein"), (t_newmethod)notein_new,
1474 (t_method)notein_free, sizeof(t_notein), CLASS_NOINLET, A_DEFFLOAT, 0);
1475 class_addlist(notein_class, notein_list);
1476 class_sethelpsymbol(notein_class, gensym("midi"));
1477 notein_sym = gensym("#notein");
1478}
1479
1480void inmidi_noteon(int portno, int channel, int pitch, int velo)
1481{
1482 if (notein_sym->s_thing)
1483 {
1484 t_atom at[3];
1485 SETFLOAT(at, pitch);
1486 SETFLOAT(at+1, velo);
1487 SETFLOAT(at+2, (channel + (portno << 4) + 1));
1488 pd_list(notein_sym->s_thing, &s_list, 3, at);
1489 }
1490}
1491
1492/* ----------------------- ctlin ------------------------- */
1493
1494static t_symbol *ctlin_sym;
1495
1496static t_class *ctlin_class;
1497
1498typedef struct _ctlin
1499{
1500 t_object x_obj;
1501 t_float x_channel;
1502 t_float x_ctlno;
1503 t_outlet *x_outlet1;
1504 t_outlet *x_outlet2;
1505 t_outlet *x_outlet3;
1506} t_ctlin;
1507
1508static void *ctlin_new(t_symbol *s, int argc, t_atom *argv)
1509{
1510 int ctlno, channel;
1511 t_ctlin *x = (t_ctlin *)pd_new(ctlin_class);
1512 if (!argc) ctlno = -1;
1513 else ctlno = atom_getfloatarg(0, argc, argv);
1514 channel = atom_getfloatarg(1, argc, argv);
1515 x->x_channel = channel;
1516 x->x_ctlno = ctlno;
1517 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1518 if (!channel)
1519 {
1520 if (x->x_ctlno < 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1521 x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
1522 }
1523 pd_bind(&x->x_obj.ob_pd, ctlin_sym);
1524 return (x);
1525}
1526
1527static void ctlin_list(t_ctlin *x, t_symbol *s, int argc, t_atom *argv)
1528{
1529 t_float ctlnumber = atom_getfloatarg(0, argc, argv);
1530 t_float value = atom_getfloatarg(1, argc, argv);
1531 t_float channel = atom_getfloatarg(2, argc, argv);
1532 if (x->x_ctlno >= 0 && x->x_ctlno != ctlnumber) return;
1533 if (x->x_channel > 0 && x->x_channel != channel) return;
1534 if (x->x_channel == 0) outlet_float(x->x_outlet3, channel);
1535 if (x->x_ctlno < 0) outlet_float(x->x_outlet2, ctlnumber);
1536 outlet_float(x->x_outlet1, value);
1537}
1538
1539static void ctlin_free(t_ctlin *x)
1540{
1541 pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
1542}
1543
1544static void ctlin_setup(void)
1545{
1546 ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new,
1547 (t_method)ctlin_free, sizeof(t_ctlin),
1548 CLASS_NOINLET, A_GIMME, 0);
1549 class_addlist(ctlin_class, ctlin_list);
1550 class_sethelpsymbol(ctlin_class, gensym("midi"));
1551 ctlin_sym = gensym("#ctlin");
1552}
1553
1554void inmidi_controlchange(int portno, int channel, int ctlnumber, int value)
1555{
1556 if (ctlin_sym->s_thing)
1557 {
1558 t_atom at[3];
1559 SETFLOAT(at, ctlnumber);
1560 SETFLOAT(at+1, value);
1561 SETFLOAT(at+2, (channel + (portno << 4) + 1));
1562 pd_list(ctlin_sym->s_thing, &s_list, 3, at);
1563 }
1564}
1565
1566/* ----------------------- pgmin ------------------------- */
1567
1568static t_symbol *pgmin_sym;
1569
1570static t_class *pgmin_class;
1571
1572typedef struct _pgmin
1573{
1574 t_object x_obj;
1575 t_float x_channel;
1576 t_outlet *x_outlet1;
1577 t_outlet *x_outlet2;
1578} t_pgmin;
1579
1580static void *pgmin_new(t_floatarg f)
1581{
1582 t_pgmin *x = (t_pgmin *)pd_new(pgmin_class);
1583 x->x_channel = f;
1584 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1585 if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1586 pd_bind(&x->x_obj.ob_pd, pgmin_sym);
1587 return (x);
1588}
1589
1590static void pgmin_list(t_pgmin *x, t_symbol *s, int argc, t_atom *argv)
1591{
1592 float value = atom_getfloatarg(0, argc, argv);
1593 float channel = atom_getfloatarg(1, argc, argv);
1594 if (x->x_channel != 0)
1595 {
1596 if (channel != x->x_channel) return;
1597 outlet_float(x->x_outlet1, value);
1598 }
1599 else
1600 {
1601 outlet_float(x->x_outlet2, channel);
1602 outlet_float(x->x_outlet1, value);
1603 }
1604}
1605
1606static void pgmin_free(t_pgmin *x)
1607{
1608 pd_unbind(&x->x_obj.ob_pd, pgmin_sym);
1609}
1610
1611static void pgmin_setup(void)
1612{
1613 pgmin_class = class_new(gensym("pgmin"), (t_newmethod)pgmin_new,
1614 (t_method)pgmin_free, sizeof(t_pgmin),
1615 CLASS_NOINLET, A_DEFFLOAT, 0);
1616 class_addlist(pgmin_class, pgmin_list);
1617 class_sethelpsymbol(pgmin_class, gensym("midi"));
1618 pgmin_sym = gensym("#pgmin");
1619}
1620
1621void inmidi_programchange(int portno, int channel, int value)
1622{
1623 if (pgmin_sym->s_thing)
1624 {
1625 t_atom at[2];
1626 SETFLOAT(at, value + 1);
1627 SETFLOAT(at+1, (channel + (portno << 4) + 1));
1628 pd_list(pgmin_sym->s_thing, &s_list, 2, at);
1629 }
1630}
1631
1632/* ----------------------- bendin ------------------------- */
1633
1634static t_symbol *bendin_sym;
1635
1636static t_class *bendin_class;
1637
1638typedef struct _bendin
1639{
1640 t_object x_obj;
1641 t_float x_channel;
1642 t_outlet *x_outlet1;
1643 t_outlet *x_outlet2;
1644} t_bendin;
1645
1646static void *bendin_new(t_floatarg f)
1647{
1648 t_bendin *x = (t_bendin *)pd_new(bendin_class);
1649 x->x_channel = f;
1650 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1651 if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1652 pd_bind(&x->x_obj.ob_pd, bendin_sym);
1653 return (x);
1654}
1655
1656static void bendin_list(t_bendin *x, t_symbol *s, int argc, t_atom *argv)
1657{
1658 t_float value = atom_getfloatarg(0, argc, argv);
1659 t_float channel = atom_getfloatarg(1, argc, argv);
1660 if (x->x_channel != 0)
1661 {
1662 if (channel != x->x_channel) return;
1663 outlet_float(x->x_outlet1, value);
1664 }
1665 else
1666 {
1667 outlet_float(x->x_outlet2, channel);
1668 outlet_float(x->x_outlet1, value);
1669 }
1670}
1671
1672static void bendin_free(t_bendin *x)
1673{
1674 pd_unbind(&x->x_obj.ob_pd, bendin_sym);
1675}
1676
1677static void bendin_setup(void)
1678{
1679 bendin_class = class_new(gensym("bendin"), (t_newmethod)bendin_new,
1680 (t_method)bendin_free, sizeof(t_bendin), CLASS_NOINLET, A_DEFFLOAT, 0);
1681 class_addlist(bendin_class, bendin_list);
1682 class_sethelpsymbol(bendin_class, gensym("midi"));
1683 bendin_sym = gensym("#bendin");
1684}
1685
1686void inmidi_pitchbend(int portno, int channel, int value)
1687{
1688 if (bendin_sym->s_thing)
1689 {
1690 t_atom at[2];
1691 SETFLOAT(at, value);
1692 SETFLOAT(at+1, (channel + (portno << 4) + 1));
1693 pd_list(bendin_sym->s_thing, &s_list, 2, at);
1694 }
1695}
1696
1697/* ----------------------- touchin ------------------------- */
1698
1699static t_symbol *touchin_sym;
1700
1701static t_class *touchin_class;
1702
1703typedef struct _touchin
1704{
1705 t_object x_obj;
1706 t_float x_channel;
1707 t_outlet *x_outlet1;
1708 t_outlet *x_outlet2;
1709} t_touchin;
1710
1711static void *touchin_new(t_floatarg f)
1712{
1713 t_touchin *x = (t_touchin *)pd_new(touchin_class);
1714 x->x_channel = f;
1715 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1716 if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1717 pd_bind(&x->x_obj.ob_pd, touchin_sym);
1718 return (x);
1719}
1720
1721static void touchin_list(t_touchin *x, t_symbol *s, int argc, t_atom *argv)
1722{
1723 t_float value = atom_getfloatarg(0, argc, argv);
1724 t_float channel = atom_getfloatarg(1, argc, argv);
1725 if (x->x_channel)
1726 {
1727 if (channel != x->x_channel) return;
1728 outlet_float(x->x_outlet1, value);
1729 }
1730 else
1731 {
1732 outlet_float(x->x_outlet2, channel);
1733 outlet_float(x->x_outlet1, value);
1734 }
1735}
1736
1737static void touchin_free(t_touchin *x)
1738{
1739 pd_unbind(&x->x_obj.ob_pd, touchin_sym);
1740}
1741
1742static void touchin_setup(void)
1743{
1744 touchin_class = class_new(gensym("touchin"), (t_newmethod)touchin_new,
1745 (t_method)touchin_free, sizeof(t_touchin),
1746 CLASS_NOINLET, A_DEFFLOAT, 0);
1747 class_addlist(touchin_class, touchin_list);
1748 class_sethelpsymbol(touchin_class, gensym("midi"));
1749 touchin_sym = gensym("#touchin");
1750}
1751
1752void inmidi_aftertouch(int portno, int channel, int value)
1753{
1754 if (touchin_sym->s_thing)
1755 {
1756 t_atom at[2];
1757 SETFLOAT(at, value);
1758 SETFLOAT(at+1, (channel + (portno << 4) + 1));
1759 pd_list(touchin_sym->s_thing, &s_list, 2, at);
1760 }
1761}
1762
1763/* ----------------------- polytouchin ------------------------- */
1764
1765static t_symbol *polytouchin_sym;
1766
1767static t_class *polytouchin_class;
1768
1769typedef struct _polytouchin
1770{
1771 t_object x_obj;
1772 t_float x_channel;
1773 t_outlet *x_outlet1;
1774 t_outlet *x_outlet2;
1775 t_outlet *x_outlet3;
1776} t_polytouchin;
1777
1778static void *polytouchin_new(t_floatarg f)
1779{
1780 t_polytouchin *x = (t_polytouchin *)pd_new(polytouchin_class);
1781 x->x_channel = f;
1782 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1783 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1784 if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
1785 pd_bind(&x->x_obj.ob_pd, polytouchin_sym);
1786 return (x);
1787}
1788
1789static void polytouchin_list(t_polytouchin *x, t_symbol *s, int argc,
1790 t_atom *argv)
1791{
1792 t_float pitch = atom_getfloatarg(0, argc, argv);
1793 t_float value = atom_getfloatarg(1, argc, argv);
1794 t_float channel = atom_getfloatarg(2, argc, argv);
1795 if (x->x_channel != 0)
1796 {
1797 if (channel != x->x_channel) return;
1798 outlet_float(x->x_outlet2, pitch);
1799 outlet_float(x->x_outlet1, value);
1800 }
1801 else
1802 {
1803 outlet_float(x->x_outlet3, channel);
1804 outlet_float(x->x_outlet2, pitch);
1805 outlet_float(x->x_outlet1, value);
1806 }
1807}
1808
1809static void polytouchin_free(t_polytouchin *x)
1810{
1811 pd_unbind(&x->x_obj.ob_pd, polytouchin_sym);
1812}
1813
1814static void polytouchin_setup(void)
1815{
1816 polytouchin_class = class_new(gensym("polytouchin"),
1817 (t_newmethod)polytouchin_new, (t_method)polytouchin_free,
1818 sizeof(t_polytouchin), CLASS_NOINLET, A_DEFFLOAT, 0);
1819 class_addlist(polytouchin_class, polytouchin_list);
1820 class_sethelpsymbol(polytouchin_class, gensym("midi"));
1821 polytouchin_sym = gensym("#polytouchin");
1822}
1823
1824void inmidi_polyaftertouch(int portno, int channel, int pitch, int value)
1825{
1826 if (polytouchin_sym->s_thing)
1827 {
1828 t_atom at[3];
1829 SETFLOAT(at, pitch);
1830 SETFLOAT(at+1, value);
1831 SETFLOAT(at+2, (channel + (portno << 4) + 1));
1832 pd_list(polytouchin_sym->s_thing, &s_list, 3, at);
1833 }
1834}
1835
1836/*----------------------- midiclkin--(midi F8 message )---------------------*/
1837static t_symbol *midiclkin_sym;
1838
1839static t_class *midiclkin_class;
1840
1841
1842typedef struct _midiclkin
1843{
1844 t_object x_obj;
1845 t_outlet *x_outlet1;
1846 t_outlet *x_outlet2;
1847} t_midiclkin;
1848
1849static void *midiclkin_new(t_floatarg f)
1850{
1851 t_midiclkin *x = (t_midiclkin *)pd_new(midiclkin_class);
1852 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1853 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1854 pd_bind(&x->x_obj.ob_pd, midiclkin_sym);
1855 return (x);
1856}
1857
1858static void midiclkin_list(t_midiclkin *x, t_symbol *s, int argc, t_atom *argv)
1859{
1860 float value = atom_getfloatarg(0, argc, argv);
1861 float count = atom_getfloatarg(1, argc, argv);
1862 outlet_float(x->x_outlet2, count);
1863 outlet_float(x->x_outlet1, value);
1864}
1865
1866static void midiclkin_free(t_midiclkin *x)
1867{
1868 pd_unbind(&x->x_obj.ob_pd, midiclkin_sym);
1869}
1870
1871static void midiclkin_setup(void)
1872{
1873 midiclkin_class = class_new(gensym("midiclkin"),
1874 (t_newmethod)midiclkin_new, (t_method)midiclkin_free,
1875 sizeof(t_midiclkin), CLASS_NOINLET, A_DEFFLOAT, 0);
1876 class_addlist(midiclkin_class, midiclkin_list);
1877 class_sethelpsymbol(midiclkin_class, gensym("midi"));
1878 midiclkin_sym = gensym("#midiclkin");
1879}
1880
1881void inmidi_clk(double timing)
1882{
1883
1884 static float prev = 0;
1885 static float count = 0;
1886 float cur,diff;
1887
1888 if (midiclkin_sym->s_thing)
1889 {
1890 t_atom at[2];
1891 diff =timing - prev;
1892 count++;
1893
1894 if (count == 3)
1895 { /* 24 count per quoter note */
1896 SETFLOAT(at, 1 );
1897 count = 0;
1898 }
1899 else SETFLOAT(at, 0);
1900
1901 SETFLOAT(at+1, diff);
1902 pd_list(midiclkin_sym->s_thing, &s_list, 2, at);
1903 prev = timing;
1904 }
1905}
1906
1907/*----------midirealtimein (midi FA,FB,FC,FF message )-----------------*/
1908
1909static t_symbol *midirealtimein_sym;
1910
1911static t_class *midirealtimein_class;
1912
1913typedef struct _midirealtimein
1914{
1915 t_object x_obj;
1916 t_outlet *x_outlet1;
1917 t_outlet *x_outlet2;
1918} t_midirealtimein;
1919
1920static void *midirealtimein_new( void)
1921{
1922 t_midirealtimein *x = (t_midirealtimein *)pd_new(midirealtimein_class);
1923 x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
1924 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
1925 pd_bind(&x->x_obj.ob_pd, midirealtimein_sym);
1926#ifndef MSW
1927 pd_error(x, "midirealtimein: works under MSW only");
1928#endif
1929 return (x);
1930}
1931
1932static void midirealtimein_list(t_midirealtimein *x, t_symbol *s,
1933 int argc, t_atom *argv)
1934{
1935 float portno = atom_getfloatarg(0, argc, argv);
1936 float byte = atom_getfloatarg(1, argc, argv);
1937
1938 outlet_float(x->x_outlet2, portno);
1939 outlet_float(x->x_outlet1, byte);
1940}
1941
1942static void midirealtimein_free(t_midirealtimein *x)
1943{
1944 pd_unbind(&x->x_obj.ob_pd, midirealtimein_sym);
1945}
1946
1947static void midirealtimein_setup(void)
1948{
1949 midirealtimein_class = class_new(gensym("midirealtimein"),
1950 (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free,
1951 sizeof(t_midirealtimein), CLASS_NOINLET, A_DEFFLOAT, 0);
1952 class_addlist(midirealtimein_class, midirealtimein_list);
1953 class_sethelpsymbol(midirealtimein_class, gensym("midi"));
1954 midirealtimein_sym = gensym("#midirealtimein");
1955}
1956
1957void inmidi_realtimein(int portno, int SysMsg)
1958{
1959 if (midirealtimein_sym->s_thing)
1960 {
1961 t_atom at[2];
1962 SETFLOAT(at, portno);
1963 SETFLOAT(at+1, SysMsg);
1964 pd_list(midirealtimein_sym->s_thing, &s_list, 1, at);
1965 }
1966}
1967
1968/* -------------------------- midiout -------------------------- */
1969
1970static t_class *midiout_class;
1971
1972void sys_putmidibyte(int portno, int byte);
1973
1974typedef struct _midiout
1975{
1976 t_object x_obj;
1977 t_float x_portno;
1978} t_midiout;
1979
1980static void *midiout_new(t_floatarg portno)
1981{
1982 t_midiout *x = (t_midiout *)pd_new(midiout_class);
1983 if (portno <= 0) portno = 1;
1984 x->x_portno = portno;
1985 floatinlet_new(&x->x_obj, &x->x_portno);
1986#ifdef __irix__
1987 post("midiout: unimplemented in IRIX");
1988#endif
1989 return (x);
1990}
1991
1992static void midiout_float(t_midiout *x, t_floatarg f)
1993{
1994 sys_putmidibyte(x->x_portno - 1, f);
1995}
1996
1997static void midiout_setup(void)
1998{
1999 midiout_class = class_new(gensym("midiout"), (t_newmethod)midiout_new, 0,
2000 sizeof(t_midiout), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
2001 class_addfloat(midiout_class, midiout_float);
2002 class_sethelpsymbol(midiout_class, gensym("midi"));
2003}
2004
2005/* -------------------------- noteout -------------------------- */
2006
2007static t_class *noteout_class;
2008
2009typedef struct _noteout
2010{
2011 t_object x_obj;
2012 t_float x_velo;
2013 t_float x_channel;
2014} t_noteout;
2015
2016static void *noteout_new(t_floatarg channel)
2017{
2018 t_noteout *x = (t_noteout *)pd_new(noteout_class);
2019 x->x_velo = 0;
2020 if (channel < 1) channel = 1;
2021 x->x_channel = channel;
2022 floatinlet_new(&x->x_obj, &x->x_velo);
2023 floatinlet_new(&x->x_obj, &x->x_channel);
2024 return (x);
2025}
2026
2027static void noteout_float(t_noteout *x, t_float f)
2028{
2029 int binchan = x->x_channel - 1;
2030 if (binchan < 0)
2031 binchan = 0;
2032 outmidi_noteon((binchan >> 4),
2033 (binchan & 15), (int)f, (int)x->x_velo);
2034}
2035
2036static void noteout_setup(void)
2037{
2038 noteout_class = class_new(gensym("noteout"), (t_newmethod)noteout_new, 0,
2039 sizeof(t_noteout), 0, A_DEFFLOAT, 0);
2040 class_addfloat(noteout_class, noteout_float);
2041 class_sethelpsymbol(noteout_class, gensym("midi"));
2042}
2043
2044
2045/* -------------------------- ctlout -------------------------- */
2046
2047static t_class *ctlout_class;
2048
2049typedef struct _ctlout
2050{
2051 t_object x_obj;
2052 t_float x_ctl;
2053 t_float x_channel;
2054} t_ctlout;
2055
2056static void *ctlout_new(t_floatarg ctl, t_floatarg channel)
2057{
2058 t_ctlout *x = (t_ctlout *)pd_new(ctlout_class);
2059 x->x_ctl = ctl;
2060 if (channel <= 0) channel = 1;
2061 x->x_channel = channel;
2062 floatinlet_new(&x->x_obj, &x->x_ctl);
2063 floatinlet_new(&x->x_obj, &x->x_channel);
2064 return (x);
2065}
2066
2067static void ctlout_float(t_ctlout *x, t_float f)
2068{
2069 int binchan = x->x_channel - 1;
2070 if (binchan < 0)
2071 binchan = 0;
2072 outmidi_controlchange((binchan >> 4),
2073 (binchan & 15), (int)(x->x_ctl), (int)f);
2074}
2075
2076static void ctlout_setup(void)
2077{
2078 ctlout_class = class_new(gensym("ctlout"), (t_newmethod)ctlout_new, 0,
2079 sizeof(t_ctlout), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
2080 class_addfloat(ctlout_class, ctlout_float);
2081 class_sethelpsymbol(ctlout_class, gensym("midi"));
2082}
2083
2084
2085/* -------------------------- pgmout -------------------------- */
2086
2087static t_class *pgmout_class;
2088
2089typedef struct _pgmout
2090{
2091 t_object x_obj;
2092 t_float x_channel;
2093} t_pgmout;
2094
2095static void *pgmout_new(t_floatarg channel)
2096{
2097 t_pgmout *x = (t_pgmout *)pd_new(pgmout_class);
2098 if (channel <= 0) channel = 1;
2099 x->x_channel = channel;
2100 floatinlet_new(&x->x_obj, &x->x_channel);
2101 return (x);
2102}
2103
2104static void pgmout_float(t_pgmout *x, t_floatarg f)
2105{
2106 int binchan = x->x_channel - 1;
2107 int n = f - 1;
2108 if (binchan < 0)
2109 binchan = 0;
2110 if (n < 0) n = 0;
2111 else if (n > 127) n = 127;
2112 outmidi_programchange((binchan >> 4),
2113 (binchan & 15), n);
2114}
2115
2116static void pgmout_setup(void)
2117{
2118 pgmout_class = class_new(gensym("pgmout"), (t_newmethod)pgmout_new, 0,
2119 sizeof(t_pgmout), 0, A_DEFFLOAT, 0);
2120 class_addfloat(pgmout_class, pgmout_float);
2121 class_sethelpsymbol(pgmout_class, gensym("midi"));
2122}
2123
2124
2125/* -------------------------- bendout -------------------------- */
2126
2127static t_class *bendout_class;
2128
2129typedef struct _bendout
2130{
2131 t_object x_obj;
2132 t_float x_channel;
2133} t_bendout;
2134
2135static void *bendout_new(t_floatarg channel)
2136{
2137 t_bendout *x = (t_bendout *)pd_new(bendout_class);
2138 if (channel <= 0) channel = 1;
2139 x->x_channel = channel;
2140 floatinlet_new(&x->x_obj, &x->x_channel);
2141 return (x);
2142}
2143
2144static void bendout_float(t_bendout *x, t_float f)
2145{
2146 int binchan = x->x_channel - 1;
2147 int n = (int)f + 8192;
2148 if (binchan < 0)
2149 binchan = 0;
2150 outmidi_pitchbend((binchan >> 4), (binchan & 15), n);
2151}
2152
2153static void bendout_setup(void)
2154{
2155 bendout_class = class_new(gensym("bendout"), (t_newmethod)bendout_new, 0,
2156 sizeof(t_bendout), 0, A_DEFFLOAT, 0);
2157 class_addfloat(bendout_class, bendout_float);
2158 class_sethelpsymbol(bendout_class, gensym("midi"));
2159}
2160
2161/* -------------------------- touch -------------------------- */
2162
2163static t_class *touchout_class;
2164
2165typedef struct _touchout
2166{
2167 t_object x_obj;
2168 t_float x_channel;
2169} t_touchout;
2170
2171static void *touchout_new(t_floatarg channel)
2172{
2173 t_touchout *x = (t_touchout *)pd_new(touchout_class);
2174 if (channel <= 0) channel = 1;
2175 x->x_channel = channel;
2176 floatinlet_new(&x->x_obj, &x->x_channel);
2177 return (x);
2178}
2179
2180static void touchout_float(t_touchout *x, t_float f)
2181{
2182 int binchan = x->x_channel - 1;
2183 if (binchan < 0)
2184 binchan = 0;
2185 outmidi_aftertouch((binchan >> 4), (binchan & 15), (int)f);
2186}
2187
2188static void touchout_setup(void)
2189{
2190 touchout_class = class_new(gensym("touchout"), (t_newmethod)touchout_new, 0,
2191 sizeof(t_touchout), 0, A_DEFFLOAT, 0);
2192 class_addfloat(touchout_class, touchout_float);
2193 class_sethelpsymbol(touchout_class, gensym("midi"));
2194}
2195
2196/* -------------------------- polytouch -------------------------- */
2197
2198static t_class *polytouchout_class;
2199
2200typedef struct _polytouchout
2201{
2202 t_object x_obj;
2203 t_float x_channel;
2204 t_float x_pitch;
2205} t_polytouchout;
2206
2207static void *polytouchout_new(t_floatarg channel)
2208{
2209 t_polytouchout *x = (t_polytouchout *)pd_new(polytouchout_class);
2210 if (channel <= 0) channel = 1;
2211 x->x_channel = channel;
2212 x->x_pitch = 0;
2213 floatinlet_new(&x->x_obj, &x->x_pitch);
2214 floatinlet_new(&x->x_obj, &x->x_channel);
2215 return (x);
2216}
2217
2218static void polytouchout_float(t_polytouchout *x, t_float n)
2219{
2220 int binchan = x->x_channel - 1;
2221 if (binchan < 0)
2222 binchan = 0;
2223 outmidi_polyaftertouch((binchan >> 4), (binchan & 15), x->x_pitch, n);
2224}
2225
2226static void polytouchout_setup(void)
2227{
2228 polytouchout_class = class_new(gensym("polytouchout"),
2229 (t_newmethod)polytouchout_new, 0,
2230 sizeof(t_polytouchout), 0, A_DEFFLOAT, 0);
2231 class_addfloat(polytouchout_class, polytouchout_float);
2232 class_sethelpsymbol(polytouchout_class, gensym("midi"));
2233}
2234
2235/* -------------------------- makenote -------------------------- */
2236
2237static t_class *makenote_class;
2238
2239typedef struct _hang
2240{
2241 t_clock *h_clock;
2242 struct _hang *h_next;
2243 t_float h_pitch;
2244 struct _makenote *h_owner;
2245} t_hang;
2246
2247typedef struct _makenote
2248{
2249 t_object x_obj;
2250 t_float x_velo;
2251 t_float x_dur;
2252 t_outlet *x_pitchout;
2253 t_outlet *x_velout;
2254 t_hang *x_hang;
2255} t_makenote;
2256
2257static void *makenote_new(t_floatarg velo, t_floatarg dur)
2258{
2259 t_makenote *x = (t_makenote *)pd_new(makenote_class);
2260 x->x_velo = velo;
2261 x->x_dur = dur;
2262 floatinlet_new(&x->x_obj, &x->x_velo);
2263 floatinlet_new(&x->x_obj, &x->x_dur);
2264 x->x_pitchout = outlet_new(&x->x_obj, &s_float);
2265 x->x_velout = outlet_new(&x->x_obj, &s_float);
2266 x->x_hang = 0;
2267 return (x);
2268}
2269
2270static void makenote_tick(t_hang *hang)
2271{
2272 t_makenote *x = hang->h_owner;
2273 t_hang *h2, *h3;
2274 outlet_float(x->x_velout, 0);
2275 outlet_float(x->x_pitchout, hang->h_pitch);
2276 if (x->x_hang == hang) x->x_hang = hang->h_next;
2277 else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3)
2278 {
2279 if (h3 == hang)
2280 {
2281 h2->h_next = h3->h_next;
2282 break;
2283 }
2284 }
2285 clock_free(hang->h_clock);
2286 freebytes(hang, sizeof(*hang));
2287}
2288
2289static void makenote_float(t_makenote *x, t_float f)
2290{
2291 t_hang *hang;
2292 if (!x->x_velo) return;
2293 outlet_float(x->x_velout, x->x_velo);
2294 outlet_float(x->x_pitchout, f);
2295 hang = (t_hang *)getbytes(sizeof *hang);
2296 hang->h_next = x->x_hang;
2297 x->x_hang = hang;
2298 hang->h_pitch = f;
2299 hang->h_owner = x;
2300 hang->h_clock = clock_new(hang, (t_method)makenote_tick);
2301 clock_delay(hang->h_clock, (x->x_dur >= 0 ? x->x_dur : 0));
2302}
2303
2304static void makenote_stop(t_makenote *x)
2305{
2306 t_hang *hang;
2307 while (hang = x->x_hang)
2308 {
2309 outlet_float(x->x_velout, 0);
2310 outlet_float(x->x_pitchout, hang->h_pitch);
2311 x->x_hang = hang->h_next;
2312 clock_free(hang->h_clock);
2313 freebytes(hang, sizeof(*hang));
2314 }
2315}
2316
2317static void makenote_clear(t_makenote *x)
2318{
2319 t_hang *hang;
2320 while (hang = x->x_hang)
2321 {
2322 x->x_hang = hang->h_next;
2323 clock_free(hang->h_clock);
2324 freebytes(hang, sizeof(*hang));
2325 }
2326}
2327
2328static void makenote_setup(void)
2329{
2330 makenote_class = class_new(gensym("makenote"),
2331 (t_newmethod)makenote_new, (t_method)makenote_clear,
2332 sizeof(t_makenote), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
2333 class_addfloat(makenote_class, makenote_float);
2334 class_addmethod(makenote_class, (t_method)makenote_stop, gensym("stop"),
2335 0);
2336 class_addmethod(makenote_class, (t_method)makenote_clear, gensym("clear"),
2337 0);
2338}
2339
2340/* -------------------------- stripnote -------------------------- */
2341
2342static t_class *stripnote_class;
2343
2344typedef struct _stripnote
2345{
2346 t_object x_obj;
2347 t_float x_velo;
2348 t_outlet *x_pitchout;
2349 t_outlet *x_velout;
2350} t_stripnote;
2351
2352static void *stripnote_new(void )
2353{
2354 t_stripnote *x = (t_stripnote *)pd_new(stripnote_class);
2355 floatinlet_new(&x->x_obj, &x->x_velo);
2356 x->x_pitchout = outlet_new(&x->x_obj, &s_float);
2357 x->x_velout = outlet_new(&x->x_obj, &s_float);
2358 return (x);
2359}
2360
2361static void stripnote_float(t_stripnote *x, t_float f)
2362{
2363 t_hang *hang;
2364 if (!x->x_velo) return;
2365 outlet_float(x->x_velout, x->x_velo);
2366 outlet_float(x->x_pitchout, f);
2367}
2368
2369static void stripnote_setup(void)
2370{
2371 stripnote_class = class_new(gensym("stripnote"),
2372 (t_newmethod)stripnote_new, 0, sizeof(t_stripnote), 0, 0);
2373 class_addfloat(stripnote_class, stripnote_float);
2374}
2375
2376/* -------------------------- poly -------------------------- */
2377
2378static t_class *poly_class;
2379
2380typedef struct voice
2381{
2382 float v_pitch;
2383 int v_used;
2384 unsigned long v_serial;
2385} t_voice;
2386
2387typedef struct poly
2388{
2389 t_object x_obj;
2390 int x_n;
2391 t_voice *x_vec;
2392 float x_vel;
2393 t_outlet *x_pitchout;
2394 t_outlet *x_velout;
2395 unsigned long x_serial;
2396 int x_steal;
2397} t_poly;
2398
2399static void *poly_new(float fnvoice, float fsteal)
2400{
2401 int i, n = fnvoice;
2402 t_poly *x = (t_poly *)pd_new(poly_class);
2403 t_voice *v;
2404 if (n < 1) n = 1;
2405 x->x_n = n;
2406 x->x_vec = (t_voice *)getbytes(n * sizeof(*x->x_vec));
2407 for (v = x->x_vec, i = n; i--; v++)
2408 v->v_pitch = v->v_used = v->v_serial = 0;
2409 x->x_vel = 0;
2410 x->x_steal = (fsteal != 0);
2411 floatinlet_new(&x->x_obj, &x->x_vel);
2412 outlet_new(&x->x_obj, &s_float);
2413 x->x_pitchout = outlet_new(&x->x_obj, &s_float);
2414 x->x_velout = outlet_new(&x->x_obj, &s_float);
2415 x->x_serial = 0;
2416 return (x);
2417}
2418
2419static void poly_float(t_poly *x, t_float f)
2420{
2421 int i;
2422 t_voice *v;
2423 t_voice *firston, *firstoff;
2424 unsigned int serialon, serialoff, onindex = 0, offindex = 0;
2425 if (x->x_vel > 0)
2426 {
2427 /* note on. Look for a vacant voice */
2428 for (v = x->x_vec, i = 0, firston = firstoff = 0,
2429 serialon = serialoff = 0xffffffff; i < x->x_n; v++, i++)
2430 {
2431 if (v->v_used && v->v_serial < serialon)
2432 firston = v, serialon = v->v_serial, onindex = i;
2433 else if (!v->v_used && v->v_serial < serialoff)
2434 firstoff = v, serialoff = v->v_serial, offindex = i;
2435 }
2436 if (firstoff)
2437 {
2438 outlet_float(x->x_velout, x->x_vel);
2439 outlet_float(x->x_pitchout, firstoff->v_pitch = f);
2440 outlet_float(x->x_obj.ob_outlet, offindex+1);
2441 firstoff->v_used = 1;
2442 firstoff->v_serial = x->x_serial++;
2443 }
2444 /* if none, steal one */
2445 else if (firston && x->x_steal)
2446 {
2447 outlet_float(x->x_velout, 0);
2448 outlet_float(x->x_pitchout, firston->v_pitch);
2449 outlet_float(x->x_obj.ob_outlet, onindex+1);
2450 outlet_float(x->x_velout, x->x_vel);
2451 outlet_float(x->x_pitchout, firston->v_pitch = f);
2452 outlet_float(x->x_obj.ob_outlet, onindex+1);
2453 firston->v_serial = x->x_serial++;
2454 }
2455 }
2456 else /* note off. Turn off oldest match */
2457 {
2458 for (v = x->x_vec, i = 0, firston = 0, serialon = 0xffffffff;
2459 i < x->x_n; v++, i++)
2460 if (v->v_used && v->v_pitch == f && v->v_serial < serialon)
2461 firston = v, serialon = v->v_serial, onindex = i;
2462 if (firston)
2463 {
2464 firston->v_used = 0;
2465 firston->v_serial = x->x_serial++;
2466 outlet_float(x->x_velout, 0);
2467 outlet_float(x->x_pitchout, firston->v_pitch);
2468 outlet_float(x->x_obj.ob_outlet, onindex+1);
2469 }
2470 }
2471}
2472
2473static void poly_stop(t_poly *x)
2474{
2475 int i;
2476 t_voice *v;
2477 for (i = 0, v = x->x_vec; i < x->x_n; i++, v++)
2478 if (v->v_used)
2479 {
2480 outlet_float(x->x_velout, 0L);
2481 outlet_float(x->x_pitchout, v->v_pitch);
2482 outlet_float(x->x_obj.ob_outlet, i+1);
2483 v->v_used = 0;
2484 v->v_serial = x->x_serial++;
2485 }
2486}
2487
2488static void poly_clear(t_poly *x)
2489{
2490 int i;
2491 t_voice *v;
2492 for (v = x->x_vec, i = x->x_n; i--; v++) v->v_used = v->v_serial = 0;
2493}
2494
2495static void poly_free(t_poly *x)
2496{
2497 freebytes(x->x_vec, x->x_n * sizeof (*x->x_vec));
2498}
2499
2500static void poly_setup(void)
2501{
2502 poly_class = class_new(gensym("poly"),
2503 (t_newmethod)poly_new, (t_method)poly_clear,
2504 sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
2505 class_addfloat(poly_class, poly_float);
2506 class_addmethod(poly_class, (t_method)poly_stop, gensym("stop"), 0);
2507 class_addmethod(poly_class, (t_method)poly_clear, gensym("clear"), 0);
2508}
2509
2510/* -------------------------- bag -------------------------- */
2511
2512static t_class *bag_class;
2513
2514typedef struct _bagelem
2515{
2516 struct _bagelem *e_next;
2517 t_float e_value;
2518} t_bagelem;
2519
2520typedef struct _bag
2521{
2522 t_object x_obj;
2523 t_float x_velo;
2524 t_bagelem *x_first;
2525} t_bag;
2526
2527static void *bag_new(void )
2528{
2529 t_bag *x = (t_bag *)pd_new(bag_class);
2530 x->x_velo = 0;
2531 floatinlet_new(&x->x_obj, &x->x_velo);
2532 outlet_new(&x->x_obj, &s_float);
2533 x->x_first = 0;
2534 return (x);
2535}
2536
2537static void bag_float(t_bag *x, t_float f)
2538{
2539 t_bagelem *bagelem, *e2, *e3;
2540 if (x->x_velo != 0)
2541 {
2542 bagelem = (t_bagelem *)getbytes(sizeof *bagelem);
2543 bagelem->e_next = 0;
2544 bagelem->e_value = f;
2545 if (!x->x_first) x->x_first = bagelem;
2546 else /* LATER replace with a faster algorithm */
2547 {
2548 for (e2 = x->x_first; e3 = e2->e_next; e2 = e3)
2549 ;
2550 e2->e_next = bagelem;
2551 }
2552 }
2553 else
2554 {
2555 if (!x->x_first) return;
2556 if (x->x_first->e_value == f)
2557 {
2558 bagelem = x->x_first;
2559 x->x_first = x->x_first->e_next;
2560 freebytes(bagelem, sizeof(*bagelem));
2561 return;
2562 }
2563 for (e2 = x->x_first; e3 = e2->e_next; e2 = e3)
2564 if (e3->e_value == f)
2565 {
2566 e2->e_next = e3->e_next;
2567 freebytes(e3, sizeof(*e3));
2568 return;
2569 }
2570 }
2571}
2572
2573static void bag_flush(t_bag *x)
2574{
2575 t_bagelem *bagelem;
2576 while (bagelem = x->x_first)
2577 {
2578 outlet_float(x->x_obj.ob_outlet, bagelem->e_value);
2579 x->x_first = bagelem->e_next;
2580 freebytes(bagelem, sizeof(*bagelem));
2581 }
2582}
2583
2584static void bag_clear(t_bag *x)
2585{
2586 t_bagelem *bagelem;
2587 while (bagelem = x->x_first)
2588 {
2589 x->x_first = bagelem->e_next;
2590 freebytes(bagelem, sizeof(*bagelem));
2591 }
2592}
2593
2594static void bag_setup(void)
2595{
2596 bag_class = class_new(gensym("bag"),
2597 (t_newmethod)bag_new, (t_method)bag_clear,
2598 sizeof(t_bag), 0, 0);
2599 class_addfloat(bag_class, bag_float);
2600 class_addmethod(bag_class, (t_method)bag_flush, gensym("flush"), 0);
2601 class_addmethod(bag_class, (t_method)bag_clear, gensym("clear"), 0);
2602}
2603
2604void x_midi_setup(void)
2605{
2606 midiin_setup();
2607 midirealtimein_setup();
2608 notein_setup();
2609 ctlin_setup();
2610 pgmin_setup();
2611 bendin_setup();
2612 touchin_setup();
2613 polytouchin_setup();
2614 midiclkin_setup();
2615 midiout_setup();
2616 noteout_setup();
2617 ctlout_setup();
2618 pgmout_setup();
2619 bendout_setup();
2620 touchout_setup();
2621 polytouchout_setup();
2622 makenote_setup();
2623 stripnote_setup();
2624 poly_setup();
2625 bag_setup();
2626}