1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 alsaseq_c.c - ALSA sequencer server interface
21 Copyright (c) 2000 Takashi Iwai <tiwai@suse.de>
22
23 This interface provides an ALSA sequencer client which receives
24 events and plays it in real-time. On this mode, TiMidity works
25 as a software (quasi-)real-time MIDI synth engine.
26
27 See doc/C/README.alsaseq for more details.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif /* HAVE_CONFIG_H */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <unistd.h>
38 #include <sched.h>
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #ifndef NO_STRING_H
42 #include <string.h>
43 #else
44 #include <strings.h>
45 #endif
46 #include <math.h>
47 #include <signal.h>
48
49 #if HAVE_ALSA_ASOUNDLIB_H
50 #include <alsa/asoundlib.h>
51 #else
52 #include <sys/asoundlib.h>
53 #endif
54
55 #include "timidity.h"
56 #include "common.h"
57 #include "controls.h"
58 #include "instrum.h"
59 #include "playmidi.h"
60 #include "readmidi.h"
61 #include "recache.h"
62 #include "output.h"
63 #include "aq.h"
64 #include "timer.h"
65
66
67 void readmidi_read_init(void);
68
69 #define MAX_PORTS 16
70
71 #define TICKTIME_HZ 100
72
73 struct seq_context {
74 snd_seq_t *handle; /* The snd_seq handle to /dev/snd/seq */
75 int client; /* The client associated with this context */
76 int num_ports; /* number of ports */
77 int port[MAX_PORTS]; /* created sequencer ports */
78 int fd; /* The file descriptor */
79 int used; /* number of current connection */
80 int active; /* */
81 int queue;
82 snd_seq_queue_status_t *q_status;
83 };
84
85 static struct seq_context alsactx;
86
87 #if SND_LIB_MAJOR > 0 || SND_LIB_MINOR >= 6
88 /* !! this is a dirty hack. not sure to work in future !! */
snd_seq_file_descriptor(snd_seq_t * handle)89 static int snd_seq_file_descriptor(snd_seq_t *handle)
90 {
91 int pfds = snd_seq_poll_descriptors_count(handle, POLLIN);
92 if (pfds > 0) {
93 struct pollfd pfd;
94 if (snd_seq_poll_descriptors(handle, &pfd, 1, POLLIN) >= 0)
95 return pfd.fd;
96 }
97 return -ENXIO;
98 }
99
alsa_seq_open(snd_seq_t ** seqp)100 static int alsa_seq_open(snd_seq_t **seqp)
101 {
102 return snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0);
103 }
104
alsa_create_port(snd_seq_t * seq,int index)105 static int alsa_create_port(snd_seq_t *seq, int index)
106 {
107 char name[32];
108 int port;
109
110 sprintf(name, "TiMidity port %d", index);
111 port = snd_seq_create_simple_port(seq, name,
112 SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
113 SND_SEQ_PORT_TYPE_MIDI_GENERIC);
114 if (port < 0) {
115 fprintf(stderr, "error in snd_seq_create_simple_port\n");
116 return -1;
117 }
118
119 return port;
120 }
121
122 #else
alsa_seq_open(snd_seq_t ** seqp)123 static int alsa_seq_open(snd_seq_t **seqp)
124 {
125 return snd_seq_open(seqp, SND_SEQ_OPEN_IN);
126 }
127
alsa_create_port(snd_seq_t * seq,int index)128 static int alsa_create_port(snd_seq_t *seq, int index)
129 {
130 snd_seq_port_info_t pinfo;
131
132 memset(&pinfo, 0, sizeof(pinfo));
133 sprintf(pinfo.name, "TiMidity port %d", index);
134 pinfo.capability = SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE;
135 pinfo.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC;
136 strcpy(pinfo.group, SND_SEQ_GROUP_DEVICE);
137 if (snd_seq_create_port(alsactx.handle, &pinfo) < 0) {
138 fprintf(stderr, "error in snd_seq_create_simple_port\n");
139 return -1;
140 }
141 return pinfo.port;
142 }
143
144 #endif
145
alsa_set_timestamping(struct seq_context * ctxp,int port)146 static void alsa_set_timestamping(struct seq_context *ctxp, int port)
147 {
148 #if HAVE_SND_SEQ_PORT_INFO_SET_TIMESTAMPING
149 int q = 0;
150 snd_seq_port_info_t *pinfo;
151
152 if (ctxp->queue < 0) {
153 q = snd_seq_alloc_queue(ctxp->handle);
154 ctxp->queue = q;
155 if (q < 0)
156 return;
157 if (snd_seq_queue_status_malloc(&ctxp->q_status) < 0) {
158 fprintf(stderr, "no memory!\n");
159 exit(1);
160 }
161 }
162
163 snd_seq_port_info_alloca(&pinfo);
164 if (snd_seq_get_port_info(ctxp->handle, port, pinfo) < 0)
165 return;
166 snd_seq_port_info_set_timestamping(pinfo, 1);
167 snd_seq_port_info_set_timestamp_real(pinfo, 1);
168 snd_seq_port_info_set_timestamp_queue(pinfo, q);
169 if (snd_seq_set_port_info(ctxp->handle, port, pinfo) < 0)
170 return;
171 #endif
172 }
173
174
175 static int ctl_open(int using_stdin, int using_stdout);
176 static void ctl_close(void);
177 static int ctl_read(int32 *valp);
178 static int cmsg(int type, int verbosity_level, char *fmt, ...);
179 static void ctl_event(CtlEvent *e);
180 static int ctl_pass_playing_list(int n, char *args[]);
181
182 /**********************************/
183 /* export the interface functions */
184
185 #define ctl alsaseq_control_mode
186
187 ControlMode ctl=
188 {
189 "ALSA sequencer interface", 'A',
190 "alsaseq",
191 1,0,0,
192 0,
193 ctl_open,
194 ctl_close,
195 ctl_pass_playing_list,
196 ctl_read,
197 NULL,
198 cmsg,
199 ctl_event
200 };
201
202 /* options */
203 int opt_realtime_priority = 0;
204 int opt_sequencer_ports = 4;
205
206 static int buffer_time_advance;
207 static long buffer_time_offset;
208 static long start_time_base;
209 static long cur_time_offset;
210 static long last_queue_offset;
211 static double rate_frac, rate_frac_nsec;
212 static FILE *outfp;
213
214 /*ARGSUSED*/
ctl_open(int using_stdin,int using_stdout)215 static int ctl_open(int using_stdin, int using_stdout)
216 {
217 ctl.opened = 1;
218 ctl.flags &= ~(CTLF_LIST_RANDOM|CTLF_LIST_SORT);
219 if (using_stdout)
220 outfp = stderr;
221 else
222 outfp = stdout;
223 return 0;
224 }
225
ctl_close(void)226 static void ctl_close(void)
227 {
228 if (!ctl.opened)
229 return;
230 }
231
ctl_read(int32 * valp)232 static int ctl_read(int32 *valp)
233 {
234 return RC_NONE;
235 }
236
cmsg(int type,int verbosity_level,char * fmt,...)237 static int cmsg(int type, int verbosity_level, char *fmt, ...)
238 {
239 va_list ap;
240
241 if((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
242 ctl.verbosity < verbosity_level)
243 return 0;
244
245 if(outfp == NULL)
246 outfp = stderr;
247
248 va_start(ap, fmt);
249 vfprintf(outfp, fmt, ap);
250 fputs(NLS, outfp);
251 fflush(outfp);
252 va_end(ap);
253
254 return 0;
255 }
256
ctl_event(CtlEvent * e)257 static void ctl_event(CtlEvent *e)
258 {
259 }
260
sig_timeout(int sig)261 static RETSIGTYPE sig_timeout(int sig)
262 {
263 signal(SIGALRM, sig_timeout); /* For SysV base */
264 /* Expect EINTR */
265 }
266
267 static void doit(struct seq_context *ctxp);
268 static int do_sequencer(struct seq_context *ctxp);
269 static int start_sequencer(struct seq_context *ctxp);
270 static void stop_sequencer(struct seq_context *ctxp);
271 static void server_reset(void);
272
273 /* reset all when SIGHUP is received */
sig_reset(int sig)274 static RETSIGTYPE sig_reset(int sig)
275 {
276 if (alsactx.active) {
277 stop_sequencer(&alsactx);
278 server_reset();
279 }
280 signal(SIGHUP, sig_reset);
281 }
282
283 /*
284 * set the process to realtime privs
285 */
set_realtime_priority(void)286 static int set_realtime_priority(void)
287 {
288 struct sched_param schp;
289 int max_prio;
290
291 if (opt_realtime_priority <= 0)
292 return 0;
293
294 memset(&schp, 0, sizeof(schp));
295 max_prio = sched_get_priority_max(SCHED_FIFO);
296 if (max_prio < opt_realtime_priority)
297 opt_realtime_priority = max_prio;
298
299 schp.sched_priority = opt_realtime_priority;
300 if (sched_setscheduler(0, SCHED_FIFO, &schp) != 0) {
301 printf("can't set sched_setscheduler - using normal priority\n");
302 return -1;
303 }
304 /* drop root priv. */
305 if (! geteuid() && getuid() != geteuid()) {
306 if (setuid(getuid()))
307 perror("dropping root priv");
308 }
309 printf("set SCHED_FIFO(%d)\n", opt_realtime_priority);
310 return 0;
311 }
312
ctl_pass_playing_list(int n,char * args[])313 static int ctl_pass_playing_list(int n, char *args[])
314 {
315 double btime;
316 int i, j;
317
318 #ifdef SIGPIPE
319 signal(SIGPIPE, SIG_IGN); /* Handle broken pipe */
320 #endif /* SIGPIPE */
321
322 printf("TiMidity starting in ALSA server mode\n");
323
324 set_realtime_priority();
325
326 if (alsa_seq_open(&alsactx.handle) < 0) {
327 fprintf(stderr, "error in snd_seq_open\n");
328 return 1;
329 }
330 alsactx.queue = -1;
331 alsactx.client = snd_seq_client_id(alsactx.handle);
332 alsactx.fd = snd_seq_file_descriptor(alsactx.handle);
333 snd_seq_set_client_name(alsactx.handle, "TiMidity");
334 snd_seq_set_client_pool_input(alsactx.handle, 1000); /* enough? */
335 if (opt_sequencer_ports < 1)
336 alsactx.num_ports = 1;
337 else if (opt_sequencer_ports > MAX_PORTS)
338 alsactx.num_ports = MAX_PORTS;
339 else
340 alsactx.num_ports = opt_sequencer_ports;
341
342 printf("Opening sequencer port:");
343 for (i = 0; i < alsactx.num_ports; i++) {
344 int port;
345 port = alsa_create_port(alsactx.handle, i);
346 if (port < 0)
347 return 1;
348 alsactx.port[i] = port;
349 alsa_set_timestamping(&alsactx, port);
350 printf(" %d:%d", alsactx.client, alsactx.port[i]);
351 }
352 printf("\n");
353
354 alsactx.used = 0;
355 alsactx.active = 0;
356
357 opt_realtime_playing = 1; /* Enable loading patch while playing */
358 allocate_cache_size = 0; /* Don't use pre-calclated samples */
359 current_keysig = (opt_init_keysig == 8) ? 0 : opt_init_keysig;
360 note_key_offset = key_adjust;
361
362 if (IS_STREAM_TRACE) {
363 /* set the audio queue size as minimum as possible, since
364 * we don't have to use audio queue..
365 */
366 play_mode->acntl(PM_REQ_GETFRAGSIZ, &buffer_time_advance);
367 if (!(play_mode->encoding & PE_MONO))
368 buffer_time_advance >>= 1;
369 if (play_mode->encoding & PE_16BIT)
370 buffer_time_advance >>= 1;
371
372 btime = (double)buffer_time_advance / play_mode->rate;
373 btime *= 1.01; /* to be sure */
374 aq_set_soft_queue(btime, 0.0);
375 } else {
376 buffer_time_advance = 0;
377 }
378 rate_frac = (double)play_mode->rate / 1000000.0;
379 rate_frac_nsec = (double)play_mode->rate / 1000000000.0;
380
381 alarm(0);
382 signal(SIGALRM, sig_timeout);
383 signal(SIGINT, safe_exit);
384 signal(SIGTERM, safe_exit);
385 signal(SIGHUP, sig_reset);
386
387 i = current_keysig + ((current_keysig < 8) ? 7 : -9), j = 0;
388 while (i != 7)
389 i += (i < 7) ? 5 : -7, j++;
390 j += note_key_offset, j -= floor(j / 12.0) * 12;
391 current_freq_table = j;
392
393 for (;;) {
394 server_reset();
395 doit(&alsactx);
396 }
397 return 0;
398 }
399
400 /*
401 * get the current time in usec from gettimeofday()
402 */
get_current_time(void)403 static long get_current_time(void)
404 {
405 struct timeval tv;
406 long t;
407
408 gettimeofday(&tv, NULL);
409 t = tv.tv_sec * 1000000L + tv.tv_usec;
410 return t - start_time_base;
411 }
412
413 /*
414 * convert from snd_seq_real_time_t to sample count
415 */
queue_time_to_position(const snd_seq_real_time_t * t)416 inline static long queue_time_to_position(const snd_seq_real_time_t *t)
417 {
418 return (long)t->tv_sec * play_mode->rate + (long)(t->tv_nsec * rate_frac_nsec);
419 }
420
421 /*
422 * get the current queue position in sample count
423 */
get_current_queue_position(struct seq_context * ctxp)424 static long get_current_queue_position(struct seq_context *ctxp)
425 {
426 #if HAVE_SND_SEQ_PORT_INFO_SET_TIMESTAMPING
427 snd_seq_get_queue_status(ctxp->handle, ctxp->queue, ctxp->q_status);
428 return queue_time_to_position(snd_seq_queue_status_get_real_time(ctxp->q_status));
429 #else
430 return 0;
431 #endif
432 }
433
434 /*
435 * update the current position from the event timestamp
436 */
update_timestamp_from_event(snd_seq_event_t * ev)437 static void update_timestamp_from_event(snd_seq_event_t *ev)
438 {
439 long t = queue_time_to_position(&ev->time.time) - last_queue_offset;
440 if (t < 0) {
441 // fprintf(stderr, "timestamp underflow! (delta=%d)\n", (int)t);
442 t = 0;
443 } else if (buffer_time_advance > 0 && t >= buffer_time_advance) {
444 // fprintf(stderr, "timestamp overflow! (delta=%d)\n", (int)t);
445 t = buffer_time_advance - 1;
446 }
447 t += buffer_time_offset;
448 if (t >= cur_time_offset)
449 cur_time_offset = t;
450 }
451
452 /*
453 * update the current position from system time
454 */
update_timestamp(void)455 static void update_timestamp(void)
456 {
457 cur_time_offset = (long)(get_current_time() * rate_frac);
458 }
459
seq_play_event(MidiEvent * ev)460 static void seq_play_event(MidiEvent *ev)
461 {
462 //JAVE make channel -Q channels quiet, modified some code from readmidi.c
463 int gch;
464 gch = GLOBAL_CHANNEL_EVENT_TYPE(ev->type);
465
466 if (gch || !IS_SET_CHANNELMASK(quietchannels, ev->channel)){
467 //if its a global event or not a masked event
468 ev->time = cur_time_offset;
469 play_event(ev);
470 }
471 }
472
stop_playing(void)473 static void stop_playing(void)
474 {
475 if(upper_voices) {
476 MidiEvent ev;
477 ev.type = ME_EOT;
478 ev.a = 0;
479 ev.b = 0;
480 seq_play_event(&ev);
481 aq_flush(0);
482 }
483 }
484
doit(struct seq_context * ctxp)485 static void doit(struct seq_context *ctxp)
486 {
487 for (;;) {
488 while (snd_seq_event_input_pending(ctxp->handle, 1)) {
489 if (do_sequencer(ctxp))
490 goto __done;
491 }
492 if (ctxp->active) {
493 MidiEvent ev;
494
495 if (IS_STREAM_TRACE) {
496 /* remember the last update position */
497 if (ctxp->queue >= 0)
498 last_queue_offset = get_current_queue_position(ctxp);
499 /* advance the buffer position */
500 buffer_time_offset += buffer_time_advance;
501 ev.time = buffer_time_offset;
502 } else {
503 /* update the current position */
504 if (ctxp->queue >= 0)
505 cur_time_offset = get_current_queue_position(ctxp);
506 else
507 update_timestamp();
508 ev.time = cur_time_offset;
509 }
510 ev.type = ME_NONE;
511 play_event(&ev);
512 aq_fill_nonblocking();
513 }
514 if (! ctxp->active || ! IS_STREAM_TRACE) {
515 fd_set rfds;
516 FD_ZERO(&rfds);
517 FD_SET(ctxp->fd, &rfds);
518 if (! IS_STREAM_TRACE) {
519 struct timeval timeout;
520 timeout.tv_sec = 0;
521 timeout.tv_usec = 10000; /* 10ms */
522 if (select(ctxp->fd + 1, &rfds, NULL, NULL, &timeout) < 0)
523 goto __done;
524 } else {
525 if (select(ctxp->fd + 1, &rfds, NULL, NULL, NULL) < 0)
526 goto __done;
527 }
528 }
529 }
530
531 __done:
532 if (ctxp->active) {
533 stop_sequencer(ctxp);
534 }
535 }
536
server_reset(void)537 static void server_reset(void)
538 {
539 readmidi_read_init();
540 playmidi_stream_init();
541 if (free_instruments_afterwards)
542 free_instruments(0);
543 reduce_voice_threshold = 0; /* Disable auto reduction voice */
544 buffer_time_offset = 0;
545 }
546
start_sequencer(struct seq_context * ctxp)547 static int start_sequencer(struct seq_context *ctxp)
548 {
549 if (play_mode->acntl(PM_REQ_PLAY_START, NULL) < 0) {
550 ctl.cmsg(CMSG_FATAL, VERB_NORMAL,
551 "Couldn't start %s (`%c')",
552 play_mode->id_name, play_mode->id_character);
553 return 0;
554 }
555 ctxp->active = 1;
556
557 buffer_time_offset = 0;
558 last_queue_offset = 0;
559 cur_time_offset = 0;
560 if (ctxp->queue >= 0) {
561 if (snd_seq_start_queue(ctxp->handle, ctxp->queue, NULL) < 0)
562 ctxp->queue = -1;
563 else
564 snd_seq_drain_output(ctxp->handle);
565 }
566 if (ctxp->queue < 0) {
567 start_time_base = 0;
568 start_time_base = get_current_time();
569 }
570
571 return 1;
572 }
573
stop_sequencer(struct seq_context * ctxp)574 static void stop_sequencer(struct seq_context *ctxp)
575 {
576 stop_playing();
577 if (ctxp->queue >= 0) {
578 snd_seq_stop_queue(ctxp->handle, ctxp->queue, NULL);
579 snd_seq_drain_output(ctxp->handle);
580 }
581 play_mode->acntl(PM_REQ_PLAY_END, NULL);
582 free_instruments(0);
583 free_global_mblock();
584 ctxp->used = 0;
585 ctxp->active = 0;
586 }
587
588 #define NOTE_CHAN(ev) ((ev)->dest.port * 16 + (ev)->data.note.channel)
589 #define CTRL_CHAN(ev) ((ev)->dest.port * 16 + (ev)->data.control.channel)
590
do_sequencer(struct seq_context * ctxp)591 static int do_sequencer(struct seq_context *ctxp)
592 {
593 int n, ne, i;
594 MidiEvent ev, evm[260];
595 snd_seq_event_t *aevp;
596
597 n = snd_seq_event_input(ctxp->handle, &aevp);
598 if (n < 0 || aevp == NULL)
599 return 0;
600
601 if (ctxp->active && ctxp->queue >= 0)
602 update_timestamp_from_event(aevp);
603 else if (IS_STREAM_TRACE)
604 cur_time_offset = buffer_time_offset;
605 else
606 update_timestamp();
607
608 switch(aevp->type) {
609 case SND_SEQ_EVENT_NOTEON:
610 ev.channel = NOTE_CHAN(aevp);
611 ev.a = aevp->data.note.note;
612 ev.b = aevp->data.note.velocity;
613 if (ev.b == 0)
614 ev.type = ME_NOTEOFF;
615 else
616 ev.type = ME_NOTEON;
617 seq_play_event(&ev);
618 break;
619
620 case SND_SEQ_EVENT_NOTEOFF:
621 ev.channel = NOTE_CHAN(aevp);
622 ev.a = aevp->data.note.note;
623 ev.b = aevp->data.note.velocity;
624 ev.type = ME_NOTEOFF;
625 seq_play_event(&ev);
626 break;
627
628 case SND_SEQ_EVENT_KEYPRESS:
629 ev.channel = NOTE_CHAN(aevp);
630 ev.a = aevp->data.note.note;
631 ev.b = aevp->data.note.velocity;
632 ev.type = ME_KEYPRESSURE;
633 seq_play_event(&ev);
634 break;
635
636 case SND_SEQ_EVENT_PGMCHANGE:
637 ev.channel = CTRL_CHAN(aevp);
638 ev.a = aevp->data.control.value;
639 ev.type = ME_PROGRAM;
640 seq_play_event(&ev);
641 break;
642
643 case SND_SEQ_EVENT_CONTROLLER:
644 if(convert_midi_control_change(CTRL_CHAN(aevp),
645 aevp->data.control.param,
646 aevp->data.control.value,
647 &ev))
648 seq_play_event(&ev);
649 break;
650
651 case SND_SEQ_EVENT_CONTROL14:
652 if (aevp->data.control.param < 0 || aevp->data.control.param >= 32)
653 break;
654 if (! convert_midi_control_change(CTRL_CHAN(aevp),
655 aevp->data.control.param,
656 (aevp->data.control.value >> 7) & 0x7f,
657 &ev))
658 break;
659 seq_play_event(&ev);
660 if (! convert_midi_control_change(CTRL_CHAN(aevp),
661 aevp->data.control.param + 32,
662 aevp->data.control.value & 0x7f,
663 &ev))
664 break;
665 seq_play_event(&ev);
666 break;
667
668 case SND_SEQ_EVENT_PITCHBEND:
669 ev.type = ME_PITCHWHEEL;
670 ev.channel = CTRL_CHAN(aevp);
671 aevp->data.control.value += 0x2000;
672 ev.a = (aevp->data.control.value) & 0x7f;
673 ev.b = (aevp->data.control.value>>7) & 0x7f;
674 seq_play_event(&ev);
675 break;
676
677 case SND_SEQ_EVENT_CHANPRESS:
678 ev.type = ME_CHANNEL_PRESSURE;
679 ev.channel = CTRL_CHAN(aevp);
680 ev.a = aevp->data.control.value;
681 seq_play_event(&ev);
682 break;
683
684 case SND_SEQ_EVENT_NONREGPARAM:
685 /* Break it back into its controler values */
686 ev.type = ME_NRPN_MSB;
687 ev.channel = CTRL_CHAN(aevp);
688 ev.a = (aevp->data.control.param >> 7) & 0x7f;
689 seq_play_event(&ev);
690 ev.type = ME_NRPN_LSB;
691 ev.channel = CTRL_CHAN(aevp);
692 ev.a = aevp->data.control.param & 0x7f;
693 seq_play_event(&ev);
694 ev.type = ME_DATA_ENTRY_MSB;
695 ev.channel = CTRL_CHAN(aevp);
696 ev.a = (aevp->data.control.value >> 7) & 0x7f;
697 seq_play_event(&ev);
698 ev.type = ME_DATA_ENTRY_LSB;
699 ev.channel = CTRL_CHAN(aevp);
700 ev.a = aevp->data.control.value & 0x7f;
701 seq_play_event(&ev);
702 break;
703
704 case SND_SEQ_EVENT_REGPARAM:
705 /* Break it back into its controler values */
706 ev.type = ME_RPN_MSB;
707 ev.channel = CTRL_CHAN(aevp);
708 ev.a = (aevp->data.control.param >> 7) & 0x7f;
709 seq_play_event(&ev);
710 ev.type = ME_RPN_LSB;
711 ev.channel = CTRL_CHAN(aevp);
712 ev.a = aevp->data.control.param & 0x7f;
713 seq_play_event(&ev);
714 ev.type = ME_DATA_ENTRY_MSB;
715 ev.channel = CTRL_CHAN(aevp);
716 ev.a = (aevp->data.control.value >> 7) & 0x7f;
717 seq_play_event(&ev);
718 ev.type = ME_DATA_ENTRY_LSB;
719 ev.channel = CTRL_CHAN(aevp);
720 ev.a = aevp->data.control.value & 0x7f;
721 seq_play_event(&ev);
722 break;
723
724 case SND_SEQ_EVENT_SYSEX:
725 if (parse_sysex_event(aevp->data.ext.ptr + 1,
726 aevp->data.ext.len - 1, &ev))
727 seq_play_event(&ev);
728 if ((ne = parse_sysex_event_multi(aevp->data.ext.ptr + 1,
729 aevp->data.ext.len - 1, evm)) > 0)
730 for (i = 0; i < ne; i++)
731 seq_play_event(&evm[i]);
732 break;
733
734 #if SND_LIB_MAJOR > 0 || SND_LIB_MINOR >= 6
735 #define snd_seq_addr_equal(a,b) ((a)->client == (b)->client && (a)->port == (b)->port)
736 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
737 if (snd_seq_addr_equal(&aevp->data.connect.dest, &aevp->dest)) {
738 if (! ctxp->active) {
739 if (! start_sequencer(ctxp)) {
740 snd_seq_free_event(aevp);
741 return 0;
742 }
743 }
744 ctxp->used++;
745 }
746 break;
747
748 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
749 if (snd_seq_addr_equal(&aevp->data.connect.dest, &aevp->dest)) {
750 if (ctxp->active) {
751 ctxp->used--;
752 if (ctxp->used <= 0) {
753 snd_seq_free_event(aevp);
754 return 1; /* quit now */
755 }
756 }
757 }
758 break;
759 #else
760 case SND_SEQ_EVENT_PORT_USED:
761 if (! ctxp->active) {
762 if (! start_sequencer(ctxp)) {
763 snd_seq_free_event(aevp);
764 return 0;
765 }
766 }
767 ctxp->used++;
768 break;
769
770 case SND_SEQ_EVENT_PORT_UNUSED:
771 if (ctxp->active) {
772 ctxp->used--;
773 if (ctxp->used <= 0) {
774 snd_seq_free_event(aevp);
775 return 1; /* quit now */
776 }
777 }
778 break;
779 #endif
780
781 default:
782 /*printf("Unsupported event %d\n", aevp->type);*/
783 break;
784 }
785 snd_seq_free_event(aevp);
786 return 0;
787 }
788
789 /*
790 * interface_<id>_loader();
791 */
interface_A_loader(void)792 ControlMode *interface_A_loader(void)
793 {
794 return &ctl;
795 }
796