annotate plugin/api/dssi_alsa_compat.c @ 1290:fa574c909c3d 3.0-integration

Add MAD_BUFFER_GUARD padding at end of mp3 buffer, in order to ensure last frame is decoded successfully (otherwise the decoded audio is truncated). Another thing learned from madplay.
author Chris Cannam
date Thu, 24 Nov 2016 17:06:31 +0000
parents d7f3dfe6f9a4
children
rev   line source
Chris@0 1 /* DSSI ALSA compatibility library
Chris@0 2 *
Chris@0 3 * This library provides for non-ALSA systems the ALSA snd_seq_event_t handling
Chris@0 4 * necessary to compile and run DSSI. It was extracted from alsa-lib 1.0.8.
Chris@0 5 *
Chris@0 6 * See ./alsa/README for more information.
Chris@0 7 */
Chris@0 8
Chris@0 9 #include <stdlib.h>
Chris@0 10 #include <errno.h>
Chris@0 11
Chris@0 12 #include "alsa/asoundef.h"
Chris@0 13 #include "alsa/sound/asequencer.h"
Chris@0 14 #include "alsa/seq.h"
Chris@0 15 #include "alsa/seq_event.h"
Chris@0 16 #include "alsa/seq_midi_event.h"
Chris@0 17
Chris@0 18 /**
Chris@0 19 * \file seq/seq_event.c
Chris@0 20 * \brief Sequencer Event Types
Chris@0 21 * \author Takashi Iwai <tiwai@suse.de>
Chris@0 22 * \date 2001
Chris@0 23 */
Chris@0 24
Chris@0 25 #define FIXED_EV(x) (_SND_SEQ_TYPE(SND_SEQ_EVFLG_FIXED) | _SND_SEQ_TYPE(x))
Chris@0 26
Chris@0 27 /** Event types conversion array */
Chris@608 28 /*
Chris@0 29 const unsigned int snd_seq_event_types[256] = {
Chris@0 30 [SND_SEQ_EVENT_SYSTEM ... SND_SEQ_EVENT_RESULT]
Chris@0 31 = FIXED_EV(SND_SEQ_EVFLG_RESULT),
Chris@0 32 [SND_SEQ_EVENT_NOTE]
Chris@0 33 = FIXED_EV(SND_SEQ_EVFLG_NOTE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_NOTE_TWOARG),
Chris@0 34 [SND_SEQ_EVENT_NOTEON ... SND_SEQ_EVENT_KEYPRESS]
Chris@0 35 = FIXED_EV(SND_SEQ_EVFLG_NOTE),
Chris@0 36 [SND_SEQ_EVENT_CONTROLLER ... SND_SEQ_EVENT_REGPARAM]
Chris@0 37 = FIXED_EV(SND_SEQ_EVFLG_CONTROL),
Chris@0 38 [SND_SEQ_EVENT_START ... SND_SEQ_EVENT_STOP]
Chris@0 39 = FIXED_EV(SND_SEQ_EVFLG_QUEUE),
Chris@0 40 [SND_SEQ_EVENT_SETPOS_TICK]
Chris@0 41 = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TICK),
Chris@0 42 [SND_SEQ_EVENT_SETPOS_TIME]
Chris@0 43 = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TIME),
Chris@0 44 [SND_SEQ_EVENT_TEMPO ... SND_SEQ_EVENT_SYNC_POS]
Chris@0 45 = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE),
Chris@0 46 [SND_SEQ_EVENT_TUNE_REQUEST ... SND_SEQ_EVENT_SENSING]
Chris@0 47 = FIXED_EV(SND_SEQ_EVFLG_NONE),
Chris@0 48 [SND_SEQ_EVENT_ECHO ... SND_SEQ_EVENT_OSS]
Chris@0 49 = FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_SYSTEM),
Chris@0 50 [SND_SEQ_EVENT_CLIENT_START ... SND_SEQ_EVENT_PORT_CHANGE]
Chris@0 51 = FIXED_EV(SND_SEQ_EVFLG_MESSAGE),
Chris@0 52 [SND_SEQ_EVENT_PORT_SUBSCRIBED ... SND_SEQ_EVENT_PORT_UNSUBSCRIBED]
Chris@0 53 = FIXED_EV(SND_SEQ_EVFLG_CONNECTION),
Chris@0 54 [SND_SEQ_EVENT_SAMPLE ... SND_SEQ_EVENT_SAMPLE_PRIVATE1]
Chris@0 55 = FIXED_EV(SND_SEQ_EVFLG_SAMPLE),
Chris@0 56 [SND_SEQ_EVENT_USR0 ... SND_SEQ_EVENT_USR9]
Chris@0 57 = FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS),
Chris@0 58 [SND_SEQ_EVENT_INSTR_BEGIN ... SND_SEQ_EVENT_INSTR_CHANGE]
Chris@0 59 = _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR),
Chris@0 60 [SND_SEQ_EVENT_SYSEX ... SND_SEQ_EVENT_BOUNCE]
Chris@0 61 = _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE),
Chris@0 62 [SND_SEQ_EVENT_USR_VAR0 ... SND_SEQ_EVENT_USR_VAR4]
Chris@0 63 = _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS),
Chris@0 64 [SND_SEQ_EVENT_NONE]
Chris@0 65 = FIXED_EV(SND_SEQ_EVFLG_NONE),
Chris@0 66 };
Chris@608 67 */
Chris@0 68 /**
Chris@0 69 * \file seq/seq_midi_event.c
Chris@0 70 * \brief MIDI byte <-> sequencer event coder
Chris@0 71 * \author Takashi Iwai <tiwai@suse.de>
Chris@0 72 * \author Jaroslav Kysela <perex@suse.cz>
Chris@0 73 * \date 2000-2001
Chris@0 74 */
Chris@0 75
Chris@0 76 /*
Chris@0 77 * MIDI byte <-> sequencer event coder
Chris@0 78 *
Chris@0 79 * Copyright (C) 1998,99,2000 Takashi Iwai <tiwai@suse.de>,
Chris@0 80 * Jaroslav Kysela <perex@suse.cz>
Chris@0 81 *
Chris@0 82 *
Chris@0 83 * This library is free software; you can redistribute it and/or modify
Chris@0 84 * it under the terms of the GNU Lesser General Public License as
Chris@0 85 * published by the Free Software Foundation; either version 2.1 of
Chris@0 86 * the License, or (at your option) any later version.
Chris@0 87 *
Chris@0 88 * This program is distributed in the hope that it will be useful,
Chris@0 89 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 90 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 91 * GNU Lesser General Public License for more details.
Chris@0 92 *
Chris@0 93 * You should have received a copy of the GNU Lesser General Public
Chris@0 94 * License along with this library; if not, write to the Free Software
Chris@0 95 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Chris@0 96 */
Chris@0 97
Chris@0 98 /* midi status */
Chris@0 99 struct snd_midi_event {
Chris@0 100 size_t qlen; /* queue length */
Chris@0 101 size_t read; /* chars read */
Chris@0 102 int type; /* current event type */
Chris@0 103 unsigned char lastcmd;
Chris@0 104 unsigned char nostat;
Chris@0 105 size_t bufsize;
Chris@0 106 unsigned char *buf; /* input buffer */
Chris@0 107 };
Chris@0 108
Chris@0 109
Chris@0 110 /* queue type */
Chris@0 111 /* from 0 to 7 are normal commands (note off, on, etc.) */
Chris@0 112 #define ST_NOTEOFF 0
Chris@0 113 #define ST_NOTEON 1
Chris@0 114 #define ST_SPECIAL 8
Chris@0 115 #define ST_SYSEX ST_SPECIAL
Chris@0 116 /* from 8 to 15 are events for 0xf0-0xf7 */
Chris@0 117
Chris@0 118
Chris@0 119 /* status event types */
Chris@0 120 typedef void (*event_encode_t)(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 121 typedef void (*event_decode_t)(const snd_seq_event_t *ev, unsigned char *buf);
Chris@0 122
Chris@0 123 /*
Chris@0 124 * prototypes
Chris@0 125 */
Chris@0 126 static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 127 static void one_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 128 static void pitchbend_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 129 static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 130 static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 131 static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
Chris@0 132 static void note_decode(const snd_seq_event_t *ev, unsigned char *buf);
Chris@0 133 static void one_param_decode(const snd_seq_event_t *ev, unsigned char *buf);
Chris@0 134 static void pitchbend_decode(const snd_seq_event_t *ev, unsigned char *buf);
Chris@0 135 static void two_param_decode(const snd_seq_event_t *ev, unsigned char *buf);
Chris@0 136 static void songpos_decode(const snd_seq_event_t *ev, unsigned char *buf);
Chris@0 137
Chris@0 138 /*
Chris@0 139 * event list
Chris@0 140 */
Chris@0 141 static struct status_event_list_t {
Chris@0 142 int event;
Chris@0 143 int qlen;
Chris@0 144 event_encode_t encode;
Chris@0 145 event_decode_t decode;
Chris@0 146 } status_event[] = {
Chris@0 147 /* 0x80 - 0xf0 */
Chris@0 148 {SND_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
Chris@0 149 {SND_SEQ_EVENT_NOTEON, 2, note_event, note_decode},
Chris@0 150 {SND_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode},
Chris@0 151 {SND_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode},
Chris@0 152 {SND_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode},
Chris@0 153 {SND_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode},
Chris@0 154 {SND_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode},
Chris@0 155 {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */
Chris@0 156 /* 0xf0 - 0xff */
Chris@0 157 {SND_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */
Chris@0 158 {SND_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */
Chris@0 159 {SND_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */
Chris@0 160 {SND_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */
Chris@0 161 {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */
Chris@0 162 {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */
Chris@0 163 {SND_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */
Chris@0 164 {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */
Chris@0 165 {SND_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */
Chris@0 166 {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */
Chris@0 167 {SND_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */
Chris@0 168 {SND_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */
Chris@0 169 {SND_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */
Chris@0 170 {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */
Chris@0 171 {SND_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */
Chris@0 172 {SND_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
Chris@0 173 };
Chris@0 174
Chris@0 175 #ifdef UNNEEDED_BY_DSSI
Chris@0 176 static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, const snd_seq_event_t *ev);
Chris@0 177 static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, const snd_seq_event_t *ev);
Chris@0 178
Chris@0 179 static struct extra_event_list_t {
Chris@0 180 int event;
Chris@0 181 int (*decode)(snd_midi_event_t *dev, unsigned char *buf, int len, const snd_seq_event_t *ev);
Chris@0 182 } extra_event[] = {
Chris@0 183 {SND_SEQ_EVENT_CONTROL14, extra_decode_ctrl14},
Chris@0 184 {SND_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn},
Chris@0 185 {SND_SEQ_EVENT_REGPARAM, extra_decode_xrpn},
Chris@0 186 };
Chris@0 187
Chris@0 188 #define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
Chris@0 189 #endif /* UNNEEDED_BY_DSSI */
Chris@0 190
Chris@0 191 /**
Chris@0 192 * \brief Initialize MIDI event parser
Chris@0 193 * \param bufsize buffer size for MIDI message
Chris@0 194 * \param rdev allocated MIDI event parser
Chris@0 195 * \return 0 on success otherwise a negative error code
Chris@0 196 *
Chris@0 197 * Allocates and initializes MIDI event parser.
Chris@0 198 */
Chris@0 199 int snd_midi_event_new(size_t bufsize, snd_midi_event_t **rdev)
Chris@0 200 {
Chris@0 201 snd_midi_event_t *dev;
Chris@0 202
Chris@0 203 *rdev = NULL;
Chris@0 204 dev = (snd_midi_event_t *)calloc(1, sizeof(snd_midi_event_t));
Chris@0 205 if (dev == NULL)
Chris@0 206 return -ENOMEM;
Chris@0 207 if (bufsize > 0) {
Chris@0 208 dev->buf = malloc(bufsize);
Chris@0 209 if (dev->buf == NULL) {
Chris@0 210 free(dev);
Chris@0 211 return -ENOMEM;
Chris@0 212 }
Chris@0 213 }
Chris@0 214 dev->bufsize = bufsize;
Chris@0 215 dev->lastcmd = 0xff;
Chris@0 216 *rdev = dev;
Chris@0 217 return 0;
Chris@0 218 }
Chris@0 219
Chris@0 220 /**
Chris@0 221 * \brief Free MIDI event parser
Chris@0 222 * \param rdev MIDI event parser
Chris@0 223 * \return 0 on success otherwise a negative error code
Chris@0 224 *
Chris@0 225 * Frees MIDI event parser.
Chris@0 226 */
Chris@0 227 void snd_midi_event_free(snd_midi_event_t *dev)
Chris@0 228 {
Chris@0 229 if (dev != NULL) {
Chris@0 230 if (dev->buf)
Chris@0 231 free(dev->buf);
Chris@0 232 free(dev);
Chris@0 233 }
Chris@0 234 }
Chris@0 235
Chris@0 236 #ifdef UNNEEDED_BY_DSSI
Chris@0 237 /**
Chris@0 238 * \brief Enable/disable MIDI command merging
Chris@0 239 * \param dev MIDI event parser
Chris@0 240 * \param on 0 - enable MIDI command merging, 1 - always pass the command
Chris@0 241 *
Chris@0 242 * Enable/disable MIDI command merging
Chris@0 243 */
Chris@0 244 void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
Chris@0 245 {
Chris@0 246 dev->nostat = on ? 1 : 0;
Chris@0 247 }
Chris@0 248 #endif /* UNNEEDED_BY_DSSI */
Chris@0 249
Chris@0 250 /*
Chris@0 251 * initialize record
Chris@0 252 */
Chris@0 253 inline static void reset_encode(snd_midi_event_t *dev)
Chris@0 254 {
Chris@0 255 dev->read = 0;
Chris@0 256 dev->qlen = 0;
Chris@0 257 dev->type = 0;
Chris@0 258 }
Chris@0 259
Chris@0 260 /**
Chris@0 261 * \brief Reset MIDI encode parser
Chris@0 262 * \param dev MIDI event parser
Chris@0 263 * \return 0 on success otherwise a negative error code
Chris@0 264 *
Chris@0 265 * Resets MIDI encode parser
Chris@0 266 */
Chris@0 267 void snd_midi_event_reset_encode(snd_midi_event_t *dev)
Chris@0 268 {
Chris@0 269 reset_encode(dev);
Chris@0 270 }
Chris@0 271
Chris@0 272 #ifdef UNNEEDED_BY_DSSI
Chris@0 273 /**
Chris@0 274 * \brief Reset MIDI decode parser
Chris@0 275 * \param dev MIDI event parser
Chris@0 276 * \return 0 on success otherwise a negative error code
Chris@0 277 *
Chris@0 278 * Resets MIDI decode parser
Chris@0 279 */
Chris@0 280 void snd_midi_event_reset_decode(snd_midi_event_t *dev)
Chris@0 281 {
Chris@0 282 dev->lastcmd = 0xff;
Chris@0 283 }
Chris@0 284
Chris@0 285 /**
Chris@0 286 * \brief Initializes MIDI parsers
Chris@0 287 * \param dev MIDI event parser
Chris@0 288 * \return 0 on success otherwise a negative error code
Chris@0 289 *
Chris@0 290 * Initializes MIDI parsers (both encode and decode)
Chris@0 291 */
Chris@0 292 void snd_midi_event_init(snd_midi_event_t *dev)
Chris@0 293 {
Chris@0 294 snd_midi_event_reset_encode(dev);
Chris@0 295 snd_midi_event_reset_decode(dev);
Chris@0 296 }
Chris@0 297
Chris@0 298 /**
Chris@0 299 * \brief Resize MIDI message (event) buffer
Chris@0 300 * \param dev MIDI event parser
Chris@0 301 * \param bufsize new requested buffer size
Chris@0 302 * \return 0 on success otherwise a negative error code
Chris@0 303 *
Chris@0 304 * Resizes MIDI message (event) buffer.
Chris@0 305 */
Chris@0 306 int snd_midi_event_resize_buffer(snd_midi_event_t *dev, size_t bufsize)
Chris@0 307 {
Chris@0 308 unsigned char *new_buf, *old_buf;
Chris@0 309
Chris@0 310 if (bufsize == dev->bufsize)
Chris@0 311 return 0;
Chris@0 312 new_buf = malloc(bufsize);
Chris@0 313 if (new_buf == NULL)
Chris@0 314 return -ENOMEM;
Chris@0 315 old_buf = dev->buf;
Chris@0 316 dev->buf = new_buf;
Chris@0 317 dev->bufsize = bufsize;
Chris@0 318 reset_encode(dev);
Chris@0 319 if (old_buf)
Chris@0 320 free(old_buf);
Chris@0 321 return 0;
Chris@0 322 }
Chris@0 323 #endif /* UNNEEDED_BY_DSSI */
Chris@0 324
Chris@0 325 /**
Chris@0 326 * \brief Read bytes and encode to sequencer event if finished
Chris@0 327 * \param dev MIDI event parser
Chris@0 328 * \param buf MIDI byte stream
Chris@0 329 * \param count count of bytes of MIDI byte stream to encode
Chris@0 330 * \param ev Result - sequencer event
Chris@0 331 * \return count of encoded bytes otherwise a negative error code
Chris@0 332 *
Chris@0 333 * Read bytes and encode to sequencer event if finished.
Chris@0 334 * If complete sequencer event is available, ev->type is not
Chris@0 335 * equal to #SND_SEQ_EVENT_NONE.
Chris@0 336 */
Chris@0 337 long snd_midi_event_encode(snd_midi_event_t *dev, const unsigned char *buf, long count, snd_seq_event_t *ev)
Chris@0 338 {
Chris@0 339 long result = 0;
Chris@0 340 int rc;
Chris@0 341
Chris@0 342 ev->type = SND_SEQ_EVENT_NONE;
Chris@0 343
Chris@0 344 while (count-- > 0) {
Chris@0 345 rc = snd_midi_event_encode_byte(dev, *buf++, ev);
Chris@0 346 result++;
Chris@0 347 if (rc < 0)
Chris@0 348 return rc;
Chris@0 349 else if (rc > 0)
Chris@0 350 return result;
Chris@0 351 }
Chris@0 352
Chris@0 353 return result;
Chris@0 354 }
Chris@0 355
Chris@0 356 /**
Chris@0 357 * \brief Read one byte and encode to sequencer event if finished
Chris@0 358 * \param dev MIDI event parser
Chris@0 359 * \param c a byte of MIDI stream
Chris@0 360 * \param ev Result - sequencer event
Chris@0 361 * \return 1 - sequencer event is completed, 0 - next byte is required for completion, otherwise a negative error code
Chris@0 362 *
Chris@0 363 * Read byte and encode to sequencer event if finished.
Chris@0 364 */
Chris@0 365 int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev)
Chris@0 366 {
Chris@0 367 int rc = 0;
Chris@0 368
Chris@0 369 c &= 0xff;
Chris@0 370
Chris@0 371 if (c >= MIDI_CMD_COMMON_CLOCK) {
Chris@0 372 /* real-time event */
Chris@0 373 ev->type = status_event[ST_SPECIAL + c - 0xf0].event;
Chris@0 374 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
Chris@0 375 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
Chris@0 376 return 1;
Chris@0 377 }
Chris@0 378
Chris@0 379 if (dev->qlen > 0) {
Chris@0 380 /* rest of command */
Chris@0 381 dev->buf[dev->read++] = c;
Chris@0 382 if (dev->type != ST_SYSEX)
Chris@0 383 dev->qlen--;
Chris@0 384 } else {
Chris@0 385 /* new command */
Chris@0 386 dev->read = 1;
Chris@0 387 if (c & 0x80) {
Chris@0 388 dev->buf[0] = c;
Chris@0 389 if ((c & 0xf0) == 0xf0) /* special events */
Chris@0 390 dev->type = (c & 0x0f) + ST_SPECIAL;
Chris@0 391 else
Chris@0 392 dev->type = (c >> 4) & 0x07;
Chris@0 393 dev->qlen = status_event[dev->type].qlen;
Chris@0 394 } else {
Chris@0 395 /* process this byte as argument */
Chris@0 396 dev->buf[dev->read++] = c;
Chris@0 397 dev->qlen = status_event[dev->type].qlen - 1;
Chris@0 398 }
Chris@0 399 }
Chris@0 400 if (dev->qlen == 0) {
Chris@0 401 ev->type = status_event[dev->type].event;
Chris@0 402 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
Chris@0 403 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
Chris@0 404 if (status_event[dev->type].encode) /* set data values */
Chris@0 405 status_event[dev->type].encode(dev, ev);
Chris@0 406 rc = 1;
Chris@0 407 } else if (dev->type == ST_SYSEX) {
Chris@0 408 if (c == MIDI_CMD_COMMON_SYSEX_END ||
Chris@0 409 dev->read >= dev->bufsize) {
Chris@0 410 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
Chris@0 411 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
Chris@0 412 ev->type = SNDRV_SEQ_EVENT_SYSEX;
Chris@0 413 ev->data.ext.len = dev->read;
Chris@0 414 ev->data.ext.ptr = dev->buf;
Chris@0 415 if (c != MIDI_CMD_COMMON_SYSEX_END)
Chris@0 416 dev->read = 0; /* continue to parse */
Chris@0 417 else
Chris@0 418 reset_encode(dev); /* all parsed */
Chris@0 419 rc = 1;
Chris@0 420 }
Chris@0 421 }
Chris@0 422
Chris@0 423 return rc;
Chris@0 424 }
Chris@0 425
Chris@0 426 /* encode note event */
Chris@0 427 static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
Chris@0 428 {
Chris@0 429 ev->data.note.channel = dev->buf[0] & 0x0f;
Chris@0 430 ev->data.note.note = dev->buf[1];
Chris@0 431 ev->data.note.velocity = dev->buf[2];
Chris@0 432 }
Chris@0 433
Chris@0 434 /* encode one parameter controls */
Chris@0 435 static void one_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
Chris@0 436 {
Chris@0 437 ev->data.control.channel = dev->buf[0] & 0x0f;
Chris@0 438 ev->data.control.value = dev->buf[1];
Chris@0 439 }
Chris@0 440
Chris@0 441 /* encode pitch wheel change */
Chris@0 442 static void pitchbend_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
Chris@0 443 {
Chris@0 444 ev->data.control.channel = dev->buf[0] & 0x0f;
Chris@0 445 ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192;
Chris@0 446 }
Chris@0 447
Chris@0 448 /* encode midi control change */
Chris@0 449 static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
Chris@0 450 {
Chris@0 451 ev->data.control.channel = dev->buf[0] & 0x0f;
Chris@0 452 ev->data.control.param = dev->buf[1];
Chris@0 453 ev->data.control.value = dev->buf[2];
Chris@0 454 }
Chris@0 455
Chris@0 456 /* encode one parameter value*/
Chris@0 457 static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
Chris@0 458 {
Chris@0 459 ev->data.control.value = dev->buf[1];
Chris@0 460 }
Chris@0 461
Chris@0 462 /* encode song position */
Chris@0 463 static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
Chris@0 464 {
Chris@0 465 ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1];
Chris@0 466 }
Chris@0 467
Chris@0 468 #ifdef UNNEEDED_BY_DSSI
Chris@0 469 /**
Chris@0 470 * \brief Decode sequencer event to MIDI byte stream
Chris@0 471 * \param dev MIDI event parser
Chris@0 472 * \param buf Result - MIDI byte stream
Chris@0 473 * \param count Available bytes in MIDI byte stream
Chris@0 474 * \param ev Event to decode
Chris@0 475 * \return count of decoded bytes otherwise a negative error code
Chris@0 476 *
Chris@0 477 * Decode sequencer event to MIDI byte stream.
Chris@0 478 */
Chris@0 479 long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count, const snd_seq_event_t *ev)
Chris@0 480 {
Chris@0 481 int cmd;
Chris@0 482 long qlen;
Chris@0 483 unsigned int type;
Chris@0 484
Chris@0 485 if (ev->type == SNDRV_SEQ_EVENT_NONE)
Chris@0 486 return -ENOENT;
Chris@0 487
Chris@0 488 for (type = 0; type < numberof(status_event); type++) {
Chris@0 489 if (ev->type == status_event[type].event)
Chris@0 490 goto __found;
Chris@0 491 }
Chris@0 492 for (type = 0; type < numberof(extra_event); type++) {
Chris@0 493 if (ev->type == extra_event[type].event)
Chris@0 494 return extra_event[type].decode(dev, buf, count, ev);
Chris@0 495 }
Chris@0 496 return -ENOENT;
Chris@0 497
Chris@0 498 __found:
Chris@0 499 if (type >= ST_SPECIAL)
Chris@0 500 cmd = 0xf0 + (type - ST_SPECIAL);
Chris@0 501 else
Chris@0 502 /* data.note.channel and data.control.channel is identical */
Chris@0 503 cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f);
Chris@0 504
Chris@0 505
Chris@0 506 if (cmd == MIDI_CMD_COMMON_SYSEX) {
Chris@0 507 qlen = ev->data.ext.len;
Chris@0 508 if (count < qlen)
Chris@0 509 return -ENOMEM;
Chris@0 510 switch (ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) {
Chris@0 511 case SNDRV_SEQ_EVENT_LENGTH_FIXED:
Chris@0 512 return -EINVAL; /* invalid event */
Chris@0 513 }
Chris@0 514 memcpy(buf, ev->data.ext.ptr, qlen);
Chris@0 515 return qlen;
Chris@0 516 } else {
Chris@0 517 unsigned char xbuf[4];
Chris@0 518
Chris@0 519 if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) {
Chris@0 520 dev->lastcmd = cmd;
Chris@0 521 xbuf[0] = cmd;
Chris@0 522 if (status_event[type].decode)
Chris@0 523 status_event[type].decode(ev, xbuf + 1);
Chris@0 524 qlen = status_event[type].qlen + 1;
Chris@0 525 } else {
Chris@0 526 if (status_event[type].decode)
Chris@0 527 status_event[type].decode(ev, xbuf + 0);
Chris@0 528 qlen = status_event[type].qlen;
Chris@0 529 }
Chris@0 530 if (count < qlen)
Chris@0 531 return -ENOMEM;
Chris@0 532 memcpy(buf, xbuf, qlen);
Chris@0 533 return qlen;
Chris@0 534 }
Chris@0 535 }
Chris@0 536 #endif /* UNNEEDED_BY_DSSI */
Chris@0 537
Chris@0 538 /* decode note event */
Chris@0 539 static void note_decode(const snd_seq_event_t *ev, unsigned char *buf)
Chris@0 540 {
Chris@0 541 buf[0] = ev->data.note.note & 0x7f;
Chris@0 542 buf[1] = ev->data.note.velocity & 0x7f;
Chris@0 543 }
Chris@0 544
Chris@0 545 /* decode one parameter controls */
Chris@0 546 static void one_param_decode(const snd_seq_event_t *ev, unsigned char *buf)
Chris@0 547 {
Chris@0 548 buf[0] = ev->data.control.value & 0x7f;
Chris@0 549 }
Chris@0 550
Chris@0 551 /* decode pitch wheel change */
Chris@0 552 static void pitchbend_decode(const snd_seq_event_t *ev, unsigned char *buf)
Chris@0 553 {
Chris@0 554 int value = ev->data.control.value + 8192;
Chris@0 555 buf[0] = value & 0x7f;
Chris@0 556 buf[1] = (value >> 7) & 0x7f;
Chris@0 557 }
Chris@0 558
Chris@0 559 /* decode midi control change */
Chris@0 560 static void two_param_decode(const snd_seq_event_t *ev, unsigned char *buf)
Chris@0 561 {
Chris@0 562 buf[0] = ev->data.control.param & 0x7f;
Chris@0 563 buf[1] = ev->data.control.value & 0x7f;
Chris@0 564 }
Chris@0 565
Chris@0 566 /* decode song position */
Chris@0 567 static void songpos_decode(const snd_seq_event_t *ev, unsigned char *buf)
Chris@0 568 {
Chris@0 569 buf[0] = ev->data.control.value & 0x7f;
Chris@0 570 buf[1] = (ev->data.control.value >> 7) & 0x7f;
Chris@0 571 }
Chris@0 572
Chris@0 573 #ifdef UNNEEDED_BY_DSSI
Chris@0 574 /* decode 14bit control */
Chris@0 575 static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int count, const snd_seq_event_t *ev)
Chris@0 576 {
Chris@0 577 unsigned char cmd;
Chris@0 578 int idx = 0;
Chris@0 579
Chris@0 580 cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
Chris@0 581 if (ev->data.control.param < 32) {
Chris@0 582 if (count < 4)
Chris@0 583 return -ENOMEM;
Chris@0 584 if (dev->nostat && count < 6)
Chris@0 585 return -ENOMEM;
Chris@0 586 if (cmd != dev->lastcmd || dev->nostat) {
Chris@0 587 if (count < 5)
Chris@0 588 return -ENOMEM;
Chris@0 589 buf[idx++] = dev->lastcmd = cmd;
Chris@0 590 }
Chris@0 591 buf[idx++] = ev->data.control.param;
Chris@0 592 buf[idx++] = (ev->data.control.value >> 7) & 0x7f;
Chris@0 593 if (dev->nostat)
Chris@0 594 buf[idx++] = cmd;
Chris@0 595 buf[idx++] = ev->data.control.param + 32;
Chris@0 596 buf[idx++] = ev->data.control.value & 0x7f;
Chris@0 597 } else {
Chris@0 598 if (count < 2)
Chris@0 599 return -ENOMEM;
Chris@0 600 if (cmd != dev->lastcmd || dev->nostat) {
Chris@0 601 if (count < 3)
Chris@0 602 return -ENOMEM;
Chris@0 603 buf[idx++] = dev->lastcmd = cmd;
Chris@0 604 }
Chris@0 605 buf[idx++] = ev->data.control.param & 0x7f;
Chris@0 606 buf[idx++] = ev->data.control.value & 0x7f;
Chris@0 607 }
Chris@0 608 return idx;
Chris@0 609 }
Chris@0 610
Chris@0 611 /* decode reg/nonreg param */
Chris@0 612 static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, const snd_seq_event_t *ev)
Chris@0 613 {
Chris@0 614 unsigned char cmd;
Chris@0 615 char *cbytes;
Chris@0 616 static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
Chris@0 617 MIDI_CTL_NONREG_PARM_NUM_LSB,
Chris@0 618 MIDI_CTL_MSB_DATA_ENTRY,
Chris@0 619 MIDI_CTL_LSB_DATA_ENTRY };
Chris@0 620 static char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB,
Chris@0 621 MIDI_CTL_REGIST_PARM_NUM_LSB,
Chris@0 622 MIDI_CTL_MSB_DATA_ENTRY,
Chris@0 623 MIDI_CTL_LSB_DATA_ENTRY };
Chris@0 624 unsigned char bytes[4];
Chris@0 625 int idx = 0, i;
Chris@0 626
Chris@0 627 if (count < 8)
Chris@0 628 return -ENOMEM;
Chris@0 629 if (dev->nostat && count < 12)
Chris@0 630 return -ENOMEM;
Chris@0 631 cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
Chris@0 632 bytes[0] = ev->data.control.param & 0x007f;
Chris@0 633 bytes[1] = (ev->data.control.param & 0x3f80) >> 7;
Chris@0 634 bytes[2] = ev->data.control.value & 0x007f;
Chris@0 635 bytes[3] = (ev->data.control.value & 0x3f80) >> 7;
Chris@0 636 if (cmd != dev->lastcmd && !dev->nostat) {
Chris@0 637 if (count < 9)
Chris@0 638 return -ENOMEM;
Chris@0 639 buf[idx++] = dev->lastcmd = cmd;
Chris@0 640 }
Chris@0 641 cbytes = ev->type == SND_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn;
Chris@0 642 for (i = 0; i < 4; i++) {
Chris@0 643 if (dev->nostat)
Chris@0 644 buf[idx++] = dev->lastcmd = cmd;
Chris@0 645 buf[idx++] = cbytes[i];
Chris@0 646 buf[idx++] = bytes[i];
Chris@0 647 }
Chris@0 648 return idx;
Chris@0 649 }
Chris@0 650 #endif /* UNNEEDED_BY_DSSI */