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; 289 290 if (!snd_seq_oss_synth_is_valid(dp, dev)) 291 return -ENXIO; 292 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) { 297 /* pass directly */ 298 return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); 299 } 300 301 if (note == 255 && info->ch[ch].note >= 0) { 302 /* volume control */ 303 int type; 304 //if (! vel) 305 /* set volume to zero -- note off */ 306 // type = SNDRV_SEQ_EVENT_NOTEOFF; 307 //else 308 if (info->ch[ch].vel) 309 /* sample already started -- volume change */ 310 type = SNDRV_SEQ_EVENT_KEYPRESS; 311 else 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 */ 318 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); 327 return -EINVAL; 328 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); 332 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); 338 } 339 return -EINVAL; 340} 341 342/* 343 * process note-off event for OSS synth 344 */ 345static int 346note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev) 347{ 348 struct seq_oss_synthinfo *info; 349 350 if (!snd_seq_oss_synth_is_valid(dp, dev)) 351 return -ENXIO; 352 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) { 357 /* pass directly */ 358 return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); 359 } 360 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); 366 } 367 return -EINVAL; /* invalid */ 368 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); 373 374 } 375 return -EINVAL; 376} 377 378/* 379 * create a note event 380 */ 381static int 382set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev) 383{ 384 if (! snd_seq_oss_synth_is_valid(dp, dev)) 385 return -ENXIO; 386 387 ev->type = type; 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; 392 393 return 0; 394} 395 396/* 397 * create a control event 398 */ 399static int 400set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev) 401{ 402 if (! snd_seq_oss_synth_is_valid(dp, dev)) 403 return -ENXIO; 404 405 ev->type = type; 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; 410 411 return 0; 412} 413 414/* 415 * create an echo event 416 */ 417static int 418set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev) 419{ 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); 424 return 0; 425} 426 427/* 428 * event input callback from ALSA sequencer: 429 * the echo event is processed here. 430 */ 431int 432snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, 433 int atomic, int hop) 434{ 435 struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data; 436 union evrec *rec; 437 438 if (ev->type != SNDRV_SEQ_EVENT_ECHO) 439 return snd_seq_oss_midi_input(ev, direct, private_data); 440 441 if (ev->source.client != dp->cseq) 442 return 0; /* ignored */ 443 444 rec = (union evrec*)&ev->data; 445 if (rec->s.code == SEQ_SYNCTIMER) { 446 /* sync echo back */ 447 snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time); 448 449 } else { 450 /* echo back event */ 451 if (dp->readq == NULL) 452 return 0; 453 snd_seq_oss_readq_put_event(dp->readq, rec); 454 } 455 return 0; 456} 457 458