gled_model/asset/midi_controller/
control.rs1use serde::{Deserialize, Serialize};
7
8use super::MidiTrigger;
9
10#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
11pub struct MidiControl {
12 pub name: String,
13 pub trigger: MidiTrigger,
15}
16
17impl MidiTrigger {
18 pub fn matches(&self, status: u8, data1: u8) -> bool {
20 self.status == status && (!self.match_data1 || self.data1 == data1)
21 }
22
23 pub fn releases(&self, press: &MidiTrigger) -> bool {
27 let note_on = press.status & 0xF0 == 0x90;
28 let same_channel = self.status & 0x0F == press.status & 0x0F;
29 note_on && same_channel && self.status & 0xF0 == 0x80 && self.data1 == press.data1
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 fn trigger(status: u8, data1: u8, match_data1: bool) -> MidiTrigger {
38 MidiTrigger {
39 status,
40 data1,
41 match_data1,
42 }
43 }
44
45 #[test]
46 fn a_trigger_matches_its_message() {
47 assert!(trigger(0x90, 24, true).matches(0x90, 24));
48 assert!(!trigger(0x90, 24, true).matches(0x90, 25));
49 assert!(!trigger(0x90, 24, true).matches(0x91, 24));
50 }
51
52 #[test]
53 fn a_pitch_bend_trigger_matches_any_data1() {
54 assert!(trigger(0xE2, 0, false).matches(0xE2, 93));
55 }
56
57 #[test]
58 fn a_note_off_releases_the_note_on_of_its_note() {
59 let press = trigger(0x90, 8, true);
60 assert!(trigger(0x80, 8, true).releases(&press));
61 assert!(!trigger(0x80, 9, true).releases(&press));
62 assert!(!trigger(0x81, 8, true).releases(&press));
63 assert!(!trigger(0x80, 8, true).releases(&trigger(0xB0, 8, true)));
64 }
65}