Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4 447 lines 13 kB view raw
1/* 2 * OSS compatible sequencer driver 3 * 4 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de> 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 */ 34static int extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev); 35static int chn_voice_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); 36static int chn_common_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); 37static int timing_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); 38static int local_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); 39static int old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev); 40static int note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev); 41static int note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev); 42static int set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev); 43static int set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev); 44static 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 53int 54snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) 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: 76 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) 77 return -EINVAL; 78 /* put a midi byte */ 79 if (! is_write_mode(dp->file_mode)) 80 break; 81 if (snd_seq_oss_midi_open(dp, q->s.dev, SNDRV_SEQ_OSS_FILE_WRITE)) 82 break; 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); 85 break; 86 87 case SEQ_ECHO: 88 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) 89 return -EINVAL; 90 return set_echo_event(dp, q, ev); 91 92 case SEQ_PRIVATE: 93 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) 94 return -EINVAL; 95 return snd_seq_oss_synth_raw_event(dp, q->c[1], q->c, ev); 96 97 default: 98 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) 99 return -EINVAL; 100 return old_event(dp, q, ev); 101 } 102 return -EINVAL; 103} 104 105/* old type events: mode1 only */ 106static int 107old_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 */ 132static int 133extended_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, 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); 172 default: 173 return set_control_event(dp, q->e.dev, 174 SNDRV_SEQ_EVENT_CONTROL14, 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 */ 186static int 187chn_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 */ 207static int 208chn_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 */ 234static int 235timing_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) 236{ 237 switch (q->t.cmd) { 238 case TMR_ECHO: 239 if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) 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 */ 269static int 270local_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 */ 285static int 286note_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) { 290 case SNDRV_SEQ_OSS_PROCESS_EVENTS: 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 */ 305 type = SNDRV_SEQ_EVENT_KEYPRESS; 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 324 case SNDRV_SEQ_OSS_PASS_EVENTS: 325 /* pass the event anyway */ 326 return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); 327 328 case SNDRV_SEQ_OSS_PROCESS_KEYPRESS: 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 */ 340static int 341note_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) { 345 case SNDRV_SEQ_OSS_PROCESS_EVENTS: 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 359 case SNDRV_SEQ_OSS_PASS_EVENTS: 360 case SNDRV_SEQ_OSS_PROCESS_KEYPRESS: 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 */ 371static int 372set_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 */ 389static int 390set_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 */ 407static int 408set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev) 409{ 410 ev->type = SNDRV_SEQ_EVENT_ECHO; 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 */ 421int 422snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, 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; 443 snd_seq_oss_readq_put_event(dp->readq, rec); 444 } 445 return 0; 446} 447