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