]> www.infradead.org Git - nvme.git/commitdiff
ALSA: seq: ump: Transmit RPN/NRPN message at each MSB/LSB data reception
authorTakashi Iwai <tiwai@suse.de>
Wed, 31 Jul 2024 13:05:25 +0000 (15:05 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 31 Jul 2024 13:08:50 +0000 (15:08 +0200)
Just like the core UMP conversion helper, we need to deal with the
partially-filled RPN/NRPN data in the sequencer UMP converter as
well.

Link: https://patch.msgid.link/20240731130528.12600-5-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/seq/seq_ump_convert.c

index b1bc6d122d92dc155a64f6d1cd8742931d8934e9..7ca62667f28d36ee1ceb2ebe26f10540f9206a85 100644 (file)
@@ -790,27 +790,39 @@ static int paf_ev_to_ump_midi2(const struct snd_seq_event *event,
 }
 
 /* set up the MIDI2 RPN/NRPN packet data from the parsed info */
-static void fill_rpn(struct ump_cvt_to_ump_bank *cc,
-                    union snd_ump_midi2_msg *data,
-                    unsigned char channel)
+static int fill_rpn(struct ump_cvt_to_ump_bank *cc,
+                   union snd_ump_midi2_msg *data,
+                   unsigned char channel,
+                   bool flush)
 {
+       if (!(cc->cc_data_lsb_set || cc->cc_data_msb_set))
+               return 0; // skip
+       /* when not flushing, wait for complete data set */
+       if (!flush && (!cc->cc_data_lsb_set || !cc->cc_data_msb_set))
+               return 0; // skip
+
        if (cc->rpn_set) {
                data->rpn.status = UMP_MSG_STATUS_RPN;
                data->rpn.bank = cc->cc_rpn_msb;
                data->rpn.index = cc->cc_rpn_lsb;
-               cc->rpn_set = 0;
-               cc->cc_rpn_msb = cc->cc_rpn_lsb = 0;
-       } else {
+       } else if (cc->nrpn_set) {
                data->rpn.status = UMP_MSG_STATUS_NRPN;
                data->rpn.bank = cc->cc_nrpn_msb;
                data->rpn.index = cc->cc_nrpn_lsb;
-               cc->nrpn_set = 0;
-               cc->cc_nrpn_msb = cc->cc_nrpn_lsb = 0;
+       } else {
+               return 0; // skip
        }
+
        data->rpn.data = upscale_14_to_32bit((cc->cc_data_msb << 7) |
                                             cc->cc_data_lsb);
        data->rpn.channel = channel;
+
+       cc->rpn_set = 0;
+       cc->nrpn_set = 0;
+       cc->cc_rpn_msb = cc->cc_rpn_lsb = 0;
        cc->cc_data_msb = cc->cc_data_lsb = 0;
+       cc->cc_data_msb_set = cc->cc_data_lsb_set = 0;
+       return 1;
 }
 
 /* convert CC event to MIDI 2.0 UMP */
@@ -823,28 +835,34 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
        unsigned char index = event->data.control.param & 0x7f;
        unsigned char val = event->data.control.value & 0x7f;
        struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel];
+       int ret;
 
        /* process special CC's (bank/rpn/nrpn) */
        switch (index) {
        case UMP_CC_RPN_MSB:
+               ret = fill_rpn(cc, data, channel, true);
                cc->rpn_set = 1;
                cc->cc_rpn_msb = val;
-               return 0; // skip
+               return ret;
        case UMP_CC_RPN_LSB:
+               ret = fill_rpn(cc, data, channel, true);
                cc->rpn_set = 1;
                cc->cc_rpn_lsb = val;
-               return 0; // skip
+               return ret;
        case UMP_CC_NRPN_MSB:
+               ret = fill_rpn(cc, data, channel, true);
                cc->nrpn_set = 1;
                cc->cc_nrpn_msb = val;
-               return 0; // skip
+               return ret;
        case UMP_CC_NRPN_LSB:
+               ret = fill_rpn(cc, data, channel, true);
                cc->nrpn_set = 1;
                cc->cc_nrpn_lsb = val;
-               return 0; // skip
+               return ret;
        case UMP_CC_DATA:
+               cc->cc_data_msb_set = 1;
                cc->cc_data_msb = val;
-               return 0; // skip
+               return fill_rpn(cc, data, channel, false);
        case UMP_CC_BANK_SELECT:
                cc->bank_set = 1;
                cc->cc_bank_msb = val;
@@ -854,11 +872,9 @@ static int cc_ev_to_ump_midi2(const struct snd_seq_event *event,
                cc->cc_bank_lsb = val;
                return 0; // skip
        case UMP_CC_DATA_LSB:
+               cc->cc_data_lsb_set = 1;
                cc->cc_data_lsb = val;
-               if (!(cc->rpn_set || cc->nrpn_set))
-                       return 0; // skip
-               fill_rpn(cc, data, channel);
-               return 1;
+               return fill_rpn(cc, data, channel, false);
        }
 
        data->cc.status = status;
@@ -926,6 +942,7 @@ static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event,
        unsigned char index = event->data.control.param & 0x7f;
        struct ump_cvt_to_ump_bank *cc = &dest_port->midi2_bank[channel];
        unsigned char msb, lsb;
+       int ret;
 
        msb = (event->data.control.value >> 7) & 0x7f;
        lsb = event->data.control.value & 0x7f;
@@ -939,28 +956,25 @@ static int ctrl14_ev_to_ump_midi2(const struct snd_seq_event *event,
                cc->cc_bank_lsb = lsb;
                return 0; // skip
        case UMP_CC_RPN_MSB:
-               cc->cc_rpn_msb = msb;
-               fallthrough;
        case UMP_CC_RPN_LSB:
-               cc->rpn_set = 1;
+               ret = fill_rpn(cc, data, channel, true);
+               cc->cc_rpn_msb = msb;
                cc->cc_rpn_lsb = lsb;
-               return 0; // skip
+               cc->rpn_set = 1;
+               return ret;
        case UMP_CC_NRPN_MSB:
-               cc->cc_nrpn_msb = msb;
-               fallthrough;
        case UMP_CC_NRPN_LSB:
+               ret = fill_rpn(cc, data, channel, true);
+               cc->cc_nrpn_msb = msb;
                cc->nrpn_set = 1;
                cc->cc_nrpn_lsb = lsb;
-               return 0; // skip
+               return ret;
        case UMP_CC_DATA:
-               cc->cc_data_msb = msb;
-               fallthrough;
        case UMP_CC_DATA_LSB:
+               cc->cc_data_msb_set = cc->cc_data_lsb_set = 1;
+               cc->cc_data_msb = msb;
                cc->cc_data_lsb = lsb;
-               if (!(cc->rpn_set || cc->nrpn_set))
-                       return 0; // skip
-               fill_rpn(cc, data, channel);
-               return 1;
+               return fill_rpn(cc, data, channel, false);
        }
 
        data->cc.status = UMP_MSG_STATUS_CC;