1use super::{Button, Template};
2
3#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
4pub struct Knob(u8);
6
7impl Knob {
8 pub fn new(index: u8) -> Self {
11 assert!(index < 16);
12 Self(index)
13 }
14
15 pub fn upper(index: u8) -> Self {
17 Self::new(index)
18 }
19 pub fn lower(index: u8) -> Self {
21 Self::new(index + 8)
22 }
23}
24
25#[derive(Debug, Eq, PartialEq, Hash, Clone)]
26pub enum Message {
27 Press { template: Template, button: Button },
29
30 Release { template: Template, button: Button },
32
33 StalePadRelease,
38
39 StaleControlButtonRelease,
41
42 TemplateChanged { template: Template },
45
46 KnobChanged {
48 template: Template,
49 knob: Knob,
50 value: u8,
51 },
52}
53
54pub struct Input;
56
57impl Input {
58 fn decode_short_message(data: &[u8]) -> Message {
59 let status = data[0] & 0xF0;
60 let template = Template(data[0] & 0x0F);
61 let note = data[1];
62 let velocity = data[2];
63
64 match [status, note, velocity] {
69 [0x90, button @ 9..=12, 127] => Message::Press {
71 template,
72 button: Button::pad(button - 9),
73 },
74 [0x80, button @ 9..=12, 0] => Message::Release {
75 template,
76 button: Button::pad(button - 9),
77 },
78 [0x90, button @ 25..=28, 127] => Message::Press {
79 template,
80 button: Button::pad(button - 25 + 4),
81 },
82 [0x80, button @ 25..=28, 0] => Message::Release {
83 template,
84 button: Button::pad(button - 25 + 4),
85 },
86 [0x80, 0, 0] => Message::StalePadRelease,
87
88 [0xB0, button @ 114..=117, 127] => Message::Press {
90 template,
91 button: Button::control(button - 114),
92 },
93 [0xB0, button @ 114..=117, 0] => Message::Release {
94 template,
95 button: Button::control(button - 114),
96 },
97 [0xB0, 0, 0] => Message::StaleControlButtonRelease,
98
99 [0xB0, knob @ 21..=28, value] => Message::KnobChanged {
101 template,
102 knob: Knob::upper(knob - 21),
103 value,
104 },
105 [0xB0, knob @ 41..=48, value] => Message::KnobChanged {
106 template,
107 knob: Knob::lower(knob - 41),
108 value,
109 },
110
111 _ => panic!("Unexpected short message {:?}", data),
112 }
113 }
114
115 fn decode_sysex_message(data: &[u8]) -> Message {
116 match *data {
117 [240, 0, 32, 41, 2, 10, 119, template, 247] => Message::TemplateChanged {
118 template: Template(template),
119 },
120 _ => panic!("Unexpected sysex message {:?}", data),
121 }
122 }
123}
124
125impl crate::InputDevice for Input {
126 const MIDI_CONNECTION_NAME: &'static str = "Launchy Launch Control input";
127 const MIDI_DEVICE_KEYWORD: &'static str = "Launch Control";
128 type Message = Message;
129
130 fn decode_message(_timestamp: u64, data: &[u8]) -> Message {
131 match data.len() {
132 3 => Self::decode_short_message(data),
133 _ => Self::decode_sysex_message(data),
134 }
135 }
136}