Update of /cvsroot/alsa/alsa-lib/src/seq
In directory sc8-pr-cvs1:/tmp/cvs-serv1707

Modified Files:
        seq_midi_event.c 
Log Message:
Added proper handling of nonregistered and registered MIDI parameters

Index: seq_midi_event.c
===================================================================
RCS file: /cvsroot/alsa/alsa-lib/src/seq/seq_midi_event.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- seq_midi_event.c    5 Dec 2002 18:01:49 -0000       1.17
+++ seq_midi_event.c    16 Jun 2003 11:00:30 -0000      1.18
@@ -35,11 +35,12 @@
 
 /* midi status */
 struct snd_midi_event {
-       size_t qlen;    /* queue length */
-       size_t read;    /* chars read */
-       int type;       /* current event type */
+       size_t qlen;            /* queue length */
+       size_t read;            /* chars read */
+       int type;               /* current event type */
        unsigned char lastcmd;
        unsigned char nostat;
+       unsigned char xreg_hit;
        size_t bufsize;
        unsigned char *buf;     /* input buffer */
 };
@@ -49,9 +50,11 @@
 /* from 0 to 7 are normal commands (note off, on, etc.) */
 #define ST_NOTEOFF     0
 #define ST_NOTEON      1
+#define ST_CONTROLLER  3
 #define ST_SPECIAL     8
 #define ST_SYSEX       ST_SPECIAL
 /* from 8 to 15 are events for 0xf0-0xf7 */
+#define ST_XREG_PARM   16
 
 
 /* status event types */
@@ -69,6 +72,8 @@
 static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
 static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
 static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
+static unsigned char get_xreg_hit_bit(unsigned char c);
+static void xreg_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
 static void note_decode(snd_seq_event_t *ev, unsigned char *buf);
 static void one_param_decode(snd_seq_event_t *ev, unsigned char *buf);
 static void pitchbend_decode(snd_seq_event_t *ev, unsigned char *buf);
@@ -113,14 +118,15 @@
 };
 
 static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, 
snd_seq_event_t *ev);
+static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, 
snd_seq_event_t *ev);
 
 static struct extra_event_list_t {
        int event;
        int (*decode)(snd_midi_event_t *dev, unsigned char *buf, int len, 
snd_seq_event_t *ev);
 } extra_event[] = {
        {SND_SEQ_EVENT_CONTROL14, extra_decode_ctrl14},
-       /*{SND_SEQ_EVENT_NONREGPARAM, extra_decode_nrpn},*/
-       /*{SND_SEQ_EVENT_REGPARAM, extra_decode_rpn},*/
+       {SND_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn},
+       {SND_SEQ_EVENT_REGPARAM, extra_decode_xrpn},
 };
 
 #ifndef DOC_HIDDEN
@@ -299,7 +305,7 @@
  */
 int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev)
 {
-       int rc = 0;
+       int tmp = 0;
 
        c &= 0xff;
 
@@ -313,11 +319,20 @@
 
        if (dev->qlen > 0) {
                /* rest of command */
+               if (c & 0x80) {         /* error? state inside data? */
+                       if (dev->type == ST_XREG_PARM) {
+                               if (c != dev->buf[0])
+                                       goto __new_command;
+                               return 0;
+                       }
+                       goto __new_command;
+               }
                dev->buf[dev->read++] = c;
                if (dev->type != ST_SYSEX)
                        dev->qlen--;
        } else {
                /* new command */
+             __new_command:
                dev->read = 1;
                if (c & 0x80) {
                        dev->buf[0] = c;
@@ -333,13 +348,39 @@
                }
        }
        if (dev->qlen == 0) {
+               /* handle xrpn special case here */
+               if (dev->type == ST_CONTROLLER &&
+                   dev->buf[1] >= MIDI_CTL_NONREG_PARM_NUM_LSB &&
+                   dev->buf[1] <= MIDI_CTL_REGIST_PARM_NUM_MSB) {
+                       dev->type = ST_XREG_PARM;
+                       dev->xreg_hit = get_xreg_hit_bit(dev->buf[1]);
+                       dev->qlen = 2;          /* we need more bytes */
+                       return 0;
+               }
+               if (dev->type == ST_XREG_PARM) {
+                       tmp = get_xreg_hit_bit(dev->buf[1]);
+                       if (tmp == 0 || (tmp & dev->xreg_hit)) {
+                               reset_encode(dev);
+                               dev->type = ST_CONTROLLER;
+                               dev->read = 1;
+                               return 0;
+                       }
+                       dev->xreg_hit |= tmp;
+                       if (dev->xreg_hit == 0x0f) {    /* finished */
+                               xreg_event(dev, ev);
+                               return 1;
+                       }
+                       dev->qlen = 2;          /* we need more bytes */
+                       return 0;
+               }
+               /* handle standard midi events */
                ev->type = status_event[dev->type].event;
                ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
                ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
                if (status_event[dev->type].encode) /* set data values */
                        status_event[dev->type].encode(dev, ev);
-               rc = 1;
-       } else  if (dev->type == ST_SYSEX) {
+               return 1;
+       } else if (dev->type == ST_SYSEX) {
                if (c == MIDI_CMD_COMMON_SYSEX_END ||
                    dev->read >= dev->bufsize) {
                        ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
@@ -351,11 +392,11 @@
                                dev->read = 0; /* continue to parse */
                        else
                                reset_encode(dev); /* all parsed */
-                       rc = 1;
+                       return 1;
                }
        }
 
-       return rc;
+       return 0;
 }
 
 /* encode note event */
