lbajardsilogic@0: /* DSSI ALSA compatibility library lbajardsilogic@0: * lbajardsilogic@0: * This library provides for non-ALSA systems the ALSA snd_seq_event_t handling lbajardsilogic@0: * necessary to compile and run DSSI. It was extracted from alsa-lib 1.0.8. lbajardsilogic@0: * lbajardsilogic@0: * See ./alsa/README for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include "alsa/asoundef.h" lbajardsilogic@0: #include "alsa/sound/asequencer.h" lbajardsilogic@0: #include "alsa/seq.h" lbajardsilogic@0: #include "alsa/seq_event.h" lbajardsilogic@0: #include "alsa/seq_midi_event.h" lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \file seq/seq_event.c lbajardsilogic@0: * \brief Sequencer Event Types lbajardsilogic@0: * \author Takashi Iwai lbajardsilogic@0: * \date 2001 lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #define FIXED_EV(x) (_SND_SEQ_TYPE(SND_SEQ_EVFLG_FIXED) | _SND_SEQ_TYPE(x)) lbajardsilogic@0: lbajardsilogic@0: /** Event types conversion array */ lbajardsilogic@0: const unsigned int snd_seq_event_types[256] = { lbajardsilogic@0: lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RESULT), // SND_SEQ_EVENT_SYSTEM = 0 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RESULT), // SND_SEQ_EVENT_RESULT lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NOTE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_NOTE_TWOARG), // SND_SEQ_EVENT_NOTE = 5 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NOTE), // SND_SEQ_EVENT_NOTEON lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NOTE), // SND_SEQ_EVENT_NOTEOFF lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NOTE), // SND_SEQ_EVENT_KEYPRESS lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_CONTROLLER = 10 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_PGMCHANGE lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_CHANPRESS lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_PITCHBEND lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_CONTROL14 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_NONREGPARAM lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONTROL),// SND_SEQ_EVENT_REGPARAM lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, // = 20 lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE), // SND_SEQ_EVENT_START = 30 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE), // SND_SEQ_EVENT_CONTINUE lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE), // SND_SEQ_EVENT_STOP lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TICK), // SND_SEQ_EVENT_SETPOS_TICK lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TIME), // SND_SEQ_EVENT_SETPOS_TIME lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE),// SND_SEQ_EVENT_TEMPO lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE),// SND_SEQ_EVENT_CLOCK lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE),// SND_SEQ_EVENT_TICK lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE),// SND_SEQ_EVENT_QUEUE_SKEW lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE),// SND_SEQ_EVENT_SYNC_POS lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NONE), // SND_SEQ_EVENT_TUNE_REQUEST = 40 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NONE), // SND_SEQ_EVENT_RESET lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NONE), // SND_SEQ_EVENT_SENSING lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_SYSTEM), // SND_SEQ_EVENT_ECHO = 50 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_SYSTEM), // SND_SEQ_EVENT_OSS lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_MESSAGE), // SND_SEQ_EVENT_CLIENT_START = 60 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_MESSAGE), // SND_SEQ_EVENT_CLIENT_EXIT lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_MESSAGE), // SND_SEQ_EVENT_CLIENT_CHANGE lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_MESSAGE), // SND_SEQ_EVENT_PORT_START lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_MESSAGE), // SND_SEQ_EVENT_PORT_EXIT lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_MESSAGE), // SND_SEQ_EVENT_PORT_CHANGE lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONNECTION), // SND_SEQ_EVENT_PORT_SUBSCRIBED lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_CONNECTION), // SND_SEQ_EVENT_PORT_UNSUBSCRIBED lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE = 70 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_CLUSTER lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_START lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_STOP lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_FREQ lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_VOLUME lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_LOOP lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_POSITION lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_SAMPLE), // SND_SEQ_EVENT_SAMPLE_PRIVATE1 lbajardsilogic@0: 0, lbajardsilogic@0: 0, // = 80 lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR0 = 90, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR1 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR2 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR3 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR4 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR5 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR6 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR7 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR8 lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), // SND_SEQ_EVENT_USR9 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_BEGIN = 100 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_END lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_INFO lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_INFO_RESULT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_FINFO lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_FINFO_RESULT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_RESET lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_STATUS lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_STATUS_RESULT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_PUT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_GET lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_GET_RESULT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_FREE lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_LIST lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_LIST_RESULT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_CLUSTER lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_CLUSTER_GET lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_CLUSTER_RESULT lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_END lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), // SND_SEQ_EVENT_INSTR_CHANGE lbajardsilogic@0: 0, // = 120 lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE), // SND_SEQ_EVENT_SYSEX = 130 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE), // SND_SEQ_EVENT_BOUNCE lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS),// SND_SEQ_EVENT_USR_VAR0 = 135 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS),// SND_SEQ_EVENT_USR_VAR1 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS),// SND_SEQ_EVENT_USR_VAR2 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS),// SND_SEQ_EVENT_USR_VAR3 lbajardsilogic@0: _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS),// SND_SEQ_EVENT_USR_VAR4 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140 -> 149 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150 -> 159 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 -> 169 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170 -> 179 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180 -> 189 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190 -> 199 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200 -> 209 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210 -> 219 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220 -> 229 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230 -> 239 lbajardsilogic@0: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240 -> 249 lbajardsilogic@0: 0, // = 250 lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: 0, lbajardsilogic@0: FIXED_EV(SND_SEQ_EVFLG_NONE), // SND_SEQ_EVENT_NONE = 255 lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: /*const unsigned int snd_seq_event_types[256] = { lbajardsilogic@0: [SND_SEQ_EVENT_SYSTEM ... SND_SEQ_EVENT_RESULT] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_RESULT), lbajardsilogic@0: [SND_SEQ_EVENT_NOTE] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_NOTE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_NOTE_TWOARG), lbajardsilogic@0: [SND_SEQ_EVENT_NOTEON ... SND_SEQ_EVENT_KEYPRESS] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_NOTE), lbajardsilogic@0: [SND_SEQ_EVENT_CONTROLLER ... SND_SEQ_EVENT_REGPARAM] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_CONTROL), lbajardsilogic@0: [SND_SEQ_EVENT_START ... SND_SEQ_EVENT_STOP] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_QUEUE), lbajardsilogic@0: [SND_SEQ_EVENT_SETPOS_TICK] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TICK), lbajardsilogic@0: [SND_SEQ_EVENT_SETPOS_TIME] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TIME), lbajardsilogic@0: [SND_SEQ_EVENT_TEMPO ... SND_SEQ_EVENT_SYNC_POS] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE), lbajardsilogic@0: [SND_SEQ_EVENT_TUNE_REQUEST ... SND_SEQ_EVENT_SENSING] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_NONE), lbajardsilogic@0: [SND_SEQ_EVENT_ECHO ... SND_SEQ_EVENT_OSS] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_SYSTEM), lbajardsilogic@0: [SND_SEQ_EVENT_CLIENT_START ... SND_SEQ_EVENT_PORT_CHANGE] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_MESSAGE), lbajardsilogic@0: [SND_SEQ_EVENT_PORT_SUBSCRIBED ... SND_SEQ_EVENT_PORT_UNSUBSCRIBED] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_CONNECTION), lbajardsilogic@0: [SND_SEQ_EVENT_SAMPLE ... SND_SEQ_EVENT_SAMPLE_PRIVATE1] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_SAMPLE), lbajardsilogic@0: [SND_SEQ_EVENT_USR0 ... SND_SEQ_EVENT_USR9] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), lbajardsilogic@0: [SND_SEQ_EVENT_INSTR_BEGIN ... SND_SEQ_EVENT_INSTR_CHANGE] lbajardsilogic@0: = _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), lbajardsilogic@0: [SND_SEQ_EVENT_SYSEX ... SND_SEQ_EVENT_BOUNCE] lbajardsilogic@0: = _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE), lbajardsilogic@0: [SND_SEQ_EVENT_USR_VAR0 ... SND_SEQ_EVENT_USR_VAR4] lbajardsilogic@0: = _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS), lbajardsilogic@0: [SND_SEQ_EVENT_NONE] lbajardsilogic@0: = FIXED_EV(SND_SEQ_EVFLG_NONE), lbajardsilogic@0: };*/ lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \file seq/seq_midi_event.c lbajardsilogic@0: * \brief MIDI byte <-> sequencer event coder lbajardsilogic@0: * \author Takashi Iwai lbajardsilogic@0: * \author Jaroslav Kysela lbajardsilogic@0: * \date 2000-2001 lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: * MIDI byte <-> sequencer event coder lbajardsilogic@0: * lbajardsilogic@0: * Copyright (C) 1998,99,2000 Takashi Iwai , lbajardsilogic@0: * Jaroslav Kysela lbajardsilogic@0: * lbajardsilogic@0: * lbajardsilogic@0: * This library is free software; you can redistribute it and/or modify lbajardsilogic@0: * it under the terms of the GNU Lesser General Public License as lbajardsilogic@0: * published by the Free Software Foundation; either version 2.1 of lbajardsilogic@0: * the License, or (at your option) any later version. lbajardsilogic@0: * lbajardsilogic@0: * This program is distributed in the hope that it will be useful, lbajardsilogic@0: * but WITHOUT ANY WARRANTY; without even the implied warranty of lbajardsilogic@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the lbajardsilogic@0: * GNU Lesser General Public License for more details. lbajardsilogic@0: * lbajardsilogic@0: * You should have received a copy of the GNU Lesser General Public lbajardsilogic@0: * License along with this library; if not, write to the Free Software lbajardsilogic@0: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: /* midi status */ lbajardsilogic@0: struct snd_midi_event { lbajardsilogic@0: size_t qlen; /* queue length */ lbajardsilogic@0: size_t read; /* chars read */ lbajardsilogic@0: int type; /* current event type */ lbajardsilogic@0: unsigned char lastcmd; lbajardsilogic@0: unsigned char nostat; lbajardsilogic@0: size_t bufsize; lbajardsilogic@0: unsigned char *buf; /* input buffer */ lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: /* queue type */ lbajardsilogic@0: /* from 0 to 7 are normal commands (note off, on, etc.) */ lbajardsilogic@0: #define ST_NOTEOFF 0 lbajardsilogic@0: #define ST_NOTEON 1 lbajardsilogic@0: #define ST_SPECIAL 8 lbajardsilogic@0: #define ST_SYSEX ST_SPECIAL lbajardsilogic@0: /* from 8 to 15 are events for 0xf0-0xf7 */ lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: /* status event types */ lbajardsilogic@0: typedef void (*event_encode_t)(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: typedef void (*event_decode_t)(const snd_seq_event_t *ev, unsigned char *buf); lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: * prototypes lbajardsilogic@0: */ lbajardsilogic@0: static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: static void one_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: static void pitchbend_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev); lbajardsilogic@0: static void note_decode(const snd_seq_event_t *ev, unsigned char *buf); lbajardsilogic@0: static void one_param_decode(const snd_seq_event_t *ev, unsigned char *buf); lbajardsilogic@0: static void pitchbend_decode(const snd_seq_event_t *ev, unsigned char *buf); lbajardsilogic@0: static void two_param_decode(const snd_seq_event_t *ev, unsigned char *buf); lbajardsilogic@0: static void songpos_decode(const snd_seq_event_t *ev, unsigned char *buf); lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: * event list lbajardsilogic@0: */ lbajardsilogic@0: static struct status_event_list_t { lbajardsilogic@0: int event; lbajardsilogic@0: int qlen; lbajardsilogic@0: event_encode_t encode; lbajardsilogic@0: event_decode_t decode; lbajardsilogic@0: } status_event[] = { lbajardsilogic@0: /* 0x80 - 0xf0 */ lbajardsilogic@0: {SND_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, lbajardsilogic@0: {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */ lbajardsilogic@0: /* 0xf0 - 0xff */ lbajardsilogic@0: {SND_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ lbajardsilogic@0: {SND_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ lbajardsilogic@0: {SND_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ lbajardsilogic@0: {SND_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ lbajardsilogic@0: {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */ lbajardsilogic@0: {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */ lbajardsilogic@0: {SND_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ lbajardsilogic@0: {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */ lbajardsilogic@0: {SND_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ lbajardsilogic@0: {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */ lbajardsilogic@0: {SND_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ lbajardsilogic@0: {SND_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ lbajardsilogic@0: {SND_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ lbajardsilogic@0: {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */ lbajardsilogic@0: {SND_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ lbajardsilogic@0: {SND_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: #ifdef UNNEEDED_BY_DSSI lbajardsilogic@0: static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, const snd_seq_event_t *ev); lbajardsilogic@0: static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, const snd_seq_event_t *ev); lbajardsilogic@0: lbajardsilogic@0: static struct extra_event_list_t { lbajardsilogic@0: int event; lbajardsilogic@0: int (*decode)(snd_midi_event_t *dev, unsigned char *buf, int len, const snd_seq_event_t *ev); lbajardsilogic@0: } extra_event[] = { lbajardsilogic@0: {SND_SEQ_EVENT_CONTROL14, extra_decode_ctrl14}, lbajardsilogic@0: {SND_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn}, lbajardsilogic@0: {SND_SEQ_EVENT_REGPARAM, extra_decode_xrpn}, lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: #define numberof(ary) (sizeof(ary)/sizeof(ary[0])) lbajardsilogic@0: #endif /* UNNEEDED_BY_DSSI */ lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Initialize MIDI event parser lbajardsilogic@0: * \param bufsize buffer size for MIDI message lbajardsilogic@0: * \param rdev allocated MIDI event parser lbajardsilogic@0: * \return 0 on success otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Allocates and initializes MIDI event parser. lbajardsilogic@0: */ lbajardsilogic@0: int snd_midi_event_new(size_t bufsize, snd_midi_event_t **rdev) lbajardsilogic@0: { lbajardsilogic@0: snd_midi_event_t *dev; lbajardsilogic@0: lbajardsilogic@0: *rdev = NULL; lbajardsilogic@0: dev = (snd_midi_event_t *)calloc(1, sizeof(snd_midi_event_t)); lbajardsilogic@0: if (dev == NULL) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: if (bufsize > 0) { lbajardsilogic@0: dev->buf = malloc(bufsize); lbajardsilogic@0: if (dev->buf == NULL) { lbajardsilogic@0: free(dev); lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: dev->bufsize = bufsize; lbajardsilogic@0: dev->lastcmd = 0xff; lbajardsilogic@0: *rdev = dev; lbajardsilogic@0: return 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Free MIDI event parser lbajardsilogic@0: * \param rdev MIDI event parser lbajardsilogic@0: * \return 0 on success otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Frees MIDI event parser. lbajardsilogic@0: */ lbajardsilogic@0: void snd_midi_event_free(snd_midi_event_t *dev) lbajardsilogic@0: { lbajardsilogic@0: if (dev != NULL) { lbajardsilogic@0: if (dev->buf) lbajardsilogic@0: free(dev->buf); lbajardsilogic@0: free(dev); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef UNNEEDED_BY_DSSI lbajardsilogic@0: /** lbajardsilogic@0: * \brief Enable/disable MIDI command merging lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \param on 0 - enable MIDI command merging, 1 - always pass the command lbajardsilogic@0: * lbajardsilogic@0: * Enable/disable MIDI command merging lbajardsilogic@0: */ lbajardsilogic@0: void snd_midi_event_no_status(snd_midi_event_t *dev, int on) lbajardsilogic@0: { lbajardsilogic@0: dev->nostat = on ? 1 : 0; lbajardsilogic@0: } lbajardsilogic@0: #endif /* UNNEEDED_BY_DSSI */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: * initialize record lbajardsilogic@0: */ lbajardsilogic@0: //inline static void reset_encode(snd_midi_event_t *dev) lbajardsilogic@0: static void reset_encode(snd_midi_event_t *dev) lbajardsilogic@0: { lbajardsilogic@0: dev->read = 0; lbajardsilogic@0: dev->qlen = 0; lbajardsilogic@0: dev->type = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Reset MIDI encode parser lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \return 0 on success otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Resets MIDI encode parser lbajardsilogic@0: */ lbajardsilogic@0: void snd_midi_event_reset_encode(snd_midi_event_t *dev) lbajardsilogic@0: { lbajardsilogic@0: reset_encode(dev); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef UNNEEDED_BY_DSSI lbajardsilogic@0: /** lbajardsilogic@0: * \brief Reset MIDI decode parser lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \return 0 on success otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Resets MIDI decode parser lbajardsilogic@0: */ lbajardsilogic@0: void snd_midi_event_reset_decode(snd_midi_event_t *dev) lbajardsilogic@0: { lbajardsilogic@0: dev->lastcmd = 0xff; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Initializes MIDI parsers lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \return 0 on success otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Initializes MIDI parsers (both encode and decode) lbajardsilogic@0: */ lbajardsilogic@0: void snd_midi_event_init(snd_midi_event_t *dev) lbajardsilogic@0: { lbajardsilogic@0: snd_midi_event_reset_encode(dev); lbajardsilogic@0: snd_midi_event_reset_decode(dev); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Resize MIDI message (event) buffer lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \param bufsize new requested buffer size lbajardsilogic@0: * \return 0 on success otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Resizes MIDI message (event) buffer. lbajardsilogic@0: */ lbajardsilogic@0: int snd_midi_event_resize_buffer(snd_midi_event_t *dev, size_t bufsize) lbajardsilogic@0: { lbajardsilogic@0: unsigned char *new_buf, *old_buf; lbajardsilogic@0: lbajardsilogic@0: if (bufsize == dev->bufsize) lbajardsilogic@0: return 0; lbajardsilogic@0: new_buf = malloc(bufsize); lbajardsilogic@0: if (new_buf == NULL) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: old_buf = dev->buf; lbajardsilogic@0: dev->buf = new_buf; lbajardsilogic@0: dev->bufsize = bufsize; lbajardsilogic@0: reset_encode(dev); lbajardsilogic@0: if (old_buf) lbajardsilogic@0: free(old_buf); lbajardsilogic@0: return 0; lbajardsilogic@0: } lbajardsilogic@0: #endif /* UNNEEDED_BY_DSSI */ lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Read bytes and encode to sequencer event if finished lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \param buf MIDI byte stream lbajardsilogic@0: * \param count count of bytes of MIDI byte stream to encode lbajardsilogic@0: * \param ev Result - sequencer event lbajardsilogic@0: * \return count of encoded bytes otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Read bytes and encode to sequencer event if finished. lbajardsilogic@0: * If complete sequencer event is available, ev->type is not lbajardsilogic@0: * equal to #SND_SEQ_EVENT_NONE. lbajardsilogic@0: */ lbajardsilogic@0: long snd_midi_event_encode(snd_midi_event_t *dev, const unsigned char *buf, long count, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: long result = 0; lbajardsilogic@0: int rc; lbajardsilogic@0: lbajardsilogic@0: ev->type = SND_SEQ_EVENT_NONE; lbajardsilogic@0: lbajardsilogic@0: while (count-- > 0) { lbajardsilogic@0: rc = snd_midi_event_encode_byte(dev, *buf++, ev); lbajardsilogic@0: result++; lbajardsilogic@0: if (rc < 0) lbajardsilogic@0: return rc; lbajardsilogic@0: else if (rc > 0) lbajardsilogic@0: return result; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return result; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * \brief Read one byte and encode to sequencer event if finished lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \param c a byte of MIDI stream lbajardsilogic@0: * \param ev Result - sequencer event lbajardsilogic@0: * \return 1 - sequencer event is completed, 0 - next byte is required for completion, otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Read byte and encode to sequencer event if finished. lbajardsilogic@0: */ lbajardsilogic@0: int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: int rc = 0; lbajardsilogic@0: lbajardsilogic@0: c &= 0xff; lbajardsilogic@0: lbajardsilogic@0: if (c >= MIDI_CMD_COMMON_CLOCK) { lbajardsilogic@0: /* real-time event */ lbajardsilogic@0: ev->type = status_event[ST_SPECIAL + c - 0xf0].event; lbajardsilogic@0: ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; lbajardsilogic@0: ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; lbajardsilogic@0: return 1; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (dev->qlen > 0) { lbajardsilogic@0: /* rest of command */ lbajardsilogic@0: dev->buf[dev->read++] = c; lbajardsilogic@0: if (dev->type != ST_SYSEX) lbajardsilogic@0: dev->qlen--; lbajardsilogic@0: } else { lbajardsilogic@0: /* new command */ lbajardsilogic@0: dev->read = 1; lbajardsilogic@0: if (c & 0x80) { lbajardsilogic@0: dev->buf[0] = c; lbajardsilogic@0: if ((c & 0xf0) == 0xf0) /* special events */ lbajardsilogic@0: dev->type = (c & 0x0f) + ST_SPECIAL; lbajardsilogic@0: else lbajardsilogic@0: dev->type = (c >> 4) & 0x07; lbajardsilogic@0: dev->qlen = status_event[dev->type].qlen; lbajardsilogic@0: } else { lbajardsilogic@0: /* process this byte as argument */ lbajardsilogic@0: dev->buf[dev->read++] = c; lbajardsilogic@0: dev->qlen = status_event[dev->type].qlen - 1; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: if (dev->qlen == 0) { lbajardsilogic@0: ev->type = status_event[dev->type].event; lbajardsilogic@0: ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; lbajardsilogic@0: ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; lbajardsilogic@0: if (status_event[dev->type].encode) /* set data values */ lbajardsilogic@0: status_event[dev->type].encode(dev, ev); lbajardsilogic@0: rc = 1; lbajardsilogic@0: } else if (dev->type == ST_SYSEX) { lbajardsilogic@0: if (c == MIDI_CMD_COMMON_SYSEX_END || lbajardsilogic@0: dev->read >= dev->bufsize) { lbajardsilogic@0: ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; lbajardsilogic@0: ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE; lbajardsilogic@0: ev->type = SNDRV_SEQ_EVENT_SYSEX; lbajardsilogic@0: ev->data.ext.len = dev->read; lbajardsilogic@0: ev->data.ext.ptr = dev->buf; lbajardsilogic@0: if (c != MIDI_CMD_COMMON_SYSEX_END) lbajardsilogic@0: dev->read = 0; /* continue to parse */ lbajardsilogic@0: else lbajardsilogic@0: reset_encode(dev); /* all parsed */ lbajardsilogic@0: rc = 1; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return rc; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* encode note event */ lbajardsilogic@0: static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->data.note.channel = dev->buf[0] & 0x0f; lbajardsilogic@0: ev->data.note.note = dev->buf[1]; lbajardsilogic@0: ev->data.note.velocity = dev->buf[2]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* encode one parameter controls */ lbajardsilogic@0: static void one_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->data.control.channel = dev->buf[0] & 0x0f; lbajardsilogic@0: ev->data.control.value = dev->buf[1]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* encode pitch wheel change */ lbajardsilogic@0: static void pitchbend_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->data.control.channel = dev->buf[0] & 0x0f; lbajardsilogic@0: ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* encode midi control change */ lbajardsilogic@0: static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->data.control.channel = dev->buf[0] & 0x0f; lbajardsilogic@0: ev->data.control.param = dev->buf[1]; lbajardsilogic@0: ev->data.control.value = dev->buf[2]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* encode one parameter value*/ lbajardsilogic@0: static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->data.control.value = dev->buf[1]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* encode song position */ lbajardsilogic@0: static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef UNNEEDED_BY_DSSI lbajardsilogic@0: /** lbajardsilogic@0: * \brief Decode sequencer event to MIDI byte stream lbajardsilogic@0: * \param dev MIDI event parser lbajardsilogic@0: * \param buf Result - MIDI byte stream lbajardsilogic@0: * \param count Available bytes in MIDI byte stream lbajardsilogic@0: * \param ev Event to decode lbajardsilogic@0: * \return count of decoded bytes otherwise a negative error code lbajardsilogic@0: * lbajardsilogic@0: * Decode sequencer event to MIDI byte stream. lbajardsilogic@0: */ lbajardsilogic@0: long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count, const snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: int cmd; lbajardsilogic@0: long qlen; lbajardsilogic@0: unsigned int type; lbajardsilogic@0: lbajardsilogic@0: if (ev->type == SNDRV_SEQ_EVENT_NONE) lbajardsilogic@0: return -ENOENT; lbajardsilogic@0: lbajardsilogic@0: for (type = 0; type < numberof(status_event); type++) { lbajardsilogic@0: if (ev->type == status_event[type].event) lbajardsilogic@0: goto __found; lbajardsilogic@0: } lbajardsilogic@0: for (type = 0; type < numberof(extra_event); type++) { lbajardsilogic@0: if (ev->type == extra_event[type].event) lbajardsilogic@0: return extra_event[type].decode(dev, buf, count, ev); lbajardsilogic@0: } lbajardsilogic@0: return -ENOENT; lbajardsilogic@0: lbajardsilogic@0: __found: lbajardsilogic@0: if (type >= ST_SPECIAL) lbajardsilogic@0: cmd = 0xf0 + (type - ST_SPECIAL); lbajardsilogic@0: else lbajardsilogic@0: /* data.note.channel and data.control.channel is identical */ lbajardsilogic@0: cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f); lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: if (cmd == MIDI_CMD_COMMON_SYSEX) { lbajardsilogic@0: qlen = ev->data.ext.len; lbajardsilogic@0: if (count < qlen) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: switch (ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) { lbajardsilogic@0: case SNDRV_SEQ_EVENT_LENGTH_FIXED: lbajardsilogic@0: return -EINVAL; /* invalid event */ lbajardsilogic@0: } lbajardsilogic@0: memcpy(buf, ev->data.ext.ptr, qlen); lbajardsilogic@0: return qlen; lbajardsilogic@0: } else { lbajardsilogic@0: unsigned char xbuf[4]; lbajardsilogic@0: lbajardsilogic@0: if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) { lbajardsilogic@0: dev->lastcmd = cmd; lbajardsilogic@0: xbuf[0] = cmd; lbajardsilogic@0: if (status_event[type].decode) lbajardsilogic@0: status_event[type].decode(ev, xbuf + 1); lbajardsilogic@0: qlen = status_event[type].qlen + 1; lbajardsilogic@0: } else { lbajardsilogic@0: if (status_event[type].decode) lbajardsilogic@0: status_event[type].decode(ev, xbuf + 0); lbajardsilogic@0: qlen = status_event[type].qlen; lbajardsilogic@0: } lbajardsilogic@0: if (count < qlen) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: memcpy(buf, xbuf, qlen); lbajardsilogic@0: return qlen; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: #endif /* UNNEEDED_BY_DSSI */ lbajardsilogic@0: lbajardsilogic@0: /* decode note event */ lbajardsilogic@0: static void note_decode(const snd_seq_event_t *ev, unsigned char *buf) lbajardsilogic@0: { lbajardsilogic@0: buf[0] = ev->data.note.note & 0x7f; lbajardsilogic@0: buf[1] = ev->data.note.velocity & 0x7f; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* decode one parameter controls */ lbajardsilogic@0: static void one_param_decode(const snd_seq_event_t *ev, unsigned char *buf) lbajardsilogic@0: { lbajardsilogic@0: buf[0] = ev->data.control.value & 0x7f; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* decode pitch wheel change */ lbajardsilogic@0: static void pitchbend_decode(const snd_seq_event_t *ev, unsigned char *buf) lbajardsilogic@0: { lbajardsilogic@0: int value = ev->data.control.value + 8192; lbajardsilogic@0: buf[0] = value & 0x7f; lbajardsilogic@0: buf[1] = (value >> 7) & 0x7f; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* decode midi control change */ lbajardsilogic@0: static void two_param_decode(const snd_seq_event_t *ev, unsigned char *buf) lbajardsilogic@0: { lbajardsilogic@0: buf[0] = ev->data.control.param & 0x7f; lbajardsilogic@0: buf[1] = ev->data.control.value & 0x7f; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* decode song position */ lbajardsilogic@0: static void songpos_decode(const snd_seq_event_t *ev, unsigned char *buf) lbajardsilogic@0: { lbajardsilogic@0: buf[0] = ev->data.control.value & 0x7f; lbajardsilogic@0: buf[1] = (ev->data.control.value >> 7) & 0x7f; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef UNNEEDED_BY_DSSI lbajardsilogic@0: /* decode 14bit control */ lbajardsilogic@0: static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int count, const snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: unsigned char cmd; lbajardsilogic@0: int idx = 0; lbajardsilogic@0: lbajardsilogic@0: cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); lbajardsilogic@0: if (ev->data.control.param < 32) { lbajardsilogic@0: if (count < 4) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: if (dev->nostat && count < 6) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: if (cmd != dev->lastcmd || dev->nostat) { lbajardsilogic@0: if (count < 5) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: buf[idx++] = dev->lastcmd = cmd; lbajardsilogic@0: } lbajardsilogic@0: buf[idx++] = ev->data.control.param; lbajardsilogic@0: buf[idx++] = (ev->data.control.value >> 7) & 0x7f; lbajardsilogic@0: if (dev->nostat) lbajardsilogic@0: buf[idx++] = cmd; lbajardsilogic@0: buf[idx++] = ev->data.control.param + 32; lbajardsilogic@0: buf[idx++] = ev->data.control.value & 0x7f; lbajardsilogic@0: } else { lbajardsilogic@0: if (count < 2) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: if (cmd != dev->lastcmd || dev->nostat) { lbajardsilogic@0: if (count < 3) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: buf[idx++] = dev->lastcmd = cmd; lbajardsilogic@0: } lbajardsilogic@0: buf[idx++] = ev->data.control.param & 0x7f; lbajardsilogic@0: buf[idx++] = ev->data.control.value & 0x7f; lbajardsilogic@0: } lbajardsilogic@0: return idx; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: /* decode reg/nonreg param */ lbajardsilogic@0: static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, const snd_seq_event_t *ev) lbajardsilogic@0: { lbajardsilogic@0: unsigned char cmd; lbajardsilogic@0: char *cbytes; lbajardsilogic@0: static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB, lbajardsilogic@0: MIDI_CTL_NONREG_PARM_NUM_LSB, lbajardsilogic@0: MIDI_CTL_MSB_DATA_ENTRY, lbajardsilogic@0: MIDI_CTL_LSB_DATA_ENTRY }; lbajardsilogic@0: static char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB, lbajardsilogic@0: MIDI_CTL_REGIST_PARM_NUM_LSB, lbajardsilogic@0: MIDI_CTL_MSB_DATA_ENTRY, lbajardsilogic@0: MIDI_CTL_LSB_DATA_ENTRY }; lbajardsilogic@0: unsigned char bytes[4]; lbajardsilogic@0: int idx = 0, i; lbajardsilogic@0: lbajardsilogic@0: if (count < 8) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: if (dev->nostat && count < 12) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); lbajardsilogic@0: bytes[0] = ev->data.control.param & 0x007f; lbajardsilogic@0: bytes[1] = (ev->data.control.param & 0x3f80) >> 7; lbajardsilogic@0: bytes[2] = ev->data.control.value & 0x007f; lbajardsilogic@0: bytes[3] = (ev->data.control.value & 0x3f80) >> 7; lbajardsilogic@0: if (cmd != dev->lastcmd && !dev->nostat) { lbajardsilogic@0: if (count < 9) lbajardsilogic@0: return -ENOMEM; lbajardsilogic@0: buf[idx++] = dev->lastcmd = cmd; lbajardsilogic@0: } lbajardsilogic@0: cbytes = ev->type == SND_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn; lbajardsilogic@0: for (i = 0; i < 4; i++) { lbajardsilogic@0: if (dev->nostat) lbajardsilogic@0: buf[idx++] = dev->lastcmd = cmd; lbajardsilogic@0: buf[idx++] = cbytes[i]; lbajardsilogic@0: buf[idx++] = bytes[i]; lbajardsilogic@0: } lbajardsilogic@0: return idx; lbajardsilogic@0: } lbajardsilogic@0: #endif /* UNNEEDED_BY_DSSI */