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#[derive(Debug, Clone, PartialEq)]
18pub enum MidiMsg {
19 ChannelVoice {
21 channel: Channel,
22 msg: ChannelVoiceMsg,
23 },
24 RunningChannelVoice {
32 channel: Channel,
33 msg: ChannelVoiceMsg,
34 },
35 ChannelMode {
37 channel: Channel,
38 msg: ChannelModeMsg,
39 },
40 RunningChannelMode {
42 channel: Channel,
43 msg: ChannelModeMsg,
44 },
45 SystemCommon { msg: SystemCommonMsg },
47 SystemRealTime { msg: SystemRealTimeMsg },
49 #[cfg(feature = "sysex")]
52 SystemExclusive { msg: SystemExclusiveMsg },
53
54 #[cfg(feature = "file")]
56 Meta { msg: Meta },
57
58 #[cfg(feature = "file")]
63 Invalid { bytes: Vec<u8>, error: ParseError },
64}
65
66impl MidiMsg {
67 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 pub fn from_midi(m: &[u8]) -> Result<(Self, usize), ParseError> {
78 Self::from_midi_with_context(m, &mut ReceiverContext::default())
79 }
80
81 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 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 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 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 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 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 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 loop {
278 if let Self::ChannelVoice { channel, msg } = midi_msg {
279 if msg.is_extensible() {
280 let mut ctx = ctx.clone();
282 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 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 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 }
362 }
363 }
364
365 pub fn is_channel_voice(&self) -> bool {
367 matches!(
368 self,
369 Self::ChannelVoice { .. } | Self::RunningChannelVoice { .. }
370 )
371 }
372
373 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 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 pub fn is_channel_mode(&self) -> bool {
409 matches!(
410 self,
411 Self::ChannelMode { .. } | Self::RunningChannelMode { .. }
412 )
413 }
414
415 pub fn is_system_common(&self) -> bool {
417 matches!(self, Self::SystemCommon { .. })
418 }
419
420 pub fn is_system_real_time(&self) -> bool {
422 matches!(self, Self::SystemRealTime { .. })
423 }
424
425 #[cfg(feature = "sysex")]
426 pub fn is_system_exclusive(&self) -> bool {
428 matches!(self, Self::SystemExclusive { .. })
429 }
430
431 #[cfg(feature = "file")]
432 pub fn is_meta(&self) -> bool {
434 matches!(self, Self::Meta { .. })
435 }
436
437 #[cfg(feature = "file")]
438 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
450pub fn next_message(m: &[u8]) -> Option<usize> {
457 if m.is_empty() {
458 return None;
459 }
460 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#[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 let mut midi = vec![];
596 noteon.extend_midi(&mut midi);
597 running_noteon.extend_midi(&mut midi);
598 reset.extend_midi(&mut midi);
600 running_reset.extend_midi(&mut midi);
601 cc.extend_midi(&mut midi);
603 running_cc.extend_midi(&mut midi);
604 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 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 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 let mut midi = vec![];
690 cc.extend_midi(&mut midi);
691 running_cc.extend_midi(&mut midi);
692
693 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 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 assert_eq!(next_message(&midi[1..]), Some(first_message_len - 1));
738 assert_eq!(next_message(&midi[first_message_len..]), None);
739 }
740}