1#![doc = include_str!("channel_voice2/README.md")]
2
3mod assignable_controller;
4mod assignable_per_note_controller;
5mod attribute;
6mod channel_pitch_bend;
7mod channel_pressure;
8mod control_change;
9mod controller;
10mod key_pressure;
11mod note_off;
12mod note_on;
13mod packet;
14mod per_note_management;
15mod per_note_pitch_bend;
16mod program_change;
17mod registered_controller;
18mod registered_per_note_controller;
19mod relative_assignable_controller;
20mod relative_registered_controller;
21
22pub use assignable_controller::*;
23pub use assignable_per_note_controller::*;
24pub use attribute::Attribute as NoteAttribute;
25pub use channel_pitch_bend::*;
26pub use channel_pressure::*;
27pub use control_change::*;
28pub use controller::Controller;
29pub use key_pressure::*;
30pub use note_off::*;
31pub use note_on::*;
32pub use packet::Packet;
33pub use per_note_management::*;
34pub use per_note_pitch_bend::*;
35pub use program_change::*;
36pub use registered_controller::*;
37pub use registered_per_note_controller::*;
38pub use relative_assignable_controller::*;
39pub use relative_registered_controller::*;
40
41pub(crate) const UMP_MESSAGE_TYPE: u8 = 0x4;
42
43#[derive(
44 derive_more::From,
45 midi2_proc::Data,
46 midi2_proc::Packets,
47 midi2_proc::Channeled,
48 midi2_proc::Grouped,
49 midi2_proc::RebufferFrom,
50 midi2_proc::RebufferFromArray,
51 midi2_proc::TryRebufferFrom,
52 Clone,
53 Copy,
54 Debug,
55 PartialEq,
56 Eq,
57)]
58pub enum ChannelVoice2<B: crate::buffer::Ump> {
59 AssignableController(assignable_controller::AssignableController<B>),
60 AssignablePerNoteController(assignable_per_note_controller::AssignablePerNoteController<B>),
61 ChannelPitchBend(channel_pitch_bend::ChannelPitchBend<B>),
62 ChannelPressure(channel_pressure::ChannelPressure<B>),
63 ControlChange(control_change::ControlChange<B>),
64 KeyPressure(key_pressure::KeyPressure<B>),
65 NoteOff(note_off::NoteOff<B>),
66 NoteOn(note_on::NoteOn<B>),
67 PerNoteManagement(per_note_management::PerNoteManagement<B>),
68 PerNotePitchBend(per_note_pitch_bend::PerNotePitchBend<B>),
69 ProgramChange(program_change::ProgramChange<B>),
70 RegisteredController(registered_controller::RegisteredController<B>),
71 RegisteredPerNoteController(registered_per_note_controller::RegisteredPerNoteController<B>),
72 RelativeAssignableController(relative_assignable_controller::RelativeAssignableController<B>),
73 RelativeRegisteredController(relative_registered_controller::RelativeRegisteredController<B>),
74}
75
76impl<'a> TryFrom<&'a [u32]> for ChannelVoice2<&'a [u32]> {
77 type Error = crate::error::InvalidData;
78 fn try_from(buffer: &'a [u32]) -> Result<Self, Self::Error> {
79 if buffer.is_empty() {
80 return Err(crate::error::InvalidData(
81 crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT,
82 ));
83 };
84
85 use crate::detail::BitOps;
86
87 Ok(match u8::from(buffer[0].nibble(2)) {
88 assignable_controller::STATUS => {
89 assignable_controller::AssignableController::try_from(buffer)?.into()
90 }
91 assignable_per_note_controller::STATUS => {
92 assignable_per_note_controller::AssignablePerNoteController::try_from(buffer)?
93 .into()
94 }
95 channel_pitch_bend::STATUS => {
96 channel_pitch_bend::ChannelPitchBend::try_from(buffer)?.into()
97 }
98 channel_pressure::STATUS => channel_pressure::ChannelPressure::try_from(buffer)?.into(),
99 control_change::STATUS => control_change::ControlChange::try_from(buffer)?.into(),
100 key_pressure::STATUS => key_pressure::KeyPressure::try_from(buffer)?.into(),
101 note_off::STATUS => note_off::NoteOff::try_from(buffer)?.into(),
102 note_on::STATUS => note_on::NoteOn::try_from(buffer)?.into(),
103 per_note_management::STATUS => {
104 per_note_management::PerNoteManagement::try_from(buffer)?.into()
105 }
106 per_note_pitch_bend::STATUS => {
107 per_note_pitch_bend::PerNotePitchBend::try_from(buffer)?.into()
108 }
109 program_change::STATUS => program_change::ProgramChange::try_from(buffer)?.into(),
110 registered_controller::STATUS => {
111 registered_controller::RegisteredController::try_from(buffer)?.into()
112 }
113 registered_per_note_controller::STATUS => {
114 registered_per_note_controller::RegisteredPerNoteController::try_from(buffer)?
115 .into()
116 }
117 relative_assignable_controller::STATUS => {
118 relative_assignable_controller::RelativeAssignableController::try_from(buffer)?
119 .into()
120 }
121 relative_registered_controller::STATUS => {
122 relative_registered_controller::RelativeRegisteredController::try_from(buffer)?
123 .into()
124 }
125 _ => Err(crate::error::InvalidData(
126 "Unknown midi2 channel voice status",
127 ))?,
128 })
129 }
130}
131
132#[cfg(test)]
133mod test {
134 use super::*;
135 use pretty_assertions::assert_eq;
136
137 #[test]
138 fn channel() {
139 use crate::traits::Channeled;
140 use crate::ux::u4;
141
142 assert_eq!(
143 ChannelVoice2::try_from(&[0x4BAC_5900, 0xC0B83064][..])
144 .unwrap()
145 .channel(),
146 u4::new(0xC),
147 );
148 }
149
150 #[test]
151 fn packets() {
152 use crate::Packets;
153
154 let message = ChannelVoice2::try_from(&[0x4BAC_5900, 0xC0B83064][..]).unwrap();
155 let mut packets = message.packets();
156 assert_eq!(&*packets.next().unwrap(), &[0x4BAC_5900, 0xC0B83064][..]);
157 assert_eq!(packets.next(), None);
158 }
159
160 #[test]
161 fn rebuffer_from_array() {
162 use crate::ArrayRebufferFrom;
163
164 let message = ChannelVoice2::try_from(&[0x4BAC_5900, 0xC0B83064][..]).unwrap();
165 let _ = ChannelVoice2::<[u32; 2]>::array_rebuffer_from(message);
166 }
167}