midi_msg/
message.rs

1use alloc::vec;
2use alloc::vec::Vec;
3use core::convert::TryFrom;
4
5use super::{
6    ChannelModeMsg, ChannelVoiceMsg, ParseError, ReceiverContext, SystemCommonMsg,
7    SystemRealTimeMsg,
8};
9
10#[cfg(feature = "sysex")]
11use super::SystemExclusiveMsg;
12
13#[cfg(feature = "file")]
14use super::Meta;
15
16/// The primary interface of this library. Used to encode MIDI messages.
17#[derive(Debug, Clone, PartialEq)]
18pub enum MidiMsg {
19    /// Channel-level messages that act on a voice, such as turning notes on and off.
20    ChannelVoice {
21        channel: Channel,
22        msg: ChannelVoiceMsg,
23    },
24    /// Like `ChannelVoice`, but with the first "status" byte of the message omitted.
25    /// When these "running status" messages are sent, the receiver must treat them
26    /// as implicitly referring to the previous "status" received.
27    ///
28    /// For instance, if a `ChannelVoiceMsg::NoteOn` message is received, and then
29    /// the next message does not contain a status byte, it implicitly refers to a
30    /// `ChannelVoiceMsg::NoteOn`.
31    RunningChannelVoice {
32        channel: Channel,
33        msg: ChannelVoiceMsg,
34    },
35    /// Channel-level messages that should alter the mode of the receiver.
36    ChannelMode {
37        channel: Channel,
38        msg: ChannelModeMsg,
39    },
40    /// Like `RunningChannelVoice` but for `ChannelMode`
41    RunningChannelMode {
42        channel: Channel,
43        msg: ChannelModeMsg,
44    },
45    /// A fairly limited set of messages, generally for device synchronization.
46    SystemCommon { msg: SystemCommonMsg },
47    /// Another limited set of messages used for device synchronization.
48    SystemRealTime { msg: SystemRealTimeMsg },
49    /// The bulk of the MIDI spec lives here, in "Universal System Exclusive" messages.
50    /// Also the home of manufacturer-specific messages.
51    #[cfg(feature = "sysex")]
52    SystemExclusive { msg: SystemExclusiveMsg },
53
54    /// A Meta event, which occur within MIDI files.
55    #[cfg(feature = "file")]
56    Meta { msg: Meta },
57
58    /// A message that was invalid.
59    ///
60    /// These can only occur in MIDI files, since only in MIDI files do we know the
61    /// length of (some) messages before we parse them.
62    #[cfg(feature = "file")]
63    Invalid { bytes: Vec<u8>, error: ParseError },
64}
65
66impl MidiMsg {
67    /// Turn a `MidiMsg` into a series of bytes.
68    pub fn to_midi(&self) -> Vec<u8> {
69        let mut r: Vec<u8> = vec![];
70        self.extend_midi(&mut r);
71        r
72    }
73
74    /// Turn a series of bytes into a `MidiMsg`.
75    ///
76    /// Ok results return a MidiMsg and the number of bytes consumed from the input.
77    pub fn from_midi(m: &[u8]) -> Result<(Self, usize), ParseError> {
78        Self::from_midi_with_context(m, &mut ReceiverContext::default())
79    }
80
81    /// Turn a series of bytes into a `MidiMsg`, given a [`ReceiverContext`](crate::ReceiverContext).
82    ///
83    /// Consecutive messages that relate to each other will be collapsed into one
84    /// `MidiMsg`. E.g. a `ChannelVoiceMsg::ControlChange` where the CC is the MSB and LSB
85    /// of `ControlChange::Volume` will turn into a single `ControlChange::Volume` with both
86    /// bytes turned into one. Use [`MidiMsg::from_midi_with_context_no_extensions`] to disable this
87    /// behavior.
88    ///
89    /// The `ReceiverContext` is also used to track the current [`TimeCode`](crate::TimeCode)
90    /// as sent through [`SystemCommonMsg::TimeCodeQuarterFrame`](crate::SystemCommonMsg::TimeCodeQuarterFrame1)
91    /// messages, or [`UniversalRealTimeMsg::TimeCodeFull`](crate::UniversalRealTimeMsg::TimeCodeFull)
92    /// messages.
93    ///
94    /// Ok results return a MidiMsg and the number of bytes consumed from the input.
95    pub fn from_midi_with_context(
96        m: &[u8],
97        ctx: &mut ReceiverContext,
98    ) -> Result<(Self, usize), ParseError> {
99        Self::_from_midi_with_context(m, ctx, true)
100    }
101
102    /// Like [`MidiMsg::from_midi_with_context`] but does not turn multiple related consecutive messages
103    /// into one `MidiMsg`.
104    pub fn from_midi_with_context_no_extensions(
105        m: &[u8],
106        ctx: &mut ReceiverContext,
107    ) -> Result<(Self, usize), ParseError> {
108        Self::_from_midi_with_context(m, ctx, false)
109    }
110
111    fn _from_midi_with_context(
112        m: &[u8],
113        ctx: &mut ReceiverContext,
114        allow_extensions: bool,
115    ) -> Result<(Self, usize), ParseError> {
116        let (mut midi_msg, mut len) = match m.first() {
117            Some(b) => match b >> 4 {
118                0x8 | 0x9 | 0xA | 0xC | 0xD | 0xE => {
119                    let (msg, len) = ChannelVoiceMsg::from_midi(m, ctx)?;
120                    let channel = Channel::from_u8(b & 0x0F);
121                    let midi_msg = Self::ChannelVoice { channel, msg };
122
123                    ctx.previous_channel_message = Some(midi_msg.clone());
124                    Ok((midi_msg, len))
125                }
126                0xB => {
127                    // Could either be a Channel Mode or CC message
128                    let channel = Channel::from_u8(b & 0x0F);
129                    let (midi_msg, len) = if let Some(b2) = m.get(1) {
130                        if b2 >= &120 {
131                            let (msg, len) = ChannelModeMsg::from_midi(m)?;
132                            (Self::ChannelMode { channel, msg }, len)
133                        } else {
134                            let (mut msg, len) = ChannelVoiceMsg::from_midi(m, ctx)?;
135
136                            if allow_extensions {
137                                // If we can interpret this message as an extension to the previous
138                                // one, do it.
139                                if let Some(Self::ChannelVoice {
140                                    channel: prev_channel,
141                                    msg: prev_msg,
142                                }) = ctx.previous_channel_message
143                                {
144                                    if channel == prev_channel
145                                        && prev_msg.is_extensible()
146                                        && msg.is_extension()
147                                    {
148                                        if let Ok(updated_msg) = prev_msg.maybe_extend(&msg) {
149                                            msg = updated_msg;
150                                        }
151                                    }
152                                }
153                            }
154                            (Self::ChannelVoice { channel, msg }, len)
155                        }
156                    } else {
157                        return Err(ParseError::UnexpectedEnd);
158                    };
159
160                    ctx.previous_channel_message = Some(midi_msg.clone());
161                    Ok((midi_msg, len))
162                }
163                0xF => {
164                    if b & 0b00001111 == 0 {
165                        #[cfg(feature = "sysex")]
166                        {
167                            let (msg, len) = SystemExclusiveMsg::from_midi(m, ctx)?;
168                            return Ok((Self::SystemExclusive { msg }, len));
169                        }
170                        #[cfg(not(feature = "sysex"))]
171                        return Err(ParseError::SystemExclusiveDisabled);
172                    } else if b & 0b00001111 == 0xF && ctx.parsing_smf {
173                        #[cfg(feature = "file")]
174                        {
175                            let (msg, len) = Meta::from_midi(m)?;
176                            return Ok((Self::Meta { msg }, len));
177                        }
178                        #[cfg(not(feature = "file"))]
179                        return Err(ParseError::FileDisabled);
180                    } else if b & 0b00001000 == 0 {
181                        let (msg, len) = SystemCommonMsg::from_midi(m, ctx)?;
182                        Ok((Self::SystemCommon { msg }, len))
183                    } else {
184                        let (msg, len) = SystemRealTimeMsg::from_midi(m)?;
185                        Ok((Self::SystemRealTime { msg }, len))
186                    }
187                }
188                _ => {
189                    if let Some(p) = &ctx.previous_channel_message {
190                        match p {
191                            Self::ChannelVoice {
192                                channel,
193                                msg: prev_msg,
194                            } => {
195                                if m.len() < 2 {
196                                    return Err(ParseError::UnexpectedEnd);
197                                }
198                                match prev_msg {
199                                    // See A-2 of the MIDI spec
200                                    ChannelVoiceMsg::ControlChange { .. } => {
201                                        if m[0] >= 120 {
202                                            let (msg, len) = ChannelModeMsg::from_midi_running(m)?;
203                                            return Ok((
204                                                Self::ChannelMode {
205                                                    channel: *channel,
206                                                    msg,
207                                                },
208                                                len,
209                                            ));
210                                        }
211                                    }
212                                    _ => (),
213                                };
214                                let (mut msg, len) =
215                                    ChannelVoiceMsg::from_midi_running(m, prev_msg, ctx)?;
216
217                                if allow_extensions {
218                                    // If we can interpret this message as an extension to the previous
219                                    // one, do it.
220                                    if prev_msg.is_extensible() && msg.is_extension() {
221                                        if let Ok(updated_msg) = prev_msg.maybe_extend(&msg) {
222                                            msg = updated_msg;
223                                        }
224                                    }
225                                }
226                                Ok((
227                                    Self::ChannelVoice {
228                                        channel: *channel,
229                                        msg,
230                                    },
231                                    len,
232                                ))
233                            }
234
235                            Self::ChannelMode { channel, .. } => {
236                                if m.len() < 2 {
237                                    return Err(ParseError::UnexpectedEnd);
238                                }
239                                // See A-2 of the MIDI spec
240                                if m[0] >= 120 {
241                                    let (msg, len) = ChannelModeMsg::from_midi_running(m)?;
242                                    Ok((
243                                        Self::ChannelMode {
244                                            channel: *channel,
245                                            msg,
246                                        },
247                                        len,
248                                    ))
249                                } else {
250                                    let control = crate::ControlChange::from_midi(m, ctx)?;
251                                    Ok((
252                                        Self::ChannelVoice {
253                                            channel: *channel,
254                                            msg: ChannelVoiceMsg::ControlChange { control },
255                                        },
256                                        2,
257                                    ))
258                                }
259                            }
260                            _ => Err(ParseError::Invalid(
261                                "ReceiverContext::previous_channel_message may only be a ChannelMode or ChannelVoice message.",
262                            )),
263                        }
264                    } else {
265                        Err(ParseError::ContextlessRunningStatus)
266                    }
267                }
268            },
269            None => Err(ParseError::UnexpectedEnd),
270        }?;
271
272        if allow_extensions {
273            // TODO: this loop could be written as a `while let` loop
274            // for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
275
276            // If this is an extensible message, try to extend it
277            loop {
278                if let Self::ChannelVoice { channel, msg } = midi_msg {
279                    if msg.is_extensible() {
280                        // Shadow the context;
281                        let mut ctx = ctx.clone();
282                        // Try to extend an extensible message
283                        match Self::_from_midi_with_context(&m[len..], &mut ctx, false) {
284                            Ok((
285                                Self::ChannelVoice {
286                                    channel: next_channel,
287                                    msg: next_msg,
288                                },
289                                next_len,
290                            )) => {
291                                if channel == next_channel && next_msg.is_extension() {
292                                    match msg.maybe_extend(&next_msg) {
293                                        Ok(updated_msg) => {
294                                            midi_msg = Self::ChannelVoice {
295                                                channel,
296                                                msg: updated_msg,
297                                            };
298                                            len += next_len;
299                                        }
300                                        _ => break,
301                                    }
302                                } else {
303                                    break;
304                                }
305                            }
306                            _ => break,
307                        }
308                    } else {
309                        break;
310                    }
311                } else {
312                    break;
313                }
314            }
315        }
316
317        Ok((midi_msg, len))
318    }
319
320    /// Turn a set of `MidiMsg`s into a series of bytes, with fewer allocations than
321    /// repeatedly concatenating the results of `to_midi`.
322    pub fn messages_to_midi(msgs: &[Self]) -> Vec<u8> {
323        let mut r: Vec<u8> = vec![];
324        for m in msgs.iter() {
325            m.extend_midi(&mut r);
326        }
327        r
328    }
329
330    /// Given a `Vec<u8>`, append this `MidiMsg` to it.
331    pub fn extend_midi(&self, v: &mut Vec<u8>) {
332        match self {
333            MidiMsg::ChannelVoice { channel, msg } => {
334                let p = v.len();
335                msg.extend_midi(v);
336                v[p] += *channel as u8;
337                match msg {
338                    ChannelVoiceMsg::HighResNoteOff { .. }
339                    | ChannelVoiceMsg::HighResNoteOn { .. } => {
340                        v[p + 3] += *channel as u8;
341                    }
342                    _ => (),
343                }
344            }
345            MidiMsg::RunningChannelVoice { msg, .. } => msg.extend_midi_running(v),
346            MidiMsg::ChannelMode { channel, msg } => {
347                let p = v.len();
348                msg.extend_midi(v);
349                v[p] += *channel as u8;
350            }
351            MidiMsg::RunningChannelMode { msg, .. } => msg.extend_midi_running(v),
352            MidiMsg::SystemCommon { msg } => msg.extend_midi(v),
353            MidiMsg::SystemRealTime { msg } => msg.extend_midi(v),
354            #[cfg(feature = "sysex")]
355            MidiMsg::SystemExclusive { msg } => msg.extend_midi(v, true),
356            #[cfg(feature = "file")]
357            MidiMsg::Meta { msg } => msg.extend_midi(v),
358            #[cfg(feature = "file")]
359            MidiMsg::Invalid { .. } => {
360                // Do nothing
361            }
362        }
363    }
364
365    /// Returns true if this message is a channel voice message.
366    pub fn is_channel_voice(&self) -> bool {
367        matches!(
368            self,
369            Self::ChannelVoice { .. } | Self::RunningChannelVoice { .. }
370        )
371    }
372
373    /// Returns true if this message is a note (on or off) message.
374    pub fn is_note(&self) -> bool {
375        matches!(
376            self,
377            Self::ChannelVoice {
378                msg: ChannelVoiceMsg::NoteOn { .. }
379                    | ChannelVoiceMsg::NoteOff { .. }
380                    | ChannelVoiceMsg::HighResNoteOn { .. }
381                    | ChannelVoiceMsg::HighResNoteOff { .. },
382                ..
383            } | Self::RunningChannelVoice {
384                msg: ChannelVoiceMsg::NoteOn { .. }
385                    | ChannelVoiceMsg::NoteOff { .. }
386                    | ChannelVoiceMsg::HighResNoteOn { .. }
387                    | ChannelVoiceMsg::HighResNoteOff { .. },
388                ..
389            }
390        )
391    }
392
393    /// Returns true if this message is a control change message.
394    pub fn is_cc(&self) -> bool {
395        matches!(
396            self,
397            Self::ChannelVoice {
398                msg: ChannelVoiceMsg::ControlChange { .. },
399                ..
400            } | Self::RunningChannelVoice {
401                msg: ChannelVoiceMsg::ControlChange { .. },
402                ..
403            }
404        )
405    }
406
407    /// Returns true if this message is a channel mode message.
408    pub fn is_channel_mode(&self) -> bool {
409        matches!(
410            self,
411            Self::ChannelMode { .. } | Self::RunningChannelMode { .. }
412        )
413    }
414
415    /// Returns true if this message is a system common message.
416    pub fn is_system_common(&self) -> bool {
417        matches!(self, Self::SystemCommon { .. })
418    }
419
420    /// Returns true if this message is a system real-time message.
421    pub fn is_system_real_time(&self) -> bool {
422        matches!(self, Self::SystemRealTime { .. })
423    }
424
425    #[cfg(feature = "sysex")]
426    /// Returns true if this message is a system exclusive message.
427    pub fn is_system_exclusive(&self) -> bool {
428        matches!(self, Self::SystemExclusive { .. })
429    }
430
431    #[cfg(feature = "file")]
432    /// Returns true if this message is a meta message.
433    pub fn is_meta(&self) -> bool {
434        matches!(self, Self::Meta { .. })
435    }
436
437    #[cfg(feature = "file")]
438    /// Returns true if this message is an invalid message.
439    pub fn is_invalid(&self) -> bool {
440        matches!(self, Self::Invalid { .. })
441    }
442}
443
444impl From<&MidiMsg> for Vec<u8> {
445    fn from(m: &MidiMsg) -> Vec<u8> {
446        m.to_midi()
447    }
448}
449
450/// Find the index of the next message in a MIDI byte sequence. This is useful for
451/// being able to skip over messages, which may be necessary when a message is
452/// unable to be deserialized.
453///
454/// This *will* skip any running status messages, since we're not parsing the byte stream,
455/// we're just looking for a "status byte" -- a byte with the upper bit set.
456pub fn next_message(m: &[u8]) -> Option<usize> {
457    if m.is_empty() {
458        return None;
459    }
460    // If the first byte has the upper bit set, it's the start of the message we're skipping over.
461    // If not, we're somewhere in the middle of a message, and we need to find the next one.
462    let start = if upper_bit_set(m[0]) { 1 } else { 0 };
463
464    (start..m.len()).find(|&i| upper_bit_set(m[i]))
465}
466
467fn upper_bit_set(x: u8) -> bool {
468    x & 0b10000000 != 0
469}
470
471#[cfg(feature = "std")]
472use strum::{EnumIter, EnumString};
473
474/// The MIDI channel, 1-16. Used by [`MidiMsg`] and elsewhere.
475#[cfg_attr(feature = "std", derive(EnumIter, EnumString))]
476#[derive(Debug, Clone, Copy, PartialEq, Eq)]
477#[repr(u8)]
478pub enum Channel {
479    Ch1,
480    Ch2,
481    Ch3,
482    Ch4,
483    Ch5,
484    Ch6,
485    Ch7,
486    Ch8,
487    Ch9,
488    Ch10,
489    Ch11,
490    Ch12,
491    Ch13,
492    Ch14,
493    Ch15,
494    Ch16,
495}
496
497impl core::fmt::Display for Channel {
498    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
499        write!(f, "Ch{}", *self as u8 + 1)
500    }
501}
502
503impl Channel {
504    pub fn from_u8(x: u8) -> Self {
505        match x {
506            0 => Self::Ch1,
507            1 => Self::Ch2,
508            2 => Self::Ch3,
509            3 => Self::Ch4,
510            4 => Self::Ch5,
511            5 => Self::Ch6,
512            6 => Self::Ch7,
513            7 => Self::Ch8,
514            8 => Self::Ch9,
515            9 => Self::Ch10,
516            10 => Self::Ch11,
517            11 => Self::Ch12,
518            12 => Self::Ch13,
519            13 => Self::Ch14,
520            14 => Self::Ch15,
521            _ => Self::Ch16,
522        }
523    }
524}
525
526impl TryFrom<u8> for Channel {
527    type Error = &'static str;
528
529    fn try_from(value: u8) -> Result<Self, Self::Error> {
530        if value > 15 {
531            return Err("Invalid channel value");
532        }
533        Ok(Self::from_u8(value))
534    }
535}
536
537#[cfg(test)]
538mod tests {
539    use super::*;
540    use crate::Channel::*;
541
542    #[test]
543    fn test_ch() {
544        assert_eq!(Ch1, Channel::from_u8(0));
545        assert_eq!(Ch2, Channel::from_u8(1));
546        assert_eq!(Ch16, Channel::from_u8(255));
547    }
548
549    #[test]
550    fn test_ch_try_from() {
551        assert_eq!(Ch1, Channel::try_from(0).unwrap());
552        assert_eq!(Ch2, Channel::try_from(1).unwrap());
553        assert_eq!(Ch16, Channel::try_from(15).unwrap());
554        assert!(Channel::try_from(16).is_err());
555    }
556
557    #[test]
558    fn test_running_status() {
559        let noteon = MidiMsg::ChannelVoice {
560            channel: Channel::Ch1,
561            msg: ChannelVoiceMsg::NoteOn {
562                note: 0x42,
563                velocity: 0x60,
564            },
565        };
566        let running_noteon = MidiMsg::RunningChannelVoice {
567            channel: Channel::Ch1,
568            msg: ChannelVoiceMsg::NoteOn {
569                note: 0x42,
570                velocity: 0x60,
571            },
572        };
573        let reset = MidiMsg::ChannelMode {
574            channel: Channel::Ch1,
575            msg: ChannelModeMsg::ResetAllControllers,
576        };
577        let running_reset = MidiMsg::RunningChannelMode {
578            channel: Channel::Ch1,
579            msg: ChannelModeMsg::ResetAllControllers,
580        };
581        let cc = MidiMsg::ChannelVoice {
582            channel: Channel::Ch1,
583            msg: ChannelVoiceMsg::ControlChange {
584                control: crate::ControlChange::Volume(0x7F),
585            },
586        };
587        let running_cc = MidiMsg::RunningChannelVoice {
588            channel: Channel::Ch1,
589            msg: ChannelVoiceMsg::ControlChange {
590                control: crate::ControlChange::Volume(0x7F),
591            },
592        };
593
594        // Push 10 messages
595        let mut midi = vec![];
596        noteon.extend_midi(&mut midi);
597        running_noteon.extend_midi(&mut midi);
598        // Ensure that channel mode messages can follow one another
599        reset.extend_midi(&mut midi);
600        running_reset.extend_midi(&mut midi);
601        // Ensure that control changes can follow one another
602        cc.extend_midi(&mut midi);
603        running_cc.extend_midi(&mut midi);
604        //   Ensure that control changes and channel mode messages can follow one another
605        reset.extend_midi(&mut midi);
606        running_cc.extend_midi(&mut midi);
607        cc.extend_midi(&mut midi);
608        running_reset.extend_midi(&mut midi);
609
610        // Read back ten messages
611        let mut offset = 0;
612        let mut ctx = ReceiverContext::new().complex_cc();
613        let (msg1, len) = MidiMsg::from_midi_with_context(&midi, &mut ctx).expect("Not an error");
614        offset += len;
615        let (msg2, len) =
616            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
617        offset += len;
618        let (msg3, len) =
619            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
620        offset += len;
621        let (msg4, len) =
622            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
623        offset += len;
624        let (msg5, len) =
625            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
626        offset += len;
627        let (msg6, len) =
628            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
629        offset += len;
630        let (msg7, len) =
631            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
632        offset += len;
633        let (msg8, len) =
634            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
635        offset += len;
636        let (msg9, len) =
637            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
638        offset += len;
639        let (msg10, _) =
640            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
641
642        // The expected messages are not running status messages, since we never deserialize into them
643        assert_eq!(msg1, noteon);
644        assert_eq!(msg2, noteon);
645        assert_eq!(msg3, reset);
646        assert_eq!(msg4, reset);
647        assert_eq!(msg5, cc);
648        assert_eq!(msg6, cc);
649        assert_eq!(msg7, reset);
650        assert_eq!(msg8, cc);
651        assert_eq!(msg9, cc);
652        assert_eq!(msg10, reset);
653    }
654
655    #[test]
656    fn test_simple_cc_running_status() {
657        let cc = MidiMsg::ChannelVoice {
658            channel: Channel::Ch1,
659            msg: ChannelVoiceMsg::ControlChange {
660                control: crate::ControlChange::Volume(0x7F),
661            },
662        };
663        let running_cc = MidiMsg::RunningChannelVoice {
664            channel: Channel::Ch1,
665            msg: ChannelVoiceMsg::ControlChange {
666                control: crate::ControlChange::Volume(0x7F),
667            },
668        };
669        let simple_cc_msb = MidiMsg::ChannelVoice {
670            channel: Channel::Ch1,
671            msg: ChannelVoiceMsg::ControlChange {
672                control: crate::ControlChange::CC {
673                    control: 7,
674                    value: 0,
675                },
676            },
677        };
678        let simple_cc_lsb = MidiMsg::ChannelVoice {
679            channel: Channel::Ch1,
680            msg: ChannelVoiceMsg::ControlChange {
681                control: crate::ControlChange::CC {
682                    control: 7 + 32,
683                    value: 0x7F,
684                },
685            },
686        };
687
688        // Push two messages
689        let mut midi = vec![];
690        cc.extend_midi(&mut midi);
691        running_cc.extend_midi(&mut midi);
692
693        // Read back 4 messages (two are running status messages)
694        let mut offset = 0;
695        let mut ctx = ReceiverContext::new();
696        let (msg1, len) = MidiMsg::from_midi_with_context(&midi, &mut ctx).expect("Not an error");
697        offset += len;
698        let (msg2, len) =
699            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
700        offset += len;
701        let (msg3, len) =
702            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
703        offset += len;
704        let (msg4, _) =
705            MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
706
707        // The expected messages are not running status messages, since we never deserialize into them
708        assert_eq!(msg1, simple_cc_msb);
709        assert_eq!(msg2, simple_cc_lsb);
710        assert_eq!(msg3, simple_cc_msb);
711        assert_eq!(msg4, simple_cc_lsb);
712    }
713
714    #[test]
715    fn test_next_message() {
716        let mut midi = vec![];
717        MidiMsg::ChannelVoice {
718            channel: Channel::Ch1,
719            msg: ChannelVoiceMsg::NoteOn {
720                note: 0x42,
721                velocity: 0x60,
722            },
723        }
724        .extend_midi(&mut midi);
725        let first_message_len = midi.len();
726        MidiMsg::ChannelVoice {
727            channel: Channel::Ch1,
728            msg: ChannelVoiceMsg::NoteOn {
729                note: 0x42,
730                velocity: 0x60,
731            },
732        }
733        .extend_midi(&mut midi);
734
735        assert_eq!(next_message(&midi), Some(first_message_len));
736        // Offset by a byte, so we're in the middle of a message
737        assert_eq!(next_message(&midi[1..]), Some(first_message_len - 1));
738        assert_eq!(next_message(&midi[first_message_len..]), None);
739    }
740}