1use std::iter;
2
3#[derive(Debug)]
5pub enum Channel {
6 Channel1,
7 Channel2,
8 Channel3,
9 Channel4,
10 Channel5,
11 Channel6,
12 Channel7,
13 Channel8,
14 Channel9,
15 Channel10,
16 Channel11,
17 Channel12,
18 Channel13,
19 Channel14,
20 Channel15,
21 Channel16,
22}
23
24impl From<u8> for Channel {
25 fn from(value: u8) -> Self {
26 match value {
27 0 => Self::Channel1,
28 1 => Self::Channel2,
29 2 => Self::Channel3,
30 3 => Self::Channel4,
31 4 => Self::Channel5,
32 5 => Self::Channel6,
33 6 => Self::Channel7,
34 7 => Self::Channel8,
35 8 => Self::Channel9,
36 9 => Self::Channel10,
37 10 => Self::Channel11,
38 11 => Self::Channel12,
39 12 => Self::Channel13,
40 13 => Self::Channel14,
41 14 => Self::Channel15,
42 _ => Self::Channel16,
43 }
44 }
45}
46
47impl Into<u8> for &Channel {
48 fn into(self) -> u8 {
49 match self.as_ref() {
50 Channel::Channel1 => 0,
51 Channel::Channel2 => 1,
52 Channel::Channel3 => 2,
53 Channel::Channel4 => 3,
54 Channel::Channel5 => 4,
55 Channel::Channel6 => 5,
56 Channel::Channel7 => 6,
57 Channel::Channel8 => 7,
58 Channel::Channel9 => 8,
59 Channel::Channel10 => 9,
60 Channel::Channel11 => 10,
61 Channel::Channel12 => 11,
62 Channel::Channel13 => 12,
63 Channel::Channel14 => 13,
64 Channel::Channel15 => 14,
65 Channel::Channel16 => 15,
66 }
67 }
68}
69
70impl AsRef<Channel> for Channel {
71 fn as_ref(&self) -> &Channel {
72 self
73 }
74}
75
76#[derive(Debug)]
80pub enum Message<'a> {
81 NoteOff(Channel, u8, u8),
84 NoteOn(Channel, u8, u8),
85 PolyphonicAftertouch(Channel, u8, u8),
86 ControlOrModeChange(Channel, u8, u8),
89 ProgramChange(Channel, u8),
90 Aftertouch(Channel, u8),
91 PitchBendChange(Channel, u8, u8),
92 SystemExclusive(&'a [u8]),
93 SongPositionPointer(u8, u8),
95 SongSelect(u8),
96 TuneRequest,
97 TimingClock,
98 Start,
99 Continue,
100 Stop,
101 ActiveSensing,
102 SystemReset,
103}
104
105impl<'a> From<&'a [u8]> for Message<'a> {
106 fn from(value: &'a [u8]) -> Self {
107 let first_byte = if value.len() >= 1 {
108 value[0]
109 } else {
110 panic!("A MIDI message can't be zero bytes long!");
111 };
112
113 let get_second_byte = || {
114 if value.len() >= 2 {
115 value[1]
116 } else {
117 panic!("No second byte present!")
119 }
120 };
121
122 let get_third_byte = || {
123 if value.len() >= 3 {
124 value[2]
125 } else {
126 panic!("No third byte present!")
127 }
128 };
129
130 match first_byte {
131 128..=143 => Self::NoteOff(
132 Channel::from(first_byte - 128),
133 get_second_byte(),
134 get_third_byte(),
135 ),
136 144..=159 => Self::NoteOn(
137 Channel::from(first_byte - 144),
138 get_second_byte(),
139 get_third_byte(),
140 ),
141 160..=175 => Self::PolyphonicAftertouch(
142 Channel::from(first_byte - 145),
143 get_second_byte(),
144 get_third_byte(),
145 ),
146 176..=191 => Self::ControlOrModeChange(
147 Channel::from(first_byte - 176),
148 get_second_byte(),
149 get_third_byte(),
150 ),
151 192..=207 => Self::ProgramChange(Channel::from(first_byte - 192), get_second_byte()),
152 208..=223 => Self::Aftertouch(Channel::from(first_byte - 208), get_second_byte()),
153 224..=239 => Self::PitchBendChange(
154 Channel::from(first_byte),
155 get_second_byte(),
156 get_third_byte(),
157 ),
158 240 => Self::SystemExclusive(&value[1..value.len() - 1]),
159 242 => Self::SongPositionPointer(get_second_byte(), get_third_byte()),
160 243 => Self::SongSelect(get_second_byte()),
161 246 => Self::TuneRequest,
162 248 => Self::TimingClock,
163 250 => Self::Start,
164 251 => Self::Continue,
165 252 => Self::Stop,
166 254 => Self::ActiveSensing,
167 255 => Self::SystemReset,
168 _ => panic!("Invalid MIDI message!"),
170 }
171 }
172}
173
174impl<'a> Into<Vec<u8>> for Message<'a> {
175 fn into(self) -> Vec<u8> {
176 fn c_to_u8(channel: &Channel) -> u8 {
177 Into::<u8>::into(channel)
178 }
179
180 match self {
181 Message::NoteOff(ref channel, note, velocity) => {
182 vec![128u8 + c_to_u8(channel), note, velocity]
183 }
184 Message::NoteOn(ref channel, note, velocity) => {
185 vec![144u8 + c_to_u8(channel), note, velocity]
186 }
187 Message::PolyphonicAftertouch(ref channel, note, pressure) => {
188 vec![160u8 + c_to_u8(channel), note, pressure]
189 }
190 Message::ControlOrModeChange(ref channel, byte2, byte3) => {
191 vec![176u8 + c_to_u8(channel), byte2, byte3]
192 }
193 Message::ProgramChange(ref channel, program) => {
194 vec![192u8 + c_to_u8(channel), program]
195 }
196 Message::Aftertouch(ref channel, pressure) => {
197 vec![208u8 + c_to_u8(channel), pressure]
198 }
199 Message::PitchBendChange(ref channel, lsb, msb) => {
200 vec![224u8 + c_to_u8(channel), lsb, msb]
201 }
202 Message::SystemExclusive(data) => iter::once(240u8)
203 .chain(data.to_owned())
204 .chain(iter::once(247u8))
205 .collect(),
206 Message::SongPositionPointer(lsb, msb) => {
207 vec![242u8, lsb, msb]
208 }
209 Message::SongSelect(song) => {
210 vec![243u8, song]
211 }
212 Message::TuneRequest => {
213 vec![246u8]
214 }
215 Message::TimingClock => {
216 vec![248u8]
217 }
218 Message::Start => {
219 vec![250u8]
220 }
221 Message::Continue => {
222 vec![251u8]
223 }
224 Message::Stop => {
225 vec![252u8]
226 }
227 Message::ActiveSensing => {
228 vec![254u8]
229 }
230 Message::SystemReset => {
231 vec![255u8]
232 }
233 }
234 }
235}