1use crate::message::*;
3use crate::prelude::*;
4use crate::status_bytes::*;
5use lv2rs_atom::prelude::*;
6use lv2rs_urid::CachedMap;
7use std::ffi::CStr;
8
9#[repr(C)]
10pub struct RawMidiMessage([u8]);
21
22impl RawMidiMessage {
23 pub fn interpret(&self) -> Result<MidiMessage, TryFromError> {
29 MidiMessage::try_from(&self.0)
30 }
31}
32
33impl<'a> AtomBody for RawMidiMessage {
34 type InitializationParameter = MidiMessage;
35
36 fn get_uri() -> &'static CStr {
37 unsafe { CStr::from_bytes_with_nul_unchecked(crate::uris::EVENT_URI) }
38 }
39
40 unsafe fn initialize_body<'b, W>(
41 writer: &mut W,
42 message: &MidiMessage,
43 _urids: &mut CachedMap,
44 ) -> Result<(), ()>
45 where
46 W: WritingFrame<'b> + WritingFrameExt<'b, Self>,
47 {
48 match message {
49 MidiMessage::NoteOff {
50 channel,
51 note,
52 velocity,
53 } => {
54 write_channel_status(writer, NOTE_OFF_STATUS, *channel)?;
55 write_data(writer, *note)?;
56 write_data(writer, *velocity)?;
57 }
58 MidiMessage::NoteOn {
59 channel,
60 note,
61 velocity,
62 } => {
63 write_channel_status(writer, NOTE_ON_STATUS, *channel)?;
64 write_data(writer, *note)?;
65 write_data(writer, *velocity)?;
66 }
67 MidiMessage::PolyKeyPressure { channel, pressure } => {
68 write_channel_status(writer, POLY_KEY_PRESSURE_STATUS, *channel)?;
69 write_data(writer, *pressure)?;
70 }
71 MidiMessage::ControlChange {
72 channel,
73 control_number,
74 control_value,
75 } => {
76 write_channel_status(writer, CONTROL_CHANGE_STATUS, *channel)?;
77 write_data(writer, *control_number)?;
78 write_data(writer, *control_value)?;
79 }
80 MidiMessage::ProgramChange {
81 channel,
82 program_number,
83 } => {
84 write_channel_status(writer, PROGRAM_CHANGE_STATUS, *channel)?;
85 write_data(writer, *program_number)?;
86 }
87 MidiMessage::ChannelPressure { channel, pressure } => {
88 write_channel_status(writer, CHANNEL_PRESSURE_STATUS, *channel)?;
89 write_data(writer, *pressure)?;
90 }
91 MidiMessage::PitchBendChange { channel, value } => {
92 write_channel_status(writer, PITCH_BEND_CHANGE_STATUS, *channel)?;
93 write_u14_data(writer, *value)?;
94 }
95 MidiMessage::TimeCodeQuarterFrame {
96 message_type,
97 value,
98 } => {
99 writer.write_sized(&TIME_CODE_QUARTER_FRAME_STATUS)?;
100 let message_type: u8 = (*message_type).into();
101 let value: u8 = (*value).into();
102 let byte: u8 = value + (message_type << 4);
103 writer.write_sized(&byte)?;
104 }
105 MidiMessage::SongPositionPointer { position } => {
106 writer.write_sized(&SONG_POSITION_POINTER_STATUS)?;
107 write_u14_data(writer, *position)?;
108 }
109 MidiMessage::SongSelect { song } => {
110 writer.write_sized(&SONG_SELECT_STATUS)?;
111 write_data(writer, *song)?;
112 }
113 MidiMessage::TuneRequest => {
114 writer.write_sized(&TUNE_REQUEST_STATUS)?;
115 }
116 MidiMessage::TimingClock => {
117 writer.write_sized(&TIMING_CLOCK_STATUS)?;
118 }
119 MidiMessage::Start => {
120 writer.write_sized(&START_STATUS)?;
121 }
122 MidiMessage::Continue => {
123 writer.write_sized(&CONTINUE_STATUS)?;
124 }
125 MidiMessage::Stop => {
126 writer.write_sized(&STOP_STATUS)?;
127 }
128 MidiMessage::ActiveSensing => {
129 writer.write_sized(&ACTIVE_SENSING_STATUS)?;
130 }
131 MidiMessage::SystemReset => {
132 writer.write_sized(&SYSTEM_RESET_STATUS)?;
133 }
134 }
135 Ok(())
136 }
137
138 fn create_ref<'b>(raw_data: &'b [u8]) -> Result<&'b Self, ()> {
139 if (raw_data.len() > 3) | (raw_data.len() == 0) {
141 return Err(());
142 }
143 if (raw_data[0] & 0b1000_0000) == 0 {
145 return Err(());
146 }
147 if (raw_data.len() >= 2) & (raw_data[1] & 0b1000_0000 != 0) {
149 return Err(());
150 }
151 if (raw_data.len() == 3) & (raw_data[2] & 0b1000_0000 != 0) {
153 return Err(());
154 }
155 let self_ptr = raw_data as *const [u8] as *const Self;
157 Ok(unsafe { self_ptr.as_ref() }.unwrap())
158 }
159}
160
161#[repr(C)]
162pub struct SystemExclusiveMessage([u8]);
171
172impl SystemExclusiveMessage {
173 pub fn get_data(&self) -> &[u8] {
175 assert!(self.0.len() >= 2);
176 let data = &self.0;
177 let len = data.len();
178 &data[1..len - 1]
179 }
180}
181
182impl<'a> AtomBody for SystemExclusiveMessage {
183 type InitializationParameter = [u8];
184
185 fn get_uri() -> &'static CStr {
186 unsafe { CStr::from_bytes_with_nul_unchecked(crate::uris::EVENT_URI) }
187 }
188
189 unsafe fn initialize_body<'b, W>(
190 writer: &mut W,
191 data: &[u8],
192 _urids: &mut CachedMap,
193 ) -> Result<(), ()>
194 where
195 W: WritingFrame<'b> + WritingFrameExt<'b, Self>,
196 {
197 writer.write_sized(&START_OF_SYSTEM_EXCLUSIVE_STATUS)?;
198 writer.write_raw(data)?;
199 writer.write_sized(&END_OF_SYSTEM_EXCLUSICE_STATUS)?;
200 Ok(())
201 }
202
203 fn create_ref<'b>(raw_data: &'b [u8]) -> Result<&'b Self, ()> {
204 let self_ptr = raw_data as *const [u8] as *const Self;
206 let self_ref = unsafe { self_ptr.as_ref() }.unwrap();
207
208 if self_ref.0.len() < 2 {
210 return Err(());
211 }
212
213 let first_byte: u8 = *self_ref.0.first().unwrap();
215 let last_byte: u8 = *self_ref.0.last().unwrap();
216 if (first_byte != START_OF_SYSTEM_EXCLUSIVE_STATUS)
217 | (last_byte != END_OF_SYSTEM_EXCLUSICE_STATUS)
218 {
219 return Err(());
220 }
221
222 for byte in &self_ref.0[1..self_ref.0.len() - 1] {
225 if (*byte & 0b1000_0000) != 0 {
226 return Err(());
227 }
228 }
229
230 Ok(self_ref)
231 }
232}
233
234unsafe fn write_channel_status<'a, W, A>(writer: &mut W, status: u8, channel: u4) -> Result<(), ()>
235where
236 W: WritingFrame<'a> + WritingFrameExt<'a, A>,
237 A: AtomBody + ?Sized,
238{
239 let channel: u8 = channel.into();
240 let status = status + channel;
241 writer.write_sized(&status).map(|_| ())
242}
243
244unsafe fn write_data<'a, W, A>(writer: &mut W, data: u7) -> Result<(), ()>
245where
246 W: WritingFrame<'a> + WritingFrameExt<'a, A>,
247 A: AtomBody + ?Sized,
248{
249 let data: u8 = data.into();
250 writer.write_sized(&data).map(|_| ())
251}
252
253unsafe fn write_u14_data<'a, W, A>(writer: &mut W, data: u14) -> Result<(), ()>
254where
255 W: WritingFrame<'a> + WritingFrameExt<'a, A>,
256 A: AtomBody + ?Sized,
257{
258 let data: u16 = data.into();
259 let msb: u8 = ((data & 0b0011_1111_1000_0000) >> 7) as u8;
260 let lsb: u8 = (data & 0b0000_0000_0111_1111) as u8;
261 writer.write_sized(&lsb)?;
262 writer.write_sized(&msb)?;
263 Ok(())
264}