1use super::parse_error::*;
2use crate::util::*;
3use alloc::vec::Vec;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum ChannelModeMsg {
8 AllSoundOff,
10 AllNotesOff,
12 ResetAllControllers,
14 OmniMode(bool),
16 PolyMode(PolyMode),
18 LocalControl(bool),
21}
22
23impl ChannelModeMsg {
24 pub(crate) fn extend_midi(&self, v: &mut Vec<u8>) {
25 v.push(0xB0);
26 self.extend_midi_running(v);
27 }
28
29 pub(crate) fn extend_midi_running(&self, v: &mut Vec<u8>) {
30 match self {
31 ChannelModeMsg::AllSoundOff => {
32 v.push(120);
33 v.push(0);
34 }
35 ChannelModeMsg::ResetAllControllers => {
36 v.push(121);
37 v.push(0);
38 }
39 ChannelModeMsg::LocalControl(on) => {
40 v.push(122);
41 v.push(if *on { 127 } else { 0 });
42 }
43 ChannelModeMsg::AllNotesOff => {
44 v.push(123);
45 v.push(0);
46 }
47 ChannelModeMsg::OmniMode(on) => {
48 v.push(if *on { 125 } else { 124 });
49 v.push(0);
50 }
51 ChannelModeMsg::PolyMode(m) => {
52 v.push(if *m == PolyMode::Poly { 127 } else { 126 });
53 v.push(match *m {
54 PolyMode::Poly => 0,
55 PolyMode::Mono(n) => n.min(16),
56 })
57 }
58 }
59 }
60
61 pub(crate) fn from_midi(m: &[u8]) -> Result<(Self, usize), ParseError> {
62 let (msg, len) = ChannelModeMsg::from_midi_running(&m[1..])?;
64 Ok((msg, len + 1))
65 }
66
67 pub(crate) fn from_midi_running(m: &[u8]) -> Result<(Self, usize), ParseError> {
68 if let (Some(b1), Some(b2)) = (m.first(), m.get(1)) {
69 if *b2 > 127 {
70 return Err(ParseError::ByteOverflow);
71 }
72 match (b1, b2) {
73 (120, _) => Ok((Self::AllSoundOff, 2)),
74 (121, _) => Ok((Self::ResetAllControllers, 2)),
75 (122, b2) => Ok((Self::LocalControl(bool_from_u7(*b2)?), 2)),
76 (123, _) => Ok((Self::AllNotesOff, 2)),
77 (124, _) => Ok((Self::OmniMode(false), 2)),
78 (125, _) => Ok((Self::OmniMode(true), 2)),
79 (126, b2) => Ok((Self::PolyMode(PolyMode::Mono(u8_from_u7(*b2)?)), 2)),
80 (127, _) => Ok((Self::PolyMode(PolyMode::Poly), 2)),
81 _ => Err(ParseError::Invalid(
82 "This shouldn't be possible: values below 120 should be control change messages",
83 )),
84 }
85 } else {
86 Err(ParseError::UnexpectedEnd)
87 }
88 }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum PolyMode {
94 Mono(u8),
100 Poly,
102}
103
104#[cfg(test)]
105mod tests {
106 use crate::*;
107 use alloc::vec;
108
109 #[test]
110 fn serialize_channel_mode_msg() {
111 assert_eq!(
112 MidiMsg::ChannelMode {
113 channel: Channel::Ch3,
114 msg: ChannelModeMsg::AllSoundOff
115 }
116 .to_midi(),
117 vec![0xB2, 120, 0]
118 );
119
120 assert_eq!(
121 MidiMsg::RunningChannelMode {
122 channel: Channel::Ch3,
123 msg: ChannelModeMsg::AllSoundOff
124 }
125 .to_midi(),
126 vec![120, 0]
127 );
128
129 assert_eq!(
130 MidiMsg::ChannelMode {
131 channel: Channel::Ch3,
132 msg: ChannelModeMsg::LocalControl(true)
133 }
134 .to_midi(),
135 vec![0xB2, 122, 127]
136 );
137
138 assert_eq!(
139 MidiMsg::ChannelMode {
140 channel: Channel::Ch3,
141 msg: ChannelModeMsg::OmniMode(true)
142 }
143 .to_midi(),
144 vec![0xB2, 125, 0]
145 );
146
147 assert_eq!(
148 MidiMsg::ChannelMode {
149 channel: Channel::Ch3,
150 msg: ChannelModeMsg::OmniMode(false)
151 }
152 .to_midi(),
153 vec![0xB2, 124, 0]
154 );
155
156 assert_eq!(
157 MidiMsg::ChannelMode {
158 channel: Channel::Ch3,
159 msg: ChannelModeMsg::PolyMode(PolyMode::Poly)
160 }
161 .to_midi(),
162 vec![0xB2, 127, 0]
163 );
164
165 assert_eq!(
166 MidiMsg::ChannelMode {
167 channel: Channel::Ch3,
168 msg: ChannelModeMsg::PolyMode(PolyMode::Mono(4))
169 }
170 .to_midi(),
171 vec![0xB2, 126, 4]
172 );
173 }
174
175 #[test]
176 fn deserialize_channel_mode_msg() {
177 let mut ctx = ReceiverContext::new();
178
179 test_serialization(
180 MidiMsg::ChannelMode {
181 channel: Channel::Ch3,
182 msg: ChannelModeMsg::AllSoundOff,
183 },
184 &mut ctx,
185 );
186
187 test_serialization(
188 MidiMsg::ChannelMode {
189 channel: Channel::Ch3,
190 msg: ChannelModeMsg::LocalControl(true),
191 },
192 &mut ctx,
193 );
194
195 test_serialization(
196 MidiMsg::ChannelMode {
197 channel: Channel::Ch3,
198 msg: ChannelModeMsg::OmniMode(true),
199 },
200 &mut ctx,
201 );
202
203 test_serialization(
204 MidiMsg::ChannelMode {
205 channel: Channel::Ch3,
206 msg: ChannelModeMsg::OmniMode(false),
207 },
208 &mut ctx,
209 );
210
211 test_serialization(
212 MidiMsg::ChannelMode {
213 channel: Channel::Ch3,
214 msg: ChannelModeMsg::PolyMode(PolyMode::Poly),
215 },
216 &mut ctx,
217 );
218
219 test_serialization(
220 MidiMsg::ChannelMode {
221 channel: Channel::Ch3,
222 msg: ChannelModeMsg::PolyMode(PolyMode::Mono(4)),
223 },
224 &mut ctx,
225 );
226 }
227}