Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
seq_oss_event.c
Go to the documentation of this file.
1 /*
2  * OSS compatible sequencer driver
3  *
4  * Copyright (C) 1998,99 Takashi Iwai <[email protected]>
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 
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"
29 
30 
31 /*
32  * prototypes
33  */
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);
45 
46 
47 /*
48  * convert an OSS event to ALSA event
49  * return 0 : enqueued
50  * non-zero : invalid - ignored
51  */
52 
53 int
55 {
56  switch (q->s.code) {
57  case SEQ_EXTENDED:
58  return extended_event(dp, q, ev);
59 
60  case EV_CHN_VOICE:
61  return chn_voice_event(dp, q, ev);
62 
63  case EV_CHN_COMMON:
64  return chn_common_event(dp, q, ev);
65 
66  case EV_TIMING:
67  return timing_event(dp, q, ev);
68 
69  case EV_SEQ_LOCAL:
70  return local_event(dp, q, ev);
71 
72  case EV_SYSEX:
73  return snd_seq_oss_synth_sysex(dp, q->x.dev, q->x.buf, ev);
74 
75  case SEQ_MIDIPUTC:
77  return -EINVAL;
78  /* put a midi byte */
79  if (! is_write_mode(dp->file_mode))
80  break;
82  break;
84  return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev);
85  break;
86 
87  case SEQ_ECHO:
89  return -EINVAL;
90  return set_echo_event(dp, q, ev);
91 
92  case SEQ_PRIVATE:
94  return -EINVAL;
95  return snd_seq_oss_synth_raw_event(dp, q->c[1], q->c, ev);
96 
97  default:
99  return -EINVAL;
100  return old_event(dp, q, ev);
101  }
102  return -EINVAL;
103 }
104 
105 /* old type events: mode1 only */
106 static int
107 old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
108 {
109  switch (q->s.code) {
110  case SEQ_NOTEOFF:
111  return note_off_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev);
112 
113  case SEQ_NOTEON:
114  return note_on_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev);
115 
116  case SEQ_WAIT:
117  /* skip */
118  break;
119 
120  case SEQ_PGMCHANGE:
121  return set_control_event(dp, 0, SNDRV_SEQ_EVENT_PGMCHANGE,
122  q->n.chn, 0, q->n.note, ev);
123 
124  case SEQ_SYNCTIMER:
125  return snd_seq_oss_timer_reset(dp->timer);
126  }
127 
128  return -EINVAL;
129 }
130 
131 /* 8bytes extended event: mode1 only */
132 static int
133 extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
134 {
135  int val;
136 
137  switch (q->e.cmd) {
138  case SEQ_NOTEOFF:
139  return note_off_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev);
140 
141  case SEQ_NOTEON:
142  return note_on_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev);
143 
144  case SEQ_PGMCHANGE:
145  return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_PGMCHANGE,
146  q->e.chn, 0, q->e.p1, ev);
147 
148  case SEQ_AFTERTOUCH:
149  return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CHANPRESS,
150  q->e.chn, 0, q->e.p1, ev);
151 
152  case SEQ_BALANCE:
153  /* convert -128:127 to 0:127 */
154  val = (char)q->e.p1;
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);
158 
159  case SEQ_CONTROLLER:
160  val = ((short)q->e.p3 << 8) | (short)q->e.p2;
161  switch (q->e.p1) {
162  case CTRL_PITCH_BENDER: /* SEQ1 V2 control */
163  /* -0x2000:0x1fff */
164  return set_control_event(dp, q->e.dev,
166  q->e.chn, 0, val, ev);
168  /* conversion: 100/semitone -> 128/semitone */
169  return set_control_event(dp, q->e.dev,
171  q->e.chn, 0, val*128/100, ev);
172  default:
173  return set_control_event(dp, q->e.dev,
175  q->e.chn, q->e.p1, val, ev);
176  }
177 
178  case SEQ_VOLMODE:
179  return snd_seq_oss_synth_raw_event(dp, q->e.dev, q->c, ev);
180 
181  }
182  return -EINVAL;
183 }
184 
185 /* channel voice events: mode1 and 2 */
186 static int
187 chn_voice_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
188 {
189  if (q->v.chn >= 32)
190  return -EINVAL;
191  switch (q->v.cmd) {
192  case MIDI_NOTEON:
193  return note_on_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev);
194 
195  case MIDI_NOTEOFF:
196  return note_off_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev);
197 
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);
201 
202  }
203  return -EINVAL;
204 }
205 
206 /* channel common events: mode1 and 2 */
207 static int
208 chn_common_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
209 {
210  if (q->l.chn >= 32)
211  return -EINVAL;
212  switch (q->l.cmd) {
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);
216 
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);
220 
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);
225 
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);
229  }
230  return -EINVAL;
231 }
232 
233 /* timer events: mode1 and mode2 */
234 static int
235 timing_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
236 {
237  switch (q->t.cmd) {
238  case TMR_ECHO:
240  return set_echo_event(dp, q, ev);
241  else {
242  union evrec tmp;
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);
247  }
248 
249  case TMR_STOP:
250  if (dp->seq_mode)
251  return snd_seq_oss_timer_stop(dp->timer);
252  return 0;
253 
254  case TMR_CONTINUE:
255  if (dp->seq_mode)
256  return snd_seq_oss_timer_continue(dp->timer);
257  return 0;
258 
259  case TMR_TEMPO:
260  if (dp->seq_mode)
261  return snd_seq_oss_timer_tempo(dp->timer, q->t.time);
262  return 0;
263  }
264 
265  return -EINVAL;
266 }
267 
268 /* local events: mode1 and 2 */
269 static int
270 local_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
271 {
272  return -EINVAL;
273 }
274 
275 /*
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
284  */
285 static int
286 note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
287 {
288  struct seq_oss_synthinfo *info = &dp->synths[dev];
289  switch (info->arg.event_passing) {
291  if (! info->ch || ch < 0 || ch >= info->nr_voices) {
292  /* pass directly */
293  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
294  }
295 
296  if (note == 255 && info->ch[ch].note >= 0) {
297  /* volume control */
298  int type;
299  //if (! vel)
300  /* set volume to zero -- note off */
301  // type = SNDRV_SEQ_EVENT_NOTEOFF;
302  //else
303  if (info->ch[ch].vel)
304  /* sample already started -- volume change */
306  else
307  /* sample not started -- start now */
308  type = SNDRV_SEQ_EVENT_NOTEON;
309  info->ch[ch].vel = vel;
310  return set_note_event(dp, dev, type, ch, info->ch[ch].note, vel, ev);
311  } else if (note >= 128)
312  return -EINVAL; /* invalid */
313 
314  if (note != info->ch[ch].note && info->ch[ch].note >= 0)
315  /* note changed - note off at beginning */
316  set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, info->ch[ch].note, 0, ev);
317  /* set current status */
318  info->ch[ch].note = note;
319  info->ch[ch].vel = vel;
320  if (vel) /* non-zero velocity - start the note now */
321  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
322  return -EINVAL;
323 
325  /* pass the event anyway */
326  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
327 
329  if (note >= 128) /* key pressure: shifted by 128 */
330  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_KEYPRESS, ch, note - 128, vel, ev);
331  else /* normal note-on event */
332  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
333  }
334  return -EINVAL;
335 }
336 
337 /*
338  * process note-off event for OSS synth
339  */
340 static int
341 note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
342 {
343  struct seq_oss_synthinfo *info = &dp->synths[dev];
344  switch (info->arg.event_passing) {
346  if (! info->ch || ch < 0 || ch >= info->nr_voices) {
347  /* pass directly */
348  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
349  }
350 
351  if (info->ch[ch].note >= 0) {
352  note = info->ch[ch].note;
353  info->ch[ch].vel = 0;
354  info->ch[ch].note = -1;
355  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev);
356  }
357  return -EINVAL; /* invalid */
358 
361  /* pass the event anyway */
362  return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev);
363 
364  }
365  return -EINVAL;
366 }
367 
368 /*
369  * create a note event
370  */
371 static int
372 set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev)
373 {
374  if (! snd_seq_oss_synth_is_valid(dp, dev))
375  return -ENXIO;
376 
377  ev->type = type;
378  snd_seq_oss_synth_addr(dp, dev, ev);
379  ev->data.note.channel = ch;
380  ev->data.note.note = note;
381  ev->data.note.velocity = vel;
382 
383  return 0;
384 }
385 
386 /*
387  * create a control event
388  */
389 static int
390 set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev)
391 {
392  if (! snd_seq_oss_synth_is_valid(dp, dev))
393  return -ENXIO;
394 
395  ev->type = type;
396  snd_seq_oss_synth_addr(dp, dev, ev);
397  ev->data.control.channel = ch;
398  ev->data.control.param = param;
399  ev->data.control.value = val;
400 
401  return 0;
402 }
403 
404 /*
405  * create an echo event
406  */
407 static int
408 set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev)
409 {
411  /* echo back to itself */
412  snd_seq_oss_fill_addr(dp, ev, dp->addr.client, dp->addr.port);
413  memcpy(&ev->data, rec, LONG_EVENT_SIZE);
414  return 0;
415 }
416 
417 /*
418  * event input callback from ALSA sequencer:
419  * the echo event is processed here.
420  */
421 int
423  int atomic, int hop)
424 {
425  struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
426  union evrec *rec;
427 
428  if (ev->type != SNDRV_SEQ_EVENT_ECHO)
429  return snd_seq_oss_midi_input(ev, direct, private_data);
430 
431  if (ev->source.client != dp->cseq)
432  return 0; /* ignored */
433 
434  rec = (union evrec*)&ev->data;
435  if (rec->s.code == SEQ_SYNCTIMER) {
436  /* sync echo back */
437  snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time);
438 
439  } else {
440  /* echo back event */
441  if (dp->readq == NULL)
442  return 0;
444  }
445  return 0;
446 }
447