1use crate::launchkey::bitmap::LaunchkeyBitmap;
2use crate::launchkey::colors::{Color, ColorPaletteIndex};
3use crate::launchkey::constants::{
4 LaunchKeySku, BITMAP_HEADER_BYTE, BUTTON_BRIGHTNESS_OVERRIDE_CHANNEL, CC_CH7,
5 CONFIGURE_DISPLAY_COMMAND, CUSTOM_COLOR_COMMAND, DISABLE_DRUM_DAW_MODE, ENABLE_DRUM_DAW_MODE,
6 ENCODER_MODE_CC, FADER_MODE_CC, PAD_MODE_CC, SET_SCREEN_TEXT_COMMAND, SYSEX_TERMINATOR,
7};
8use crate::launchkey::modes::encoder_mode::EncoderMode;
9use crate::launchkey::modes::fader_mode::FaderMode;
10use crate::launchkey::modes::pad_mode::PadMode;
11use crate::launchkey::surface::buttons::{Brightness, LaunchKeyButton};
12use crate::launchkey::surface::display::{
13 Arrangement, ContextualDisplayTarget, DisplayConfig, DisplayTarget, GlobalDisplayTarget,
14};
15use crate::launchkey::surface::pads::{LEDMode, PadInMode};
16use std::ops::Deref;
17
18#[derive(Debug, Clone)]
21pub enum LaunchkeyCommand {
22 SetDrumDAWMode(bool),
23 SetPadMode(PadMode),
24 SetEncoderMode(EncoderMode),
25 SetFaderMode(FaderMode),
26 SetButtonBrightness {
27 launch_key_button: LaunchKeyButton,
28 brightness: Brightness,
29 },
30 SetPadColor {
31 pad_in_mode: PadInMode,
32 mode: LEDMode,
33 color_palette_index: ColorPaletteIndex,
34 },
35 SetPadCustomColor {
36 pad_in_mode: PadInMode,
37 color: Color,
38 },
39 SetScreenTextGlobal {
40 target: GlobalDisplayTarget,
41 arrangement: Arrangement,
42 },
43 SetScreenTextContextual {
44 target: ContextualDisplayTarget,
45 text: String,
46 },
47 SendScreenBitmap {
48 target: GlobalDisplayTarget,
49 bitmap: Box<LaunchkeyBitmap>,
50 },
51}
52
53impl LaunchkeyCommand {
54 pub(crate) fn as_bytes(&self, sku: &LaunchKeySku) -> Vec<u8> {
56 let header = sku.sys_ex_header();
57 match self {
58 LaunchkeyCommand::SetDrumDAWMode(enable) => {
59 if *enable {
60 ENABLE_DRUM_DAW_MODE.into()
61 } else {
62 DISABLE_DRUM_DAW_MODE.into()
63 }
64 }
65 LaunchkeyCommand::SetPadMode(mode) => vec![CC_CH7, PAD_MODE_CC, mode.to_value()],
66 LaunchkeyCommand::SetEncoderMode(mode) => {
67 vec![CC_CH7, ENCODER_MODE_CC, mode.to_value()]
68 }
69 LaunchkeyCommand::SetFaderMode(mode) => vec![CC_CH7, FADER_MODE_CC, mode.to_value()],
70 LaunchkeyCommand::SetButtonBrightness {
71 launch_key_button,
72 brightness,
73 } => {
74 vec![
75 BUTTON_BRIGHTNESS_OVERRIDE_CHANNEL,
76 (*launch_key_button).to_value(),
77 brightness.value(),
78 ]
79 }
80 LaunchkeyCommand::SetPadColor {
82 pad_in_mode,
83 mode,
84 color_palette_index,
85 } => {
86 let channel = mode.to_midi_channel(*pad_in_mode);
87 vec![
88 channel,
89 (*pad_in_mode).to_index(),
90 color_palette_index.as_u8(),
91 ]
92 }
93 LaunchkeyCommand::SetPadCustomColor { pad_in_mode, color } => {
94 let mut data = header.to_vec();
95 data.extend_from_slice(&[
96 CUSTOM_COLOR_COMMAND.0,
97 CUSTOM_COLOR_COMMAND.1,
98 (*pad_in_mode).to_index(),
99 color.r.into(),
100 color.g.into(),
101 color.b.into(),
102 ]);
103 data.push(SYSEX_TERMINATOR);
104 data
105 }
106
107 LaunchkeyCommand::SetScreenTextGlobal {
109 target,
110 arrangement,
111 } => {
112 let mut data: Vec<u8> = Vec::new();
113 data.extend(self.configure_display(
115 (*target).into(),
116 DisplayConfig::Arrangement(arrangement.clone()),
117 sku,
118 ));
119
120 match arrangement {
122 Arrangement::NameValue(name, value) => {
123 data.extend(self.set_screen_text(
124 (*target).into(),
125 0,
126 name.to_string(),
127 sku,
128 ));
129 data.extend(self.set_screen_text(
130 (*target).into(),
131 1,
132 value.to_string(),
133 sku,
134 ));
135 }
136 Arrangement::TitleNameValue(title, name, value) => {
137 data.extend(self.set_screen_text(
138 (*target).into(),
139 0,
140 title.to_string(),
141 sku,
142 ));
143 data.extend(self.set_screen_text(
144 (*target).into(),
145 1,
146 name.to_string(),
147 sku,
148 ));
149 data.extend(self.set_screen_text(
150 (*target).into(),
151 2,
152 value.to_string(),
153 sku,
154 ));
155 }
156 Arrangement::TitleEightNames(title, names) => {
157 data.extend(self.set_screen_text(
158 (*target).into(),
159 0,
160 title.to_string(),
161 sku,
162 ));
163 for (i, name) in names.iter().enumerate() {
164 data.extend(self.set_screen_text(
165 (*target).into(),
166 (i + 1) as u8,
167 name.to_string(),
168 sku,
169 ));
170 }
171 }
172 Arrangement::NameNumericValue(name) => {
173 data.extend(self.set_screen_text(
174 (*target).into(),
175 0,
176 name.to_string(),
177 sku,
178 ));
179 }
180 }
181
182 data.extend(self.configure_display((*target).into(), DisplayConfig::Trigger, sku));
184
185 data
186 }
187 LaunchkeyCommand::SetScreenTextContextual { target, text } => {
188 self.set_screen_text((*target).into(), 0, text.to_string(), sku)
189 }
190 LaunchkeyCommand::SendScreenBitmap { target, bitmap } => {
191 let mut data = header.to_vec();
192 data.extend_from_slice(&[BITMAP_HEADER_BYTE, (*target).into()]);
193 data.extend_from_slice(bitmap.deref().as_ref());
194 data.push(SYSEX_TERMINATOR);
195 data
196 }
197 }
198 }
199
200 fn configure_display(
202 &self,
203 target: DisplayTarget,
204 config: DisplayConfig,
205 sku: &LaunchKeySku,
206 ) -> Vec<u8> {
207 let mut data = sku.sys_ex_header().to_vec();
208 data.extend_from_slice(&[
209 CONFIGURE_DISPLAY_COMMAND,
210 target.into(),
211 config.clone().into(),
212 ]);
213 data.push(SYSEX_TERMINATOR);
214 data
215 }
216
217 fn set_screen_text(
219 &self,
220 target: DisplayTarget,
221 field: u8,
222 text: String,
223 sku: &LaunchKeySku,
224 ) -> Vec<u8> {
225 let mut data = sku.sys_ex_header().to_vec();
226 data.extend_from_slice(&[SET_SCREEN_TEXT_COMMAND, target.into(), field]);
227 data.extend(text.as_bytes());
228 data.push(SYSEX_TERMINATOR);
229 data
230 }
231}