linux/sound/core/seq/seq_midi_event.c
<<
>>
Prefs
   1/*
   2 *  MIDI byte <-> sequencer event coder
   3 *
   4 *  Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>,
   5 *                        Jaroslav Kysela <perex@perex.cz>
   6 *
   7 *   This program is free software; you can redistribute it and/or modify
   8 *   it under the terms of the GNU General Public License as published by
   9 *   the Free Software Foundation; either version 2 of the License, or
  10 *   (at your option) any later version.
  11 *
  12 *   This program is distributed in the hope that it will be useful,
  13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 *   GNU General Public License for more details.
  16 *
  17 *   You should have received a copy of the GNU General Public License
  18 *   along with this program; if not, write to the Free Software
  19 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20 */
  21
  22#include <linux/slab.h>
  23#include <linux/errno.h>
  24#include <linux/string.h>
  25#include <sound/core.h>
  26#include <sound/seq_kernel.h>
  27#include <sound/seq_midi_event.h>
  28#include <sound/asoundef.h>
  29
  30MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
  31MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder");
  32MODULE_LICENSE("GPL");
  33
  34/* event type, index into status_event[] */
  35/* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */
  36#define ST_INVALID      7
  37#define ST_SPECIAL      8
  38#define ST_SYSEX        ST_SPECIAL
  39/* from 8 to 15 are events for 0xf0-0xf7 */
  40
  41
  42/*
  43 * prototypes
  44 */
  45static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
  46static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
  47static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
  48static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
  49static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
  50static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
  51static void note_decode(struct snd_seq_event *ev, unsigned char *buf);
  52static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf);
  53static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf);
  54static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf);
  55static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf);
  56
  57/*
  58 * event list
  59 */
  60static struct status_event_list {
  61        int event;
  62        int qlen;
  63        void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev);
  64        void (*decode)(struct snd_seq_event *ev, unsigned char *buf);
  65} status_event[] = {
  66        /* 0x80 - 0xef */
  67        {SNDRV_SEQ_EVENT_NOTEOFF,        2, note_event, note_decode},
  68        {SNDRV_SEQ_EVENT_NOTEON,         2, note_event, note_decode},
  69        {SNDRV_SEQ_EVENT_KEYPRESS,       2, note_event, note_decode},
  70        {SNDRV_SEQ_EVENT_CONTROLLER,     2, two_param_ctrl_event, two_param_decode},
  71        {SNDRV_SEQ_EVENT_PGMCHANGE,      1, one_param_ctrl_event, one_param_decode},
  72        {SNDRV_SEQ_EVENT_CHANPRESS,      1, one_param_ctrl_event, one_param_decode},
  73        {SNDRV_SEQ_EVENT_PITCHBEND,      2, pitchbend_ctrl_event, pitchbend_decode},
  74        /* invalid */
  75        {SNDRV_SEQ_EVENT_NONE,          -1, NULL, NULL},
  76        /* 0xf0 - 0xff */
  77        {SNDRV_SEQ_EVENT_SYSEX,          1, NULL, NULL}, /* sysex: 0xf0 */
  78        {SNDRV_SEQ_EVENT_QFRAME,         1, one_param_event, one_param_decode}, /* 0xf1 */
  79        {SNDRV_SEQ_EVENT_SONGPOS,        2, songpos_event, songpos_decode}, /* 0xf2 */
  80        {SNDRV_SEQ_EVENT_SONGSEL,        1, one_param_event, one_param_decode}, /* 0xf3 */
  81        {SNDRV_SEQ_EVENT_NONE,          -1, NULL, NULL}, /* 0xf4 */
  82        {SNDRV_SEQ_EVENT_NONE,          -1, NULL, NULL}, /* 0xf5 */
  83        {SNDRV_SEQ_EVENT_TUNE_REQUEST,   0, NULL, NULL}, /* 0xf6 */
  84        {SNDRV_SEQ_EVENT_NONE,          -1, NULL, NULL}, /* 0xf7 */
  85        {SNDRV_SEQ_EVENT_CLOCK,          0, NULL, NULL}, /* 0xf8 */
  86        {SNDRV_SEQ_EVENT_NONE,          -1, NULL, NULL}, /* 0xf9 */
  87        {SNDRV_SEQ_EVENT_START,          0, NULL, NULL}, /* 0xfa */
  88        {SNDRV_SEQ_EVENT_CONTINUE,       0, NULL, NULL}, /* 0xfb */
  89        {SNDRV_SEQ_EVENT_STOP,           0, NULL, NULL}, /* 0xfc */
  90        {SNDRV_SEQ_EVENT_NONE,          -1, NULL, NULL}, /* 0xfd */
  91        {SNDRV_SEQ_EVENT_SENSING,        0, NULL, NULL}, /* 0xfe */
  92        {SNDRV_SEQ_EVENT_RESET,          0, NULL, NULL}, /* 0xff */
  93};
  94
  95static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len,
  96                               struct snd_seq_event *ev);
  97static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, int count,
  98                             struct snd_seq_event *ev);
  99
 100static struct extra_event_list {
 101        int event;
 102        int (*decode)(struct snd_midi_event *dev, unsigned char *buf, int len,
 103                      struct snd_seq_event *ev);
 104} extra_event[] = {
 105        {SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14},
 106        {SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn},
 107        {SNDRV_SEQ_EVENT_REGPARAM, extra_decode_xrpn},
 108};
 109
 110/*
 111 *  new/delete record
 112 */
 113
 114int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
 115{
 116        struct snd_midi_event *dev;
 117
 118        *rdev = NULL;
 119        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 120        if (dev == NULL)
 121                return -ENOMEM;
 122        if (bufsize > 0) {
 123                dev->buf = kmalloc(bufsize, GFP_KERNEL);
 124                if (dev->buf == NULL) {
 125                        kfree(dev);
 126                        return -ENOMEM;
 127                }
 128        }
 129        dev->bufsize = bufsize;
 130        dev->lastcmd = 0xff;
 131        dev->type = ST_INVALID;
 132        spin_lock_init(&dev->lock);
 133        *rdev = dev;
 134        return 0;
 135}
 136
 137void snd_midi_event_free(struct snd_midi_event *dev)
 138{
 139        if (dev != NULL) {
 140                kfree(dev->buf);
 141                kfree(dev);
 142        }
 143}
 144
 145/*
 146 * initialize record
 147 */
 148static inline void reset_encode(struct snd_midi_event *dev)
 149{
 150        dev->read = 0;
 151        dev->qlen = 0;
 152        dev->type = ST_INVALID;
 153}
 154
 155void snd_midi_event_reset_encode(struct snd_midi_event *dev)
 156{
 157        unsigned long flags;
 158
 159        spin_lock_irqsave(&dev->lock, flags);
 160        reset_encode(dev);
 161        spin_unlock_irqrestore(&dev->lock, flags);
 162}
 163
 164void snd_midi_event_reset_decode(struct snd_midi_event *dev)
 165{
 166        unsigned long flags;
 167
 168        spin_lock_irqsave(&dev->lock, flags);
 169        dev->lastcmd = 0xff;
 170        spin_unlock_irqrestore(&dev->lock, flags);
 171}
 172
 173#if 0
 174void snd_midi_event_init(struct snd_midi_event *dev)
 175{
 176        snd_midi_event_reset_encode(dev);
 177        snd_midi_event_reset_decode(dev);
 178}
 179#endif  /*  0  */
 180
 181void snd_midi_event_no_status(struct snd_midi_event *dev, int on)
 182{
 183        dev->nostat = on ? 1 : 0;
 184}
 185
 186/*
 187 * resize buffer
 188 */
 189#if 0
 190int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize)
 191{
 192        unsigned char *new_buf, *old_buf;
 193        unsigned long flags;
 194
 195        if (bufsize == dev->bufsize)
 196                return 0;
 197        new_buf = kmalloc(bufsize, GFP_KERNEL);
 198        if (new_buf == NULL)
 199                return -ENOMEM;
 200        spin_lock_irqsave(&dev->lock, flags);
 201        old_buf = dev->buf;
 202        dev->buf = new_buf;
 203        dev->bufsize = bufsize;
 204        reset_encode(dev);
 205        spin_unlock_irqrestore(&dev->lock, flags);
 206        kfree(old_buf);
 207        return 0;
 208}
 209#endif  /*  0  */
 210
 211/*
 212 *  read bytes and encode to sequencer event if finished
 213 *  return the size of encoded bytes
 214 */
 215long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count,
 216                           struct snd_seq_event *ev)
 217{
 218        long result = 0;
 219        int rc;
 220
 221        ev->type = SNDRV_SEQ_EVENT_NONE;
 222
 223        while (count-- > 0) {
 224                rc = snd_midi_event_encode_byte(dev, *buf++, ev);
 225                result++;
 226                if (rc < 0)
 227                        return rc;
 228                else if (rc > 0)
 229                        return result;
 230        }
 231
 232        return result;
 233}
 234
 235/*
 236 *  read one byte and encode to sequencer event:
 237 *  return 1 if MIDI bytes are encoded to an event
 238 *         0 data is not finished
 239 *         negative for error
 240 */
 241int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
 242                               struct snd_seq_event *ev)
 243{
 244        int rc = 0;
 245        unsigned long flags;
 246
 247        c &= 0xff;
 248
 249        if (c >= MIDI_CMD_COMMON_CLOCK) {
 250                /* real-time event */
 251                ev->type = status_event[ST_SPECIAL + c - 0xf0].event;
 252                ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
 253                ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
 254                return ev->type != SNDRV_SEQ_EVENT_NONE;
 255        }
 256
 257        spin_lock_irqsave(&dev->lock, flags);
 258        if ((c & 0x80) &&
 259            (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) {
 260                /* new command */
 261                dev->buf[0] = c;
 262                if ((c & 0xf0) == 0xf0) /* system messages */
 263                        dev->type = (c & 0x0f) + ST_SPECIAL;
 264                else
 265                        dev->type = (c >> 4) & 0x07;
 266                dev->read = 1;
 267                dev->qlen = status_event[dev->type].qlen;
 268        } else {
 269                if (dev->qlen > 0) {
 270                        /* rest of command */
 271                        dev->buf[dev->read++] = c;
 272                        if (dev->type != ST_SYSEX)
 273                                dev->qlen--;
 274                } else {
 275                        /* running status */
 276                        dev->buf[1] = c;
 277                        dev->qlen = status_event[dev->type].qlen - 1;
 278                        dev->read = 2;
 279                }
 280        }
 281        if (dev->qlen == 0) {
 282                ev->type = status_event[dev->type].event;
 283                ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
 284                ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
 285                if (status_event[dev->type].encode) /* set data values */
 286                        status_event[dev->type].encode(dev, ev);
 287                if (dev->type >= ST_SPECIAL)
 288                        dev->type = ST_INVALID;
 289                rc = 1;
 290        } else  if (dev->type == ST_SYSEX) {
 291                if (c == MIDI_CMD_COMMON_SYSEX_END ||
 292                    dev->read >= dev->bufsize) {
 293                        ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
 294                        ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
 295                        ev->type = SNDRV_SEQ_EVENT_SYSEX;
 296                        ev->data.ext.len = dev->read;
 297                        ev->data.ext.ptr = dev->buf;
 298                        if (c != MIDI_CMD_COMMON_SYSEX_END)
 299                                dev->read = 0; /* continue to parse */
 300                        else
 301                                reset_encode(dev); /* all parsed */
 302                        rc = 1;
 303                }
 304        }
 305
 306        spin_unlock_irqrestore(&dev->lock, flags);
 307        return rc;
 308}
 309
 310/* encode note event */
 311static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
 312{
 313        ev->data.note.channel = dev->buf[0] & 0x0f;
 314        ev->data.note.note = dev->buf[1];
 315        ev->data.note.velocity = dev->buf[2];
 316}
 317
 318/* encode one parameter controls */
 319static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
 320{
 321        ev->data.control.channel = dev->buf[0] & 0x0f;
 322        ev->data.control.value = dev->buf[1];
 323}
 324
 325/* encode pitch wheel change */
 326static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
 327{
 328        ev->data.control.channel = dev->buf[0] & 0x0f;
 329        ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192;
 330}
 331
 332/* encode midi control change */
 333static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
 334{
 335        ev->data.control.channel = dev->buf[0] & 0x0f;
 336        ev->data.control.param = dev->buf[1];
 337        ev->data.control.value = dev->buf[2];
 338}
 339
 340/* encode one parameter value*/
 341static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
 342{
 343        ev->data.control.value = dev->buf[1];
 344}
 345
 346/* encode song position */
 347static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
 348{
 349        ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1];
 350}
 351
 352/*
 353 * decode from a sequencer event to midi bytes
 354 * return the size of decoded midi events
 355 */
 356long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count,
 357                           struct snd_seq_event *ev)
 358{
 359        unsigned int cmd, type;
 360
 361        if (ev->type == SNDRV_SEQ_EVENT_NONE)
 362                return -ENOENT;
 363
 364        for (type = 0; type < ARRAY_SIZE(status_event); type++) {
 365                if (ev->type == status_event[type].event)
 366                        goto __found;
 367        }
 368        for (type = 0; type < ARRAY_SIZE(extra_event); type++) {
 369                if (ev->type == extra_event[type].event)
 370                        return extra_event[type].decode(dev, buf, count, ev);
 371        }
 372        return -ENOENT;
 373
 374      __found:
 375        if (type >= ST_SPECIAL)
 376                cmd = 0xf0 + (type - ST_SPECIAL);
 377        else
 378                /* data.note.channel and data.control.channel is identical */
 379                cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f);
 380
 381
 382        if (cmd == MIDI_CMD_COMMON_SYSEX) {
 383                snd_midi_event_reset_decode(dev);
 384                return snd_seq_expand_var_event(ev, count, buf, 1, 0);
 385        } else {
 386                int qlen;
 387                unsigned char xbuf[4];
 388                unsigned long flags;
 389
 390                spin_lock_irqsave(&dev->lock, flags);
 391                if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) {
 392                        dev->lastcmd = cmd;
 393                        spin_unlock_irqrestore(&dev->lock, flags);
 394                        xbuf[0] = cmd;
 395                        if (status_event[type].decode)
 396                                status_event[type].decode(ev, xbuf + 1);
 397                        qlen = status_event[type].qlen + 1;
 398                } else {
 399                        spin_unlock_irqrestore(&dev->lock, flags);
 400                        if (status_event[type].decode)
 401                                status_event[type].decode(ev, xbuf + 0);
 402                        qlen = status_event[type].qlen;
 403                }
 404                if (count < qlen)
 405                        return -ENOMEM;
 406                memcpy(buf, xbuf, qlen);
 407                return qlen;
 408        }
 409}
 410
 411
 412/* decode note event */
 413static void note_decode(struct snd_seq_event *ev, unsigned char *buf)
 414{
 415        buf[0] = ev->data.note.note & 0x7f;
 416        buf[1] = ev->data.note.velocity & 0x7f;
 417}
 418
 419/* decode one parameter controls */
 420static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf)
 421{
 422        buf[0] = ev->data.control.value & 0x7f;
 423}
 424
 425/* decode pitch wheel change */
 426static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf)
 427{
 428        int value = ev->data.control.value + 8192;
 429        buf[0] = value & 0x7f;
 430        buf[1] = (value >> 7) & 0x7f;
 431}
 432
 433/* decode midi control change */
 434static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf)
 435{
 436        buf[0] = ev->data.control.param & 0x7f;
 437        buf[1] = ev->data.control.value & 0x7f;
 438}
 439
 440/* decode song position */
 441static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf)
 442{
 443        buf[0] = ev->data.control.value & 0x7f;
 444        buf[1] = (ev->data.control.value >> 7) & 0x7f;
 445}
 446
 447/* decode 14bit control */
 448static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf,
 449                               int count, struct snd_seq_event *ev)
 450{
 451        unsigned char cmd;
 452        int idx = 0;
 453
 454        cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
 455        if (ev->data.control.param < 0x20) {
 456                if (count < 4)
 457                        return -ENOMEM;
 458                if (dev->nostat && count < 6)
 459                        return -ENOMEM;
 460                if (cmd != dev->lastcmd || dev->nostat) {
 461                        if (count < 5)
 462                                return -ENOMEM;
 463                        buf[idx++] = dev->lastcmd = cmd;
 464                }
 465                buf[idx++] = ev->data.control.param;
 466                buf[idx++] = (ev->data.control.value >> 7) & 0x7f;
 467                if (dev->nostat)
 468                        buf[idx++] = cmd;
 469                buf[idx++] = ev->data.control.param + 0x20;
 470                buf[idx++] = ev->data.control.value & 0x7f;
 471        } else {
 472                if (count < 2)
 473                        return -ENOMEM;
 474                if (cmd != dev->lastcmd || dev->nostat) {
 475                        if (count < 3)
 476                                return -ENOMEM;
 477                        buf[idx++] = dev->lastcmd = cmd;
 478                }
 479                buf[idx++] = ev->data.control.param & 0x7f;
 480                buf[idx++] = ev->data.control.value & 0x7f;
 481        }
 482        return idx;
 483}
 484
 485/* decode reg/nonreg param */
 486static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
 487                             int count, struct snd_seq_event *ev)
 488{
 489        unsigned char cmd;
 490        char *cbytes;
 491        static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
 492                                       MIDI_CTL_NONREG_PARM_NUM_LSB,
 493                                       MIDI_CTL_MSB_DATA_ENTRY,
 494                                       MIDI_CTL_LSB_DATA_ENTRY };
 495        static char cbytes_rpn[4] =  { MIDI_CTL_REGIST_PARM_NUM_MSB,
 496                                       MIDI_CTL_REGIST_PARM_NUM_LSB,
 497                                       MIDI_CTL_MSB_DATA_ENTRY,
 498                                       MIDI_CTL_LSB_DATA_ENTRY };
 499        unsigned char bytes[4];
 500        int idx = 0, i;
 501
 502        if (count < 8)
 503                return -ENOMEM;
 504        if (dev->nostat && count < 12)
 505                return -ENOMEM;
 506        cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
 507        bytes[0] = ev->data.control.param & 0x007f;
 508        bytes[1] = (ev->data.control.param & 0x3f80) >> 7;
 509        bytes[2] = ev->data.control.value & 0x007f;
 510        bytes[3] = (ev->data.control.value & 0x3f80) >> 7;
 511        if (cmd != dev->lastcmd && !dev->nostat) {
 512                if (count < 9)
 513                        return -ENOMEM;
 514                buf[idx++] = dev->lastcmd = cmd;
 515        }
 516        cbytes = ev->type == SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn;
 517        for (i = 0; i < 4; i++) {
 518                if (dev->nostat)
 519                        buf[idx++] = dev->lastcmd = cmd;
 520                buf[idx++] = cbytes[i];
 521                buf[idx++] = bytes[i];
 522        }
 523        return idx;
 524}
 525
 526/*
 527 *  exports
 528 */
 529 
 530EXPORT_SYMBOL(snd_midi_event_new);
 531EXPORT_SYMBOL(snd_midi_event_free);
 532EXPORT_SYMBOL(snd_midi_event_reset_encode);
 533EXPORT_SYMBOL(snd_midi_event_reset_decode);
 534EXPORT_SYMBOL(snd_midi_event_no_status);
 535EXPORT_SYMBOL(snd_midi_event_encode);
 536EXPORT_SYMBOL(snd_midi_event_encode_byte);
 537EXPORT_SYMBOL(snd_midi_event_decode);
 538
 539static int __init alsa_seq_midi_event_init(void)
 540{
 541        return 0;
 542}
 543
 544static void __exit alsa_seq_midi_event_exit(void)
 545{
 546}
 547
 548module_init(alsa_seq_midi_event_init)
 549module_exit(alsa_seq_midi_event_exit)
 550
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.