@@ -400,6 +441,44 @@
        ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1];
 }
 
+static unsigned char get_xreg_hit_bit(unsigned char c)
+{
+       switch (c) {
+       case MIDI_CTL_NONREG_PARM_NUM_MSB:
+       case MIDI_CTL_REGIST_PARM_NUM_MSB:
+               return 1;
+       case MIDI_CTL_NONREG_PARM_NUM_LSB:
+       case MIDI_CTL_REGIST_PARM_NUM_LSB:
+               return 2;
+       case MIDI_CTL_MSB_DATA_ENTRY:
+               return 4;
+       case MIDI_CTL_LSB_DATA_ENTRY:
+               return 8;
+       default:
+               return 0;
+       }
+}
+
+/* encode xreg event */
+static void xreg_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+{
+       int i;
+
+       ev->type = (dev->buf[1] == MIDI_CTL_NONREG_PARM_NUM_MSB ||
+                   dev->buf[1] == MIDI_CTL_NONREG_PARM_NUM_LSB) ?
+                       SND_SEQ_EVENT_NONREGPARAM : SND_SEQ_EVENT_REGPARAM;            
 
+       ev->data.control.param = 0;
+       ev->data.control.value = 0;
+       for (i = 1; i < 9; i += 2) {
+               switch (get_xreg_hit_bit(dev->buf[i])) {
+               case 1: ev->data.control.param |= dev->buf[i+1] << 7;   break;
+               case 2: ev->data.control.param |= dev->buf[i+1];        break;
+               case 4: ev->data.control.value |= dev->buf[i+1] << 7;   break;
+               case 8: ev->data.control.value |= dev->buf[i+1];        break;
+               }
+       }
+}
+
 /**
  * \brief Decode sequencer event to MIDI byte stream
  * \param dev MIDI event parser
@@ -510,12 +589,12 @@
        unsigned char cmd;
        int idx = 0;
 
+       cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
        if (ev->data.control.param < 32) {
                if (count < 4)
                        return -ENOMEM;
                if (dev->nostat && count < 6)
                        return -ENOMEM;
-               cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
                if (cmd != dev->lastcmd || dev->nostat) {
                        if (count < 5)
                                return -ENOMEM;
@@ -527,11 +606,9 @@
                        buf[idx++] = cmd;
                buf[idx++] = ev->data.control.param + 32;
                buf[idx++] = ev->data.control.value & 0x7f;
-               return idx;
        } else {
                if (count < 2)
                        return -ENOMEM;
-               cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
                if (cmd != dev->lastcmd || dev->nostat) {
                        if (count < 3)
                                return -ENOMEM;
@@ -539,6 +616,46 @@
                }
                buf[idx++] = ev->data.control.param & 0x7f;
                buf[idx++] = ev->data.control.value & 0x7f;
-               return idx;
        }
+       return idx;
+}
+
+/* decode reg/nonreg param */
+static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, 
snd_seq_event_t *ev)
+{
+       unsigned char cmd;
+       char *cbytes;
+       static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
+                                      MIDI_CTL_NONREG_PARM_NUM_LSB,
+                                      MIDI_CTL_MSB_DATA_ENTRY,
+                                      MIDI_CTL_LSB_DATA_ENTRY };
+       static char cbytes_rpn[4] =  { MIDI_CTL_REGIST_PARM_NUM_MSB,
+                                      MIDI_CTL_REGIST_PARM_NUM_LSB,
+                                      MIDI_CTL_MSB_DATA_ENTRY,
+                                      MIDI_CTL_LSB_DATA_ENTRY };
+       unsigned char bytes[4];
+       int idx = 0, i;
+
+       if (count < 8)
+               return -ENOMEM;
+       if (dev->nostat && count < 12)
+               return -ENOMEM;
+       cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f);
+       bytes[0] = ev->data.control.param & 0x007f;
+       bytes[1] = (ev->data.control.param & 0x3f80) >> 7;
+       bytes[2] = ev->data.control.value & 0x007f;
+       bytes[3] = (ev->data.control.value & 0x3f80) >> 7;
+       if (cmd != dev->lastcmd && !dev->nostat) {
+               if (count < 9)
+                       return -ENOMEM;
+               buf[idx++] = dev->lastcmd = cmd;
+       }
+       cbytes = ev->type == SND_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn;
+       for (i = 0; i < 4; i++) {
+               if (dev->nostat)
+                       buf[idx++] = dev->lastcmd = cmd;
+               buf[idx++] = cbytes[i];
+               buf[idx++] = bytes[i];
+       }
+       return idx;
 }



-------------------------------------------------------
This SF.NET email is sponsored by: eBay
Great deals on office technology -- on eBay now! Click here:
http://adfarm.mediaplex.com/ad/ck/711-11697-6916-5
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to