From a11b695c5ee5f50355c7a23d0f70e1d851d285c2 Mon Sep 17 00:00:00 2001 From: beau trepp Date: Thu, 12 Dec 2019 19:38:15 +0800 Subject: [PATCH] Converts midi channel and cable to be enums. This will allow pattern matching and seems to be more use-able. Tests are defined to ensure the u8 serialization still corresponds to expected midi values --- src/data/midi/code_index_number.rs | 1 - src/data/midi/midi_channel.rs | 71 +++++++++++++++++++--- src/data/midi/midi_message.rs | 4 ++ src/data/midi/mod.rs | 1 + src/data/usb_midi/cable_number.rs | 70 +++++++++++++++++++-- src/data/usb_midi/usb_midi_event_packet.rs | 1 + 6 files changed, 133 insertions(+), 15 deletions(-) diff --git a/src/data/midi/code_index_number.rs b/src/data/midi/code_index_number.rs index a57e2c3..9fd1c0b 100644 --- a/src/data/midi/code_index_number.rs +++ b/src/data/midi/code_index_number.rs @@ -21,7 +21,6 @@ impl Into for CodeIndexNumber { } } - impl CodeIndexNumber { /// Miscellaneous function codes. Reserved for future extensions diff --git a/src/data/midi/midi_channel.rs b/src/data/midi/midi_channel.rs index 84ab8bb..14f0562 100644 --- a/src/data/midi/midi_channel.rs +++ b/src/data/midi/midi_channel.rs @@ -2,24 +2,79 @@ use crate::util::try_from::{TryFrom}; /// The MidiChannel is a value ranging from 0x0 to 0xF /// This is a standard midi concept -pub struct MidiChannel(u8); - +#[derive(Debug)] +#[repr(u8)] +pub enum MidiChannel { + Channel0 = 0x0, Channel1 = 0x1, Channel2 = 0x2, Channel3 = 0x3, + Channel4 = 0x4, Channel5 = 0x5, Channel6 = 0x6, Channel7 = 0x7, + Channel8 = 0x8, Channel9 = 0x9, Channel10 = 0xA, Channel11 = 0xB, + Channel12 = 0xC, Channel13 = 0xD, Channel14 = 0xE, Channel15 = 0xF +} impl TryFrom for MidiChannel { - fn try_from(value:u8) -> Option { - if value > 0xF { - None - } else { - Some(MidiChannel(value)) + fn try_from(value:u8) -> Option { + match value { + x if x == MidiChannel::Channel0 as u8 => Some(MidiChannel::Channel0), + x if x == MidiChannel::Channel1 as u8 => Some(MidiChannel::Channel1), + x if x == MidiChannel::Channel2 as u8 => Some(MidiChannel::Channel2), + x if x == MidiChannel::Channel3 as u8 => Some(MidiChannel::Channel3), + x if x == MidiChannel::Channel4 as u8 => Some(MidiChannel::Channel4), + x if x == MidiChannel::Channel5 as u8 => Some(MidiChannel::Channel5), + x if x == MidiChannel::Channel6 as u8 => Some(MidiChannel::Channel6), + x if x == MidiChannel::Channel7 as u8 => Some(MidiChannel::Channel7), + x if x == MidiChannel::Channel8 as u8 => Some(MidiChannel::Channel8), + x if x == MidiChannel::Channel9 as u8 => Some(MidiChannel::Channel9), + x if x == MidiChannel::Channel10 as u8 => Some(MidiChannel::Channel10), + x if x == MidiChannel::Channel11 as u8 => Some(MidiChannel::Channel11), + x if x == MidiChannel::Channel12 as u8 => Some(MidiChannel::Channel12), + x if x == MidiChannel::Channel13 as u8 => Some(MidiChannel::Channel13), + x if x == MidiChannel::Channel14 as u8 => Some(MidiChannel::Channel14), + x if x == MidiChannel::Channel15 as u8 => Some(MidiChannel::Channel15), + _ => None } } + } impl Into for MidiChannel { fn into(self) -> u8 { - self.0 + self as u8 } } +#[cfg(test)] +mod tests { + + use super::*; + macro_rules! channel_test { + ($($id:ident:$value:expr,)*) => { + $( + #[test] + fn $id() { + let (input,expected) = $value; + assert_eq!(input as u8, expected); + } + )* + } + } + channel_test! { + cable_0: (MidiChannel::Channel0,0), + cable_1: (MidiChannel::Channel1,1), + cable_2: (MidiChannel::Channel2,2), + cable_3: (MidiChannel::Channel3,3), + cable_4: (MidiChannel::Channel4,4), + cable_5: (MidiChannel::Channel5,5), + cable_6: (MidiChannel::Channel6,6), + cable_7: (MidiChannel::Channel7,7), + cable_8: (MidiChannel::Channel8,8), + cable_9: (MidiChannel::Channel9,9), + cable_10: (MidiChannel::Channel10,10), + cable_11: (MidiChannel::Channel11,11), + cable_12: (MidiChannel::Channel12,12), + cable_13: (MidiChannel::Channel13,13), + cable_14: (MidiChannel::Channel14,14), + cable_15: (MidiChannel::Channel15,15), + } +} \ No newline at end of file diff --git a/src/data/midi/midi_message.rs b/src/data/midi/midi_message.rs index e69de29..03d2b10 100644 --- a/src/data/midi/midi_message.rs +++ b/src/data/midi/midi_message.rs @@ -0,0 +1,4 @@ + +pub struct MidiMessage { + payload: [u8;3] +} \ No newline at end of file diff --git a/src/data/midi/mod.rs b/src/data/midi/mod.rs index 98a2383..4d17e2f 100644 --- a/src/data/midi/mod.rs +++ b/src/data/midi/mod.rs @@ -1,3 +1,4 @@ pub mod notes; pub mod code_index_number; pub mod midi_channel; +pub mod midi_message; \ No newline at end of file diff --git a/src/data/usb_midi/cable_number.rs b/src/data/usb_midi/cable_number.rs index 14f439d..78467d5 100644 --- a/src/data/usb_midi/cable_number.rs +++ b/src/data/usb_midi/cable_number.rs @@ -3,21 +3,79 @@ use crate::util::try_from::{TryFrom}; /// The Cable Number (CN) is a value ranging from 0x0 to 0xF /// indicating the number assignment of the Embedded MIDI Jack associated /// with the endpoint that is transferring the data -pub struct CableNumber(u8); +#[derive(Debug)] +#[repr(u8)] +pub enum CableNumber { + Cable0 = 0x0, Cable1 = 0x1, Cable2 = 0x2, Cable3 = 0x3, + Cable4 = 0x4, Cable5 = 0x5, Cable6 = 0x6, Cable7 = 0x7, + Cable8 = 0x8, Cable9 = 0x9, Cable10 = 0xA, Cable11 = 0xB, + Cable12 = 0xC, Cable13 = 0xD, Cable14 = 0xE, Cable15 = 0xF +} impl TryFrom for CableNumber { fn try_from(value:u8) -> Option { - if value > 0xF { - None - } else { - Some(CableNumber(value)) + match value { + x if x == CableNumber::Cable0 as u8 => Some(CableNumber::Cable0), + x if x == CableNumber::Cable1 as u8 => Some(CableNumber::Cable1), + x if x == CableNumber::Cable2 as u8 => Some(CableNumber::Cable2), + x if x == CableNumber::Cable3 as u8 => Some(CableNumber::Cable3), + x if x == CableNumber::Cable4 as u8 => Some(CableNumber::Cable4), + x if x == CableNumber::Cable5 as u8 => Some(CableNumber::Cable5), + x if x == CableNumber::Cable6 as u8 => Some(CableNumber::Cable6), + x if x == CableNumber::Cable7 as u8 => Some(CableNumber::Cable7), + x if x == CableNumber::Cable8 as u8 => Some(CableNumber::Cable8), + x if x == CableNumber::Cable9 as u8 => Some(CableNumber::Cable9), + x if x == CableNumber::Cable10 as u8 => Some(CableNumber::Cable10), + x if x == CableNumber::Cable11 as u8 => Some(CableNumber::Cable11), + x if x == CableNumber::Cable12 as u8 => Some(CableNumber::Cable12), + x if x == CableNumber::Cable13 as u8 => Some(CableNumber::Cable13), + x if x == CableNumber::Cable14 as u8 => Some(CableNumber::Cable14), + x if x == CableNumber::Cable15 as u8 => Some(CableNumber::Cable15), + _ => None } } + } impl Into for CableNumber { fn into(self) -> u8 { - self.0 + self as u8 } } + +#[cfg(test)] +mod tests { + + use super::*; + macro_rules! cable_test { + ($($id:ident:$value:expr,)*) => { + $( + #[test] + fn $id() { + let (input,expected) = $value; + assert_eq!(input as u8, expected); + } + )* + } + } + + cable_test! { + cable_0: (CableNumber::Cable0,0), + cable_1: (CableNumber::Cable1,1), + cable_2: (CableNumber::Cable2,2), + cable_3: (CableNumber::Cable3,3), + cable_4: (CableNumber::Cable4,4), + cable_5: (CableNumber::Cable5,5), + cable_6: (CableNumber::Cable6,6), + cable_7: (CableNumber::Cable7,7), + cable_8: (CableNumber::Cable8,8), + cable_9: (CableNumber::Cable9,9), + cable_10: (CableNumber::Cable10,10), + cable_11: (CableNumber::Cable11,11), + cable_12: (CableNumber::Cable12,12), + cable_13: (CableNumber::Cable13,13), + cable_14: (CableNumber::Cable14,14), + cable_15: (CableNumber::Cable15,15), + } +} \ No newline at end of file diff --git a/src/data/usb_midi/usb_midi_event_packet.rs b/src/data/usb_midi/usb_midi_event_packet.rs index 0882fbf..e3b75d5 100644 --- a/src/data/usb_midi/usb_midi_event_packet.rs +++ b/src/data/usb_midi/usb_midi_event_packet.rs @@ -2,6 +2,7 @@ use crate::data::usb_midi::cable_number::CableNumber; use crate::data::midi::code_index_number::CodeIndexNumber; use crate::data::midi::notes::Note; use crate::data::midi::midi_channel::MidiChannel; +use crate::data::midi::midi_message::MidiMessage; /// A packet that communicates with the host /// Note that the payload seems fairly 'open'