summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/s_midi.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/s_midi.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/s_midi.c642
1 files changed, 0 insertions, 642 deletions
diff --git a/apps/plugins/pdbox/PDa/src/s_midi.c b/apps/plugins/pdbox/PDa/src/s_midi.c
deleted file mode 100644
index 72a8792b25..0000000000
--- a/apps/plugins/pdbox/PDa/src/s_midi.c
+++ /dev/null
@@ -1,642 +0,0 @@
1/* Copyright (c) 1997-1999 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/* Clock functions (which should move, but where?) and MIDI queueing */
6
7#include "m_pd.h"
8#include "s_stuff.h"
9#include "m_imp.h"
10#ifdef UNIX
11#include <unistd.h>
12#include <sys/time.h>
13#ifdef HAVE_BSTRING_H
14#include <bstring.h>
15#endif
16#endif
17#ifdef MSW
18#include <winsock.h>
19#include <sys/types.h>
20#include <sys/timeb.h>
21#include <wtypes.h>
22#endif
23#include <string.h>
24#include <stdio.h>
25#include <signal.h>
26
27typedef struct _midiqelem
28{
29 double q_time;
30 int q_portno;
31 unsigned char q_onebyte;
32 unsigned char q_byte1;
33 unsigned char q_byte2;
34 unsigned char q_byte3;
35} t_midiqelem;
36
37#define MIDIQSIZE 1024
38
39t_midiqelem midi_outqueue[MIDIQSIZE];
40int midi_outhead, midi_outtail;
41t_midiqelem midi_inqueue[MIDIQSIZE];
42int midi_inhead, midi_intail;
43static double sys_midiinittime;
44
45 /* this is our current estimate for at what "system" real time the
46 current logical time's output should occur. */
47static double sys_dactimeminusrealtime;
48 /* same for input, should be schduler advance earlier. */
49static double sys_adctimeminusrealtime;
50
51static double sys_newdactimeminusrealtime = -1e20;
52static double sys_newadctimeminusrealtime = -1e20;
53static double sys_whenupdate;
54
55void sys_initmidiqueue( void)
56{
57 sys_midiinittime = clock_getlogicaltime();
58 sys_dactimeminusrealtime = sys_adctimeminusrealtime = 0;
59}
60
61 /* this is called from the OS dependent code from time to time when we
62 think we know the delay (outbuftime) in seconds, at which the last-output
63 audio sample will go out the door. */
64void sys_setmiditimediff(double inbuftime, double outbuftime)
65{
66 double dactimeminusrealtime =
67 .001 * clock_gettimesince(sys_midiinittime)
68 - outbuftime - sys_getrealtime();
69 double adctimeminusrealtime =
70 .001 * clock_gettimesince(sys_midiinittime)
71 + inbuftime - sys_getrealtime();
72 if (dactimeminusrealtime > sys_newdactimeminusrealtime)
73 sys_newdactimeminusrealtime = dactimeminusrealtime;
74 if (adctimeminusrealtime > sys_newadctimeminusrealtime)
75 sys_newadctimeminusrealtime = adctimeminusrealtime;
76 if (sys_getrealtime() > sys_whenupdate)
77 {
78 sys_dactimeminusrealtime = sys_newdactimeminusrealtime;
79 sys_adctimeminusrealtime = sys_newadctimeminusrealtime;
80 sys_newdactimeminusrealtime = -1e20;
81 sys_newadctimeminusrealtime = -1e20;
82 sys_whenupdate = sys_getrealtime() + 1;
83 }
84}
85
86 /* return the logical time of the DAC sample we believe is currently
87 going out, based on how much "system time" has elapsed since the
88 last time sys_setmiditimediff got called. */
89static double sys_getmidioutrealtime( void)
90{
91 return (sys_getrealtime() + sys_dactimeminusrealtime);
92}
93
94static double sys_getmidiinrealtime( void)
95{
96 return (sys_getrealtime() + sys_adctimeminusrealtime);
97}
98
99static void sys_putnext( void)
100{
101 int portno = midi_outqueue[midi_outtail].q_portno;
102 if (midi_outqueue[midi_outtail].q_onebyte)
103 sys_putmidibyte(portno, midi_outqueue[midi_outtail].q_byte1);
104 else sys_putmidimess(portno, midi_outqueue[midi_outtail].q_byte1,
105 midi_outqueue[midi_outtail].q_byte2,
106 midi_outqueue[midi_outtail].q_byte3);
107 midi_outtail = (midi_outtail + 1 == MIDIQSIZE ? 0 : midi_outtail + 1);
108}
109
110/* #define TEST_DEJITTER */
111
112void sys_pollmidioutqueue( void)
113{
114#ifdef TEST_DEJITTER
115 static int db = 0;
116#endif
117 double midirealtime = sys_getmidioutrealtime();
118#ifdef TEST_DEJITTER
119 if (midi_outhead == midi_outtail)
120 db = 0;
121#endif
122 while (midi_outhead != midi_outtail)
123 {
124#ifdef TEST_DEJITTER
125 if (!db)
126 {
127 post("out: del %f, midiRT %f logicaltime %f, RT %f dacminusRT %f",
128 (midi_outqueue[midi_outtail].q_time - midirealtime),
129 midirealtime, .001 * clock_gettimesince(sys_midiinittime),
130 sys_getrealtime(), sys_dactimeminusrealtime);
131 db = 1;
132 }
133#endif
134 if (midi_outqueue[midi_outtail].q_time <= midirealtime)
135 sys_putnext();
136 else break;
137 }
138}
139
140static void sys_queuemidimess(int portno, int onebyte, int a, int b, int c)
141{
142 t_midiqelem *midiqelem;
143 int newhead = midi_outhead +1;
144 if (newhead == MIDIQSIZE)
145 newhead = 0;
146 /* if FIFO is full flush an element to make room */
147 if (newhead == midi_outtail)
148 sys_putnext();
149 midi_outqueue[midi_outhead].q_portno = portno;
150 midi_outqueue[midi_outhead].q_onebyte = onebyte;
151 midi_outqueue[midi_outhead].q_byte1 = a;
152 midi_outqueue[midi_outhead].q_byte2 = b;
153 midi_outqueue[midi_outhead].q_byte3 = c;
154 midi_outqueue[midi_outhead].q_time =
155 .001 * clock_gettimesince(sys_midiinittime);
156 midi_outhead = newhead;
157 sys_pollmidioutqueue();
158}
159
160#define MIDI_NOTEON 144
161#define MIDI_POLYAFTERTOUCH 160
162#define MIDI_CONTROLCHANGE 176
163#define MIDI_PROGRAMCHANGE 192
164#define MIDI_AFTERTOUCH 208
165#define MIDI_PITCHBEND 224
166
167void outmidi_noteon(int portno, int channel, int pitch, int velo)
168{
169 if (pitch < 0) pitch = 0;
170 else if (pitch > 127) pitch = 127;
171 if (velo < 0) velo = 0;
172 else if (velo > 127) velo = 127;
173 sys_queuemidimess(portno, 0, MIDI_NOTEON + (channel & 0xf), pitch, velo);
174}
175
176void outmidi_controlchange(int portno, int channel, int ctl, int value)
177{
178 if (ctl < 0) ctl = 0;
179 else if (ctl > 127) ctl = 127;
180 if (value < 0) value = 0;
181 else if (value > 127) value = 127;
182 sys_queuemidimess(portno, 0, MIDI_CONTROLCHANGE + (channel & 0xf),
183 ctl, value);
184}
185
186void outmidi_programchange(int portno, int channel, int value)
187{
188 if (value < 0) value = 0;
189 else if (value > 127) value = 127;
190 sys_queuemidimess(portno, 0,
191 MIDI_PROGRAMCHANGE + (channel & 0xf), value, 0);
192}
193
194void outmidi_pitchbend(int portno, int channel, int value)
195{
196 if (value < 0) value = 0;
197 else if (value > 16383) value = 16383;
198 sys_queuemidimess(portno, 0, MIDI_PITCHBEND + (channel & 0xf),
199 (value & 127), ((value>>7) & 127));
200}
201
202void outmidi_aftertouch(int portno, int channel, int value)
203{
204 if (value < 0) value = 0;
205 else if (value > 127) value = 127;
206 sys_queuemidimess(portno, 0, MIDI_AFTERTOUCH + (channel & 0xf), value, 0);
207}
208
209void outmidi_polyaftertouch(int portno, int channel, int pitch, int value)
210{
211 if (pitch < 0) pitch = 0;
212 else if (pitch > 127) pitch = 127;
213 if (value < 0) value = 0;
214 else if (value > 127) value = 127;
215 sys_queuemidimess(portno, 0, MIDI_POLYAFTERTOUCH + (channel & 0xf),
216 pitch, value);
217}
218
219void outmidi_mclk(int portno)
220{
221 sys_queuemidimess(portno, 1, 0xf8, 0,0);
222}
223
224/* ------------------------- MIDI input queue handling ------------------ */
225typedef struct midiparser
226{
227 int mp_status;
228 int mp_gotbyte1;
229 int mp_byte1;
230} t_midiparser;
231
232#define MIDINOTEOFF 0x80 /* 2 following 'data bytes' */
233#define MIDINOTEON 0x90 /* 2 */
234#define MIDIPOLYTOUCH 0xa0 /* 2 */
235#define MIDICONTROLCHANGE 0xb0 /* 2 */
236#define MIDIPROGRAMCHANGE 0xc0 /* 1 */
237#define MIDICHANNELTOUCH 0xd0 /* 1 */
238#define MIDIPITCHBEND 0xe0 /* 2 */
239#define MIDISTARTSYSEX 0xf0 /* (until F7) */
240#define MIDITIMECODE 0xf1 /* 1 */
241#define MIDISONGPOS 0xf2 /* 2 */
242#define MIDISONGSELECT 0xf3 /* 1 */
243#define MIDIRESERVED1 0xf4 /* ? */
244#define MIDIRESERVED2 0xf5 /* ? */
245#define MIDITUNEREQUEST 0xf6 /* 0 */
246#define MIDIENDSYSEX 0xf7 /* 0 */
247#define MIDICLOCK 0xf8 /* 0 */
248#define MIDITICK 0xf9 /* 0 */
249#define MIDISTART 0xfa /* 0 */
250#define MIDICONT 0xfb /* 0 */
251#define MIDISTOP 0xfc /* 0 */
252#define MIDIACTIVESENSE 0xfe /* 0 */
253#define MIDIRESET 0xff /* 0 */
254
255 /* functions in x_midi.c */
256void inmidi_realtimein(int portno, int cmd);
257void inmidi_byte(int portno, int byte);
258void inmidi_sysex(int portno, int byte);
259void inmidi_noteon(int portno, int channel, int pitch, int velo);
260void inmidi_controlchange(int portno, int channel, int ctlnumber, int value);
261void inmidi_programchange(int portno, int channel, int value);
262void inmidi_pitchbend(int portno, int channel, int value);
263void inmidi_aftertouch(int portno, int channel, int value);
264void inmidi_polyaftertouch(int portno, int channel, int pitch, int value);
265
266static void sys_dispatchnextmidiin( void)
267{
268 static t_midiparser parser[MAXMIDIINDEV], *parserp;
269 int portno = midi_inqueue[midi_intail].q_portno,
270 byte = midi_inqueue[midi_intail].q_byte1;
271 if (!midi_inqueue[midi_intail].q_onebyte)
272 bug("sys_dispatchnextmidiin");
273 if (portno < 0 || portno >= MAXMIDIINDEV)
274 bug("sys_dispatchnextmidiin 2");
275 parserp = parser + portno;
276 outlet_setstacklim();
277
278 if (byte >= 0xf8)
279 inmidi_realtimein(portno, byte);
280 else
281 {
282 inmidi_byte(portno, byte);
283 if (byte & 0x80)
284 {
285 if (byte == MIDITUNEREQUEST || byte == MIDIRESERVED1 ||
286 byte == MIDIRESERVED2)
287 parserp->mp_status = 0;
288 else if (byte == MIDISTARTSYSEX)
289 {
290 inmidi_sysex(portno, byte);
291 parserp->mp_status = byte;
292 }
293 else if (byte == MIDIENDSYSEX)
294 {
295 inmidi_sysex(portno, byte);
296 parserp->mp_status = 0;
297 }
298 else
299 {
300 parserp->mp_status = byte;
301 }
302 parserp->mp_gotbyte1 = 0;
303 }
304 else
305 {
306 int cmd = (parserp->mp_status >= 0xf0 ? parserp->mp_status :
307 (parserp->mp_status & 0xf0));
308 int chan = (parserp->mp_status & 0xf);
309 int byte1 = parserp->mp_byte1, gotbyte1 = parserp->mp_gotbyte1;
310 switch (cmd)
311 {
312 case MIDINOTEOFF:
313 if (gotbyte1)
314 inmidi_noteon(portno, chan, byte1, 0),
315 parserp->mp_gotbyte1 = 0;
316 else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
317 break;
318 case MIDINOTEON:
319 if (gotbyte1)
320 inmidi_noteon(portno, chan, byte1, byte),
321 parserp->mp_gotbyte1 = 0;
322 else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
323 break;
324 case MIDIPOLYTOUCH:
325 if (gotbyte1)
326 inmidi_polyaftertouch(portno, chan, byte1, byte),
327 parserp->mp_gotbyte1 = 0;
328 else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
329 break;
330 case MIDICONTROLCHANGE:
331 if (gotbyte1)
332 inmidi_controlchange(portno, chan, byte1, byte),
333 parserp->mp_gotbyte1 = 0;
334 else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
335 break;
336 case MIDIPROGRAMCHANGE:
337 inmidi_programchange(portno, chan, byte);
338 break;
339 case MIDICHANNELTOUCH:
340 inmidi_aftertouch(portno, chan, byte);
341 break;
342 case MIDIPITCHBEND:
343 if (gotbyte1)
344 inmidi_pitchbend(portno, chan, ((byte << 7) + byte1)),
345 parserp->mp_gotbyte1 = 0;
346 else parserp->mp_byte1 = byte, parserp->mp_gotbyte1 = 1;
347 break;
348 case MIDISTARTSYSEX:
349 inmidi_sysex(portno, byte);
350 break;
351
352 /* other kinds of messages are just dropped here. We'll
353 need another status byte before we start letting MIDI in
354 again (no running status across "system" messages). */
355 case MIDITIMECODE: /* 1 data byte*/
356 break;
357 case MIDISONGPOS: /* 2 */
358 break;
359 case MIDISONGSELECT: /* 1 */
360 break;
361 }
362 }
363 }
364 midi_intail = (midi_intail + 1 == MIDIQSIZE ? 0 : midi_intail + 1);
365}
366
367void sys_pollmidiinqueue( void)
368{
369#ifdef TEST_DEJITTER
370 static int db = 0;
371#endif
372 double logicaltime = .001 * clock_gettimesince(sys_midiinittime);
373#ifdef TEST_DEJITTER
374 if (midi_inhead == midi_intail)
375 db = 0;
376#endif
377 while (midi_inhead != midi_intail)
378 {
379#ifdef TEST_DEJITTER
380 if (!db)
381 {
382 post("in del %f, logicaltime %f, RT %f adcminusRT %f",
383 (midi_inqueue[midi_intail].q_time - logicaltime),
384 logicaltime, sys_getrealtime(), sys_adctimeminusrealtime);
385 db = 1;
386 }
387#endif
388#if 0
389 if (midi_inqueue[midi_intail].q_time <= logicaltime - 0.007)
390 post("late %f",
391 1000 * (logicaltime - midi_inqueue[midi_intail].q_time));
392#endif
393 if (midi_inqueue[midi_intail].q_time <= logicaltime)
394 {
395#if 0
396 post("diff %f",
397 1000* (logicaltime - midi_inqueue[midi_intail].q_time));
398#endif
399 sys_dispatchnextmidiin();
400 }
401 else break;
402 }
403}
404
405 /* this should be called from the system dependent MIDI code when a byte
406 comes in, as a result of our calling sys_poll_midi. We stick it on a
407 timetag queue and dispatch it at the appropriate logical time. */
408
409
410void sys_midibytein(int portno, int byte)
411{
412 static int warned = 0;
413 t_midiqelem *midiqelem;
414 int newhead = midi_inhead +1;
415 if (newhead == MIDIQSIZE)
416 newhead = 0;
417 /* if FIFO is full flush an element to make room */
418 if (newhead == midi_intail)
419 {
420 if (!warned)
421 {
422 post("warning: MIDI timing FIFO overflowed");
423 warned = 1;
424 }
425 sys_dispatchnextmidiin();
426 }
427 midi_inqueue[midi_inhead].q_portno = portno;
428 midi_inqueue[midi_inhead].q_onebyte = 1;
429 midi_inqueue[midi_inhead].q_byte1 = byte;
430 midi_inqueue[midi_inhead].q_time = sys_getmidiinrealtime();
431 midi_inhead = newhead;
432 sys_pollmidiinqueue();
433}
434
435void sys_pollmidiqueue( void)
436{
437#if 0
438 static double lasttime;
439 double newtime = sys_getrealtime();
440 if (newtime - lasttime > 0.007)
441 post("delay %d", (int)(1000 * (newtime - lasttime)));
442 lasttime = newtime;
443#endif
444 sys_poll_midi(); /* OS dependent poll for MIDI input */
445 sys_pollmidioutqueue();
446 sys_pollmidiinqueue();
447}
448
449/******************** dialog window and device listing ********************/
450
451#ifdef USEAPI_OSS
452void midi_oss_init( void);
453#endif
454
455 /* last requested parameters */
456static int midi_nmidiindev;
457static int midi_midiindev[MAXMIDIINDEV];
458static int midi_nmidioutdev;
459static int midi_midioutdev[MAXMIDIOUTDEV];
460
461static void sys_get_midi_params(int *pnmidiindev, int *pmidiindev,
462 int *pnmidioutdev, int *pmidioutdev)
463{
464 int i;
465 *pnmidiindev = midi_nmidiindev;
466 for (i = 0; i < MAXMIDIINDEV; i++)
467 pmidiindev[i] = midi_midiindev[i];
468 *pnmidioutdev = midi_nmidioutdev;
469 for (i = 0; i < MAXMIDIOUTDEV; i++)
470 pmidioutdev[i] = midi_midioutdev[i];
471}
472
473static void sys_save_midi_params(
474 int nmidiindev, int *midiindev,
475 int nmidioutdev, int *midioutdev)
476{
477 int i;
478 midi_nmidiindev = nmidiindev;
479 for (i = 0; i < MAXMIDIINDEV; i++)
480 midi_midiindev[i] = midiindev[i];
481 midi_nmidioutdev = nmidioutdev;
482 for (i = 0; i < MAXMIDIOUTDEV; i++)
483 midi_midioutdev[i] = midioutdev[i];
484}
485
486void sys_open_midi(int nmidiindev, int *midiindev,
487 int nmidioutdev, int *midioutdev)
488{
489#ifdef USEAPI_OSS
490 midi_oss_init();
491#endif
492 sys_do_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev);
493 sys_save_midi_params(nmidiindev, midiindev,
494 nmidioutdev, midioutdev);
495}
496
497 /* open midi using whatever parameters were last used */
498void sys_reopen_midi( void)
499{
500 int nmidiindev, midiindev[MAXMIDIINDEV];
501 int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
502 sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev);
503 sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev);
504}
505
506#define MAXNDEV 20
507#define DEVDESCSIZE 80
508
509#ifdef MSW
510#define DEVONSET 0 /* microsoft device list starts at 0 (the "mapper"). */
511#else /* (see also MSW ifdef in sys_parsedevlist(), s_main.c) */
512#define DEVONSET 1 /* To agree with command line flags, normally start at 1 */
513#endif
514
515void sys_listmididevs(void )
516{
517 char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
518 int nindevs = 0, noutdevs = 0, i;
519
520 midi_getdevs(indevlist, &nindevs, outdevlist, &noutdevs,
521 MAXNDEV, DEVDESCSIZE);
522
523 if (!nindevs)
524 post("no midi input devices found");
525 else
526 {
527 post("input devices:");
528 for (i = 0; i < nindevs; i++)
529 post("%d. %s", i+1, indevlist + i * DEVDESCSIZE);
530 }
531 if (!noutdevs)
532 post("no midi output devices found");
533 else
534 {
535 post("output devices:");
536 for (i = 0; i < noutdevs; i++)
537 post("%d. %s", i+DEVONSET, outdevlist + i * DEVDESCSIZE);
538 }
539}
540
541extern t_class *glob_pdobject;
542
543 /* start an midi settings dialog window */
544void glob_midi_properties(t_pd *dummy, t_floatarg flongform)
545{
546 char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
547 /* these are the devices you're using: */
548 int nindev, midiindev[MAXMIDIINDEV];
549 int noutdev, midioutdev[MAXMIDIOUTDEV];
550 int midiindev1, midiindev2, midiindev3, midiindev4,
551 midioutdev1, midioutdev2, midioutdev3, midioutdev4;
552
553 /* these are all the devices on your system: */
554 char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
555 int nindevs = 0, noutdevs = 0, i;
556
557 char indevliststring[MAXNDEV*(DEVDESCSIZE+4)+80],
558 outdevliststring[MAXNDEV*(DEVDESCSIZE+4)+80];
559
560 midi_getdevs(indevlist, &nindevs, outdevlist, &noutdevs,
561 MAXNDEV, DEVDESCSIZE);
562
563 strcpy(indevliststring, "{ {none} ");
564 for (i = 0; i < nindevs; i++)
565 {
566 strcat(indevliststring, "\"");
567 strcat(indevliststring, indevlist + i * DEVDESCSIZE);
568 strcat(indevliststring, "\" ");
569 }
570 strcat(indevliststring, "}");
571
572 strcpy(outdevliststring, "{ {none} ");
573 for (i = 0; i < noutdevs; i++)
574 {
575 strcat(outdevliststring, "\"");
576 strcat(outdevliststring, outdevlist + i * DEVDESCSIZE);
577 strcat(outdevliststring, "\" ");
578 }
579 strcat(outdevliststring, "}");
580
581 sys_get_midi_params(&nindev, midiindev, &noutdev, midioutdev);
582
583 if (nindev > 1 || noutdev > 1)
584 flongform = 1;
585
586 midiindev1 = (nindev > 0 && midiindev[0]>= 0 ? midiindev[0]+1 : 0);
587 midiindev2 = (nindev > 1 && midiindev[1]>= 0 ? midiindev[1]+1 : 0);
588 midiindev3 = (nindev > 2 && midiindev[2]>= 0 ? midiindev[2]+1 : 0);
589 midiindev4 = (nindev > 3 && midiindev[3]>= 0 ? midiindev[3]+1 : 0);
590 midioutdev1 = (noutdev > 0 && midioutdev[0]>=0 ? midioutdev[0]+1 : 0);
591 midioutdev2 = (noutdev > 1 && midioutdev[1]>=0 ? midioutdev[1]+1 : 0);
592 midioutdev3 = (noutdev > 2 && midioutdev[2]>=0 ? midioutdev[2]+1 : 0);
593 midioutdev4 = (noutdev > 3 && midioutdev[3]>=0 ? midioutdev[3]+1 : 0);
594
595 sprintf(buf,
596"pdtk_midi_dialog %%s \
597%s %d %d %d %d %s %d %d %d %d \
598%d\n",
599 indevliststring,
600 midiindev1, midiindev2, midiindev3, midiindev4,
601 outdevliststring,
602 midioutdev1, midioutdev2, midioutdev3, midioutdev4,
603 (flongform != 0));
604 gfxstub_deleteforkey(0);
605 gfxstub_new(&glob_pdobject, glob_midi_properties, buf);
606}
607
608 /* new values from dialog window */
609void glob_midi_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
610{
611 int nmidiindev, midiindev[MAXMIDIINDEV];
612 int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
613 int i, nindev, noutdev;
614 int newmidiindev[4], newmidioutdev[4];
615
616 for (i = 0; i < 4; i++)
617 {
618 newmidiindev[i] = atom_getintarg(i, argc, argv);
619 newmidioutdev[i] = atom_getintarg(i+4, argc, argv);
620 }
621
622 for (i = 0, nindev = 0; i < 4; i++)
623 {
624 if (newmidiindev[i] > 0)
625 {
626 newmidiindev[nindev] = newmidiindev[i]-1;
627 nindev++;
628 }
629 }
630 for (i = 0, noutdev = 0; i < 4; i++)
631 {
632 if (newmidioutdev[i] > 0)
633 {
634 newmidioutdev[noutdev] = newmidioutdev[i]-1;
635 noutdev++;
636 }
637 }
638
639 sys_close_midi();
640 sys_open_midi(nindev, newmidiindev, noutdev, newmidioutdev);
641}
642