2 * OSS compatible sequencer driver
4 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
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.
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.
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
21 #include "seq_oss_device.h"
22 #include "seq_oss_synth.h"
23 #include "seq_oss_midi.h"
24 #include "seq_oss_event.h"
25 #include "seq_oss_timer.h"
26 #include <sound/seq_oss_legacy.h>
27 #include "seq_oss_readq.h"
28 #include "seq_oss_writeq.h"
34 static int extended_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
);
35 static int chn_voice_event(struct seq_oss_devinfo
*dp
, union evrec
*event_rec
, struct snd_seq_event
*ev
);
36 static int chn_common_event(struct seq_oss_devinfo
*dp
, union evrec
*event_rec
, struct snd_seq_event
*ev
);
37 static int timing_event(struct seq_oss_devinfo
*dp
, union evrec
*event_rec
, struct snd_seq_event
*ev
);
38 static int local_event(struct seq_oss_devinfo
*dp
, union evrec
*event_rec
, struct snd_seq_event
*ev
);
39 static int old_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
);
40 static int note_on_event(struct seq_oss_devinfo
*dp
, int dev
, int ch
, int note
, int vel
, struct snd_seq_event
*ev
);
41 static int note_off_event(struct seq_oss_devinfo
*dp
, int dev
, int ch
, int note
, int vel
, struct snd_seq_event
*ev
);
42 static int set_note_event(struct seq_oss_devinfo
*dp
, int dev
, int type
, int ch
, int note
, int vel
, struct snd_seq_event
*ev
);
43 static int set_control_event(struct seq_oss_devinfo
*dp
, int dev
, int type
, int ch
, int param
, int val
, struct snd_seq_event
*ev
);
44 static int set_echo_event(struct seq_oss_devinfo
*dp
, union evrec
*rec
, struct snd_seq_event
*ev
);
48 * convert an OSS event to ALSA event
50 * non-zero : invalid - ignored
54 snd_seq_oss_process_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
58 return extended_event(dp
, q
, ev
);
61 return chn_voice_event(dp
, q
, ev
);
64 return chn_common_event(dp
, q
, ev
);
67 return timing_event(dp
, q
, ev
);
70 return local_event(dp
, q
, ev
);
73 return snd_seq_oss_synth_sysex(dp
, q
->x
.dev
, q
->x
.buf
, ev
);
76 if (dp
->seq_mode
== SNDRV_SEQ_OSS_MODE_MUSIC
)
79 if (! is_write_mode(dp
->file_mode
))
81 if (snd_seq_oss_midi_open(dp
, q
->s
.dev
, SNDRV_SEQ_OSS_FILE_WRITE
))
83 if (snd_seq_oss_midi_filemode(dp
, q
->s
.dev
) & SNDRV_SEQ_OSS_FILE_WRITE
)
84 return snd_seq_oss_midi_putc(dp
, q
->s
.dev
, q
->s
.parm1
, ev
);
88 if (dp
->seq_mode
== SNDRV_SEQ_OSS_MODE_MUSIC
)
90 return set_echo_event(dp
, q
, ev
);
93 if (dp
->seq_mode
== SNDRV_SEQ_OSS_MODE_MUSIC
)
95 return snd_seq_oss_synth_raw_event(dp
, q
->c
[1], q
->c
, ev
);
98 if (dp
->seq_mode
== SNDRV_SEQ_OSS_MODE_MUSIC
)
100 return old_event(dp
, q
, ev
);
105 /* old type events: mode1 only */
107 old_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
111 return note_off_event(dp
, 0, q
->n
.chn
, q
->n
.note
, q
->n
.vel
, ev
);
114 return note_on_event(dp
, 0, q
->n
.chn
, q
->n
.note
, q
->n
.vel
, ev
);
121 return set_control_event(dp
, 0, SNDRV_SEQ_EVENT_PGMCHANGE
,
122 q
->n
.chn
, 0, q
->n
.note
, ev
);
125 return snd_seq_oss_timer_reset(dp
->timer
);
131 /* 8bytes extended event: mode1 only */
133 extended_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
139 return note_off_event(dp
, q
->e
.dev
, q
->e
.chn
, q
->e
.p1
, q
->e
.p2
, ev
);
142 return note_on_event(dp
, q
->e
.dev
, q
->e
.chn
, q
->e
.p1
, q
->e
.p2
, ev
);
145 return set_control_event(dp
, q
->e
.dev
, SNDRV_SEQ_EVENT_PGMCHANGE
,
146 q
->e
.chn
, 0, q
->e
.p1
, ev
);
149 return set_control_event(dp
, q
->e
.dev
, SNDRV_SEQ_EVENT_CHANPRESS
,
150 q
->e
.chn
, 0, q
->e
.p1
, ev
);
153 /* convert -128:127 to 0:127 */
155 val
= (val
+ 128) / 2;
156 return set_control_event(dp
, q
->e
.dev
, SNDRV_SEQ_EVENT_CONTROLLER
,
157 q
->e
.chn
, CTL_PAN
, val
, ev
);
160 val
= ((short)q
->e
.p3
<< 8) | (short)q
->e
.p2
;
162 case CTRL_PITCH_BENDER
: /* SEQ1 V2 control */
164 return set_control_event(dp
, q
->e
.dev
,
165 SNDRV_SEQ_EVENT_PITCHBEND
,
166 q
->e
.chn
, 0, val
, ev
);
167 case CTRL_PITCH_BENDER_RANGE
:
168 /* conversion: 100/semitone -> 128/semitone */
169 return set_control_event(dp
, q
->e
.dev
,
170 SNDRV_SEQ_EVENT_REGPARAM
,
171 q
->e
.chn
, 0, val
*128/100, ev
);
173 return set_control_event(dp
, q
->e
.dev
,
174 SNDRV_SEQ_EVENT_CONTROL14
,
175 q
->e
.chn
, q
->e
.p1
, val
, ev
);
179 return snd_seq_oss_synth_raw_event(dp
, q
->e
.dev
, q
->c
, ev
);
185 /* channel voice events: mode1 and 2 */
187 chn_voice_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
193 return note_on_event(dp
, q
->v
.dev
, q
->v
.chn
, q
->v
.note
, q
->v
.parm
, ev
);
196 return note_off_event(dp
, q
->v
.dev
, q
->v
.chn
, q
->v
.note
, q
->v
.parm
, ev
);
198 case MIDI_KEY_PRESSURE
:
199 return set_note_event(dp
, q
->v
.dev
, SNDRV_SEQ_EVENT_KEYPRESS
,
200 q
->v
.chn
, q
->v
.note
, q
->v
.parm
, ev
);
206 /* channel common events: mode1 and 2 */
208 chn_common_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
213 case MIDI_PGM_CHANGE
:
214 return set_control_event(dp
, q
->l
.dev
, SNDRV_SEQ_EVENT_PGMCHANGE
,
215 q
->l
.chn
, 0, q
->l
.p1
, ev
);
217 case MIDI_CTL_CHANGE
:
218 return set_control_event(dp
, q
->l
.dev
, SNDRV_SEQ_EVENT_CONTROLLER
,
219 q
->l
.chn
, q
->l
.p1
, q
->l
.val
, ev
);
221 case MIDI_PITCH_BEND
:
222 /* conversion: 0:0x3fff -> -0x2000:0x1fff */
223 return set_control_event(dp
, q
->l
.dev
, SNDRV_SEQ_EVENT_PITCHBEND
,
224 q
->l
.chn
, 0, q
->l
.val
- 8192, ev
);
226 case MIDI_CHN_PRESSURE
:
227 return set_control_event(dp
, q
->l
.dev
, SNDRV_SEQ_EVENT_CHANPRESS
,
228 q
->l
.chn
, 0, q
->l
.val
, ev
);
233 /* timer events: mode1 and mode2 */
235 timing_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
239 if (dp
->seq_mode
== SNDRV_SEQ_OSS_MODE_MUSIC
)
240 return set_echo_event(dp
, q
, ev
);
243 memset(&tmp
, 0, sizeof(tmp
));
244 /* XXX: only for little-endian! */
245 tmp
.echo
= (q
->t
.time
<< 8) | SEQ_ECHO
;
246 return set_echo_event(dp
, &tmp
, ev
);
251 return snd_seq_oss_timer_stop(dp
->timer
);
256 return snd_seq_oss_timer_continue(dp
->timer
);
261 return snd_seq_oss_timer_tempo(dp
->timer
, q
->t
.time
);
268 /* local events: mode1 and 2 */
270 local_event(struct seq_oss_devinfo
*dp
, union evrec
*q
, struct snd_seq_event
*ev
)
276 * process note-on event for OSS synth
277 * three different modes are available:
278 * - SNDRV_SEQ_OSS_PROCESS_EVENTS (for one-voice per channel mode)
279 * Accept note 255 as volume change.
280 * - SNDRV_SEQ_OSS_PASS_EVENTS
281 * Pass all events to lowlevel driver anyway
282 * - SNDRV_SEQ_OSS_PROCESS_KEYPRESS (mostly for Emu8000)
283 * Use key-pressure if note >= 128
286 note_on_event(struct seq_oss_devinfo
*dp
, int dev
, int ch
, int note
, int vel
, struct snd_seq_event
*ev
)
288 struct seq_oss_synthinfo
*info
;
290 if (!snd_seq_oss_synth_is_valid(dp
, dev
))
293 info
= &dp
->synths
[dev
];
294 switch (info
->arg
.event_passing
) {
295 case SNDRV_SEQ_OSS_PROCESS_EVENTS
:
296 if (! info
->ch
|| ch
< 0 || ch
>= info
->nr_voices
) {
298 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEON
, ch
, note
, vel
, ev
);
301 if (note
== 255 && info
->ch
[ch
].note
>= 0) {
305 /* set volume to zero -- note off */
306 // type = SNDRV_SEQ_EVENT_NOTEOFF;
308 if (info
->ch
[ch
].vel
)
309 /* sample already started -- volume change */
310 type
= SNDRV_SEQ_EVENT_KEYPRESS
;
312 /* sample not started -- start now */
313 type
= SNDRV_SEQ_EVENT_NOTEON
;
314 info
->ch
[ch
].vel
= vel
;
315 return set_note_event(dp
, dev
, type
, ch
, info
->ch
[ch
].note
, vel
, ev
);
316 } else if (note
>= 128)
317 return -EINVAL
; /* invalid */
319 if (note
!= info
->ch
[ch
].note
&& info
->ch
[ch
].note
>= 0)
320 /* note changed - note off at beginning */
321 set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEOFF
, ch
, info
->ch
[ch
].note
, 0, ev
);
322 /* set current status */
323 info
->ch
[ch
].note
= note
;
324 info
->ch
[ch
].vel
= vel
;
325 if (vel
) /* non-zero velocity - start the note now */
326 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEON
, ch
, note
, vel
, ev
);
329 case SNDRV_SEQ_OSS_PASS_EVENTS
:
330 /* pass the event anyway */
331 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEON
, ch
, note
, vel
, ev
);
333 case SNDRV_SEQ_OSS_PROCESS_KEYPRESS
:
334 if (note
>= 128) /* key pressure: shifted by 128 */
335 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_KEYPRESS
, ch
, note
- 128, vel
, ev
);
336 else /* normal note-on event */
337 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEON
, ch
, note
, vel
, ev
);
343 * process note-off event for OSS synth
346 note_off_event(struct seq_oss_devinfo
*dp
, int dev
, int ch
, int note
, int vel
, struct snd_seq_event
*ev
)
348 struct seq_oss_synthinfo
*info
;
350 if (!snd_seq_oss_synth_is_valid(dp
, dev
))
353 info
= &dp
->synths
[dev
];
354 switch (info
->arg
.event_passing
) {
355 case SNDRV_SEQ_OSS_PROCESS_EVENTS
:
356 if (! info
->ch
|| ch
< 0 || ch
>= info
->nr_voices
) {
358 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEON
, ch
, note
, vel
, ev
);
361 if (info
->ch
[ch
].note
>= 0) {
362 note
= info
->ch
[ch
].note
;
363 info
->ch
[ch
].vel
= 0;
364 info
->ch
[ch
].note
= -1;
365 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEOFF
, ch
, note
, vel
, ev
);
367 return -EINVAL
; /* invalid */
369 case SNDRV_SEQ_OSS_PASS_EVENTS
:
370 case SNDRV_SEQ_OSS_PROCESS_KEYPRESS
:
371 /* pass the event anyway */
372 return set_note_event(dp
, dev
, SNDRV_SEQ_EVENT_NOTEOFF
, ch
, note
, vel
, ev
);
379 * create a note event
382 set_note_event(struct seq_oss_devinfo
*dp
, int dev
, int type
, int ch
, int note
, int vel
, struct snd_seq_event
*ev
)
384 if (! snd_seq_oss_synth_is_valid(dp
, dev
))
388 snd_seq_oss_synth_addr(dp
, dev
, ev
);
389 ev
->data
.note
.channel
= ch
;
390 ev
->data
.note
.note
= note
;
391 ev
->data
.note
.velocity
= vel
;
397 * create a control event
400 set_control_event(struct seq_oss_devinfo
*dp
, int dev
, int type
, int ch
, int param
, int val
, struct snd_seq_event
*ev
)
402 if (! snd_seq_oss_synth_is_valid(dp
, dev
))
406 snd_seq_oss_synth_addr(dp
, dev
, ev
);
407 ev
->data
.control
.channel
= ch
;
408 ev
->data
.control
.param
= param
;
409 ev
->data
.control
.value
= val
;
415 * create an echo event
418 set_echo_event(struct seq_oss_devinfo
*dp
, union evrec
*rec
, struct snd_seq_event
*ev
)
420 ev
->type
= SNDRV_SEQ_EVENT_ECHO
;
421 /* echo back to itself */
422 snd_seq_oss_fill_addr(dp
, ev
, dp
->addr
.client
, dp
->addr
.port
);
423 memcpy(&ev
->data
, rec
, LONG_EVENT_SIZE
);
428 * event input callback from ALSA sequencer:
429 * the echo event is processed here.
432 snd_seq_oss_event_input(struct snd_seq_event
*ev
, int direct
, void *private_data
,
435 struct seq_oss_devinfo
*dp
= (struct seq_oss_devinfo
*)private_data
;
438 if (ev
->type
!= SNDRV_SEQ_EVENT_ECHO
)
439 return snd_seq_oss_midi_input(ev
, direct
, private_data
);
441 if (ev
->source
.client
!= dp
->cseq
)
442 return 0; /* ignored */
444 rec
= (union evrec
*)&ev
->data
;
445 if (rec
->s
.code
== SEQ_SYNCTIMER
) {
447 snd_seq_oss_writeq_wakeup(dp
->writeq
, rec
->t
.time
);
450 /* echo back event */
451 if (dp
->readq
== NULL
)
453 snd_seq_oss_readq_put_event(dp
->readq
, rec
);