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