linux/sound/core/seq/oss/seq_oss_event.c
<<
>>
Prefs
   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
 448