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_on(&self) -> bool {
374 matches!(
375 self,
376 Self::ChannelVoice {
377 msg: ChannelVoiceMsg::NoteOn { .. } | ChannelVoiceMsg::HighResNoteOn { .. },
378 ..
379 } | Self::RunningChannelVoice {
380 msg: ChannelVoiceMsg::NoteOn { .. } | ChannelVoiceMsg::HighResNoteOn { .. },
381 ..
382 }
383 )
384 }
385
386 pub fn is_note_off(&self) -> bool {
387 matches!(
388 self,
389 Self::ChannelVoice {
390 msg: ChannelVoiceMsg::NoteOff { .. } | ChannelVoiceMsg::HighResNoteOff { .. },
391 ..
392 } | Self::RunningChannelVoice {
393 msg: ChannelVoiceMsg::NoteOff { .. } | ChannelVoiceMsg::HighResNoteOff { .. },
394 ..
395 }
396 )
397 }
398
399 pub fn is_note(&self) -> bool {
401 matches!(
402 self,
403 Self::ChannelVoice {
404 msg: ChannelVoiceMsg::NoteOn { .. }
405 | ChannelVoiceMsg::NoteOff { .. }
406 | ChannelVoiceMsg::HighResNoteOn { .. }
407 | ChannelVoiceMsg::HighResNoteOff { .. },
408 ..
409 } | Self::RunningChannelVoice {
410 msg: ChannelVoiceMsg::NoteOn { .. }
411 | ChannelVoiceMsg::NoteOff { .. }
412 | ChannelVoiceMsg::HighResNoteOn { .. }
413 | ChannelVoiceMsg::HighResNoteOff { .. },
414 ..
415 }
416 )
417 }
418
419 pub fn is_cc(&self) -> bool {
421 matches!(
422 self,
423 Self::ChannelVoice {
424 msg: ChannelVoiceMsg::ControlChange { .. },
425 ..
426 } | Self::RunningChannelVoice {
427 msg: ChannelVoiceMsg::ControlChange { .. },
428 ..
429 }
430 )
431 }
432
433 pub fn is_channel_mode(&self) -> bool {
435 matches!(
436 self,
437 Self::ChannelMode { .. } | Self::RunningChannelMode { .. }
438 )
439 }
440
441 pub fn is_system_common(&self) -> bool {
443 matches!(self, Self::SystemCommon { .. })
444 }
445
446 pub fn is_system_real_time(&self) -> bool {
448 matches!(self, Self::SystemRealTime { .. })
449 }
450
451 #[cfg(feature = "sysex")]
452 pub fn is_system_exclusive(&self) -> bool {
454 matches!(self, Self::SystemExclusive { .. })
455 }
456
457 #[cfg(feature = "file")]
458 pub fn is_meta(&self) -> bool {
460 matches!(self, Self::Meta { .. })
461 }
462
463 #[cfg(feature = "file")]
464 pub fn is_invalid(&self) -> bool {
466 matches!(self, Self::Invalid { .. })
467 }
468}
469
470impl From<&MidiMsg> for Vec<u8> {
471 fn from(m: &MidiMsg) -> Vec<u8> {
472 m.to_midi()
473 }
474}
475
476pub fn next_message(m: &[u8]) -> Option<usize> {
483 if m.is_empty() {
484 return None;
485 }
486 let start = if upper_bit_set(m[0]) { 1 } else { 0 };
489
490 (start..m.len()).find(|&i| upper_bit_set(m[i]))
491}
492
493fn upper_bit_set(x: u8) -> bool {
494 x & 0b10000000 != 0
495}
496
497#[cfg(feature = "std")]
498use strum::{EnumIter, EnumString};
499
500#[cfg_attr(feature = "std", derive(EnumIter, EnumString))]
502#[derive(Debug, Clone, Copy, PartialEq, Eq)]
503#[repr(u8)]
504pub enum Channel {
505 Ch1,
506 Ch2,
507 Ch3,
508 Ch4,
509 Ch5,
510 Ch6,
511 Ch7,
512 Ch8,
513 Ch9,
514 Ch10,
515 Ch11,
516 Ch12,
517 Ch13,
518 Ch14,
519 Ch15,
520 Ch16,
521}
522
523impl core::fmt::Display for Channel {
524 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
525 write!(f, "Ch{}", *self as u8 + 1)
526 }
527}
528
529impl Channel {
530 pub fn from_u8(x: u8) -> Self {
531 match x {
532 0 => Self::Ch1,
533 1 => Self::Ch2,
534 2 => Self::Ch3,
535 3 => Self::Ch4,
536 4 => Self::Ch5,
537 5 => Self::Ch6,
538 6 => Self::Ch7,
539 7 => Self::Ch8,
540 8 => Self::Ch9,
541 9 => Self::Ch10,
542 10 => Self::Ch11,
543 11 => Self::Ch12,
544 12 => Self::Ch13,
545 13 => Self::Ch14,
546 14 => Self::Ch15,
547 _ => Self::Ch16,
548 }
549 }
550}
551
552impl TryFrom<u8> for Channel {
553 type Error = &'static str;
554
555 fn try_from(value: u8) -> Result<Self, Self::Error> {
556 if value > 15 {
557 return Err("Invalid channel value");
558 }
559 Ok(Self::from_u8(value))
560 }
561}
562
563#[cfg(test)]
564mod tests {
565 use super::*;
566 use crate::Channel::*;
567
568 #[test]
569 fn test_ch() {
570 assert_eq!(Ch1, Channel::from_u8(0));
571 assert_eq!(Ch2, Channel::from_u8(1));
572 assert_eq!(Ch16, Channel::from_u8(255));
573 }
574
575 #[test]
576 fn test_ch_try_from() {
577 assert_eq!(Ch1, Channel::try_from(0).unwrap());
578 assert_eq!(Ch2, Channel::try_from(1).unwrap());
579 assert_eq!(Ch16, Channel::try_from(15).unwrap());
580 assert!(Channel::try_from(16).is_err());
581 }
582
583 #[test]
584 fn test_running_status() {
585 let noteon = MidiMsg::ChannelVoice {
586 channel: Channel::Ch1,
587 msg: ChannelVoiceMsg::NoteOn {
588 note: 0x42,
589 velocity: 0x60,
590 },
591 };
592 let running_noteon = MidiMsg::RunningChannelVoice {
593 channel: Channel::Ch1,
594 msg: ChannelVoiceMsg::NoteOn {
595 note: 0x42,
596 velocity: 0x60,
597 },
598 };
599 let reset = MidiMsg::ChannelMode {
600 channel: Channel::Ch1,
601 msg: ChannelModeMsg::ResetAllControllers,
602 };
603 let running_reset = MidiMsg::RunningChannelMode {
604 channel: Channel::Ch1,
605 msg: ChannelModeMsg::ResetAllControllers,
606 };
607 let cc = MidiMsg::ChannelVoice {
608 channel: Channel::Ch1,
609 msg: ChannelVoiceMsg::ControlChange {
610 control: crate::ControlChange::Volume(0x7F),
611 },
612 };
613 let running_cc = MidiMsg::RunningChannelVoice {
614 channel: Channel::Ch1,
615 msg: ChannelVoiceMsg::ControlChange {
616 control: crate::ControlChange::Volume(0x7F),
617 },
618 };
619
620 let mut midi = vec![];
622 noteon.extend_midi(&mut midi);
623 running_noteon.extend_midi(&mut midi);
624 reset.extend_midi(&mut midi);
626 running_reset.extend_midi(&mut midi);
627 cc.extend_midi(&mut midi);
629 running_cc.extend_midi(&mut midi);
630 reset.extend_midi(&mut midi);
632 running_cc.extend_midi(&mut midi);
633 cc.extend_midi(&mut midi);
634 running_reset.extend_midi(&mut midi);
635
636 let mut offset = 0;
638 let mut ctx = ReceiverContext::new().complex_cc();
639 let (msg1, len) = MidiMsg::from_midi_with_context(&midi, &mut ctx).expect("Not an error");
640 offset += len;
641 let (msg2, len) =
642 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
643 offset += len;
644 let (msg3, len) =
645 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
646 offset += len;
647 let (msg4, len) =
648 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
649 offset += len;
650 let (msg5, len) =
651 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
652 offset += len;
653 let (msg6, len) =
654 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
655 offset += len;
656 let (msg7, len) =
657 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
658 offset += len;
659 let (msg8, len) =
660 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
661 offset += len;
662 let (msg9, len) =
663 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
664 offset += len;
665 let (msg10, _) =
666 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
667
668 assert_eq!(msg1, noteon);
670 assert_eq!(msg2, noteon);
671 assert_eq!(msg3, reset);
672 assert_eq!(msg4, reset);
673 assert_eq!(msg5, cc);
674 assert_eq!(msg6, cc);
675 assert_eq!(msg7, reset);
676 assert_eq!(msg8, cc);
677 assert_eq!(msg9, cc);
678 assert_eq!(msg10, reset);
679 }
680
681 #[test]
682 fn test_simple_cc_running_status() {
683 let cc = MidiMsg::ChannelVoice {
684 channel: Channel::Ch1,
685 msg: ChannelVoiceMsg::ControlChange {
686 control: crate::ControlChange::Volume(0x7F),
687 },
688 };
689 let running_cc = MidiMsg::RunningChannelVoice {
690 channel: Channel::Ch1,
691 msg: ChannelVoiceMsg::ControlChange {
692 control: crate::ControlChange::Volume(0x7F),
693 },
694 };
695 let simple_cc_msb = MidiMsg::ChannelVoice {
696 channel: Channel::Ch1,
697 msg: ChannelVoiceMsg::ControlChange {
698 control: crate::ControlChange::CC {
699 control: 7,
700 value: 0,
701 },
702 },
703 };
704 let simple_cc_lsb = MidiMsg::ChannelVoice {
705 channel: Channel::Ch1,
706 msg: ChannelVoiceMsg::ControlChange {
707 control: crate::ControlChange::CC {
708 control: 7 + 32,
709 value: 0x7F,
710 },
711 },
712 };
713
714 let mut midi = vec![];
716 cc.extend_midi(&mut midi);
717 running_cc.extend_midi(&mut midi);
718
719 let mut offset = 0;
721 let mut ctx = ReceiverContext::new();
722 let (msg1, len) = MidiMsg::from_midi_with_context(&midi, &mut ctx).expect("Not an error");
723 offset += len;
724 let (msg2, len) =
725 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
726 offset += len;
727 let (msg3, len) =
728 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
729 offset += len;
730 let (msg4, _) =
731 MidiMsg::from_midi_with_context(&midi[offset..], &mut ctx).expect("Not an error");
732
733 assert_eq!(msg1, simple_cc_msb);
735 assert_eq!(msg2, simple_cc_lsb);
736 assert_eq!(msg3, simple_cc_msb);
737 assert_eq!(msg4, simple_cc_lsb);
738 }
739
740 #[test]
741 fn test_next_message() {
742 let mut midi = vec![];
743 MidiMsg::ChannelVoice {
744 channel: Channel::Ch1,
745 msg: ChannelVoiceMsg::NoteOn {
746 note: 0x42,
747 velocity: 0x60,
748 },
749 }
750 .extend_midi(&mut midi);
751 let first_message_len = midi.len();
752 MidiMsg::ChannelVoice {
753 channel: Channel::Ch1,
754 msg: ChannelVoiceMsg::NoteOn {
755 note: 0x42,
756 velocity: 0x60,
757 },
758 }
759 .extend_midi(&mut midi);
760
761 assert_eq!(next_message(&midi), Some(first_message_len));
762 assert_eq!(next_message(&midi[1..]), Some(first_message_len - 1));
764 assert_eq!(next_message(&midi[first_message_len..]), None);
765 }
766}