1use super::{MidiEffectTarget, MidiSceneTarget};
5use serde::{Deserialize, Serialize};
6use strum::{Display, EnumDiscriminants, EnumIter};
7
8use crate::asset::scene::color::SceneInstanceColor;
9
10#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
11pub struct MidiOutputBinding {
12 pub name: String,
13 pub kind: MidiOutputBindingKind,
14 #[serde(default)]
16 pub mode: Option<u8>,
17}
18
19impl Default for MidiOutputBinding {
20 fn default() -> Self {
21 Self {
22 name: "Output".to_owned(),
23 kind: MidiOutputBindingKind::Value(MidiValueOutput::default()),
24 mode: None,
25 }
26 }
27}
28
29#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, EnumDiscriminants)]
32#[strum_discriminants(name(MidiOutputBindingSelector), derive(Display, EnumIter))]
33pub enum MidiOutputBindingKind {
34 #[strum_discriminants(strum(serialize = "Single Value"))]
35 Value(MidiValueOutput),
36 #[strum_discriminants(strum(serialize = "Scene Color Mapping"))]
37 SceneColorValue(MidiSceneColorValueOutput),
38 #[strum_discriminants(strum(serialize = "Mackie Meter"))]
40 Meter(MidiMeterOutput),
41}
42
43#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
47pub struct MidiMeterOutput {
48 pub strip: u8,
50 pub source: MidiValueSource,
51}
52
53impl MidiMeterOutput {
54 const MAX_LEVEL: u8 = 12;
56
57 pub fn message(&self, value: f32) -> [u8; 2] {
59 let level = (value.clamp(0.0, 1.0) * f32::from(Self::MAX_LEVEL)).round() as u8;
60 [0xD0, ((self.strip & 0x07) << 4) | level]
61 }
62}
63
64#[derive(
66 Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy, Hash, Default, Display, EnumIter,
67)]
68pub enum MidiEffectParameter {
69 #[default]
70 Opacity,
71 #[strum(serialize = "Beat Progression")]
72 BeatProgression,
73 #[strum(serialize = "Color Shift")]
74 ColorShift,
75 #[strum(serialize = "Beat Offset")]
76 BeatOffset,
77 #[strum(serialize = "Setting 1")]
78 Setting0,
79 #[strum(serialize = "Setting 2")]
80 Setting1,
81 #[strum(serialize = "Setting 3")]
82 Setting2,
83 #[strum(serialize = "Setting 4")]
84 Setting3,
85 #[strum(serialize = "Setting 5")]
86 Setting4,
87 #[strum(serialize = "Setting 6")]
88 Setting5,
89}
90
91impl MidiOutputBindingKind {
92 pub fn source(&self) -> Option<&MidiValueSource> {
94 match self {
95 Self::Value(output) => Some(&output.source),
96 Self::Meter(meter) => Some(&meter.source),
97 Self::SceneColorValue(_) => None,
98 }
99 }
100
101 pub fn source_mut(&mut self) -> Option<&mut MidiValueSource> {
102 match self {
103 Self::Value(output) => Some(&mut output.source),
104 Self::Meter(meter) => Some(&mut meter.source),
105 Self::SceneColorValue(_) => None,
106 }
107 }
108}
109
110impl MidiEffectParameter {
111 pub fn setting(index: u8) -> Option<Self> {
113 Some(match index {
114 0 => Self::Setting0,
115 1 => Self::Setting1,
116 2 => Self::Setting2,
117 3 => Self::Setting3,
118 4 => Self::Setting4,
119 5 => Self::Setting5,
120 _ => return None,
121 })
122 }
123}
124
125impl Default for MidiOutputBindingKind {
126 fn default() -> Self {
127 Self::Value(MidiValueOutput::default())
128 }
129}
130
131#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
132pub struct MidiValueOutput {
133 pub status: u8,
134 pub data1: u8,
135 pub min: u8,
136 pub max: u8,
137 pub active_value: u8,
138 pub source: MidiValueSource,
139}
140
141impl Default for MidiValueOutput {
142 fn default() -> Self {
143 Self {
144 status: 176,
145 data1: 0,
146 min: 0,
147 max: 127,
148 active_value: 127,
149 source: MidiValueSource::SelectedSceneOpacity,
150 }
151 }
152}
153
154#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Default, EnumDiscriminants)]
157#[strum_discriminants(
158 name(MidiValueSourceKind),
159 derive(Display, EnumIter),
160 strum(serialize_all = "title_case")
161)]
162pub enum MidiValueSource {
163 #[default]
164 SelectedSceneOpacity,
165 #[strum_discriminants(strum(serialize = "Selected Scene (Distributed 0-127)"))]
166 SelectedSceneDistributed,
167 #[strum_discriminants(strum(serialize = "Selected Effect (Distributed 0-127)"))]
170 SelectedEffectDistributed,
171 #[strum_discriminants(strum(serialize = "Selected Scene Opacity Live"))]
174 SelectedSceneOpacityLive,
175 #[strum_discriminants(strum(serialize = "Effect Live Value"))]
178 SelectedSceneEffectLive {
179 effect: MidiEffectTarget,
180 parameter: MidiEffectParameter,
181 },
182 #[strum_discriminants(strum(serialize = "Effect Selected"))]
185 EffectSelected {
186 index: u8,
187 },
188 SelectedSceneInputDimmer,
189 SelectedSceneBeatOffset,
190 SelectedSceneIgnoreMainDimmer,
191 SelectedSceneSetOffsetOnFlash,
192 MainDimmer,
193 #[strum_discriminants(strum(serialize = "Beat Flank"))]
194 BeatFlankPulse {
195 start_beat: f32,
196 end_beat: f32,
197 blackout_blink_value: Option<u8>,
198 },
199 Blackout {
200 inverted: bool,
201 blink: bool,
202 },
203 SceneOpacity {
204 target: MidiSceneTarget,
205 },
206 SceneInputDimmer {
207 target: MidiSceneTarget,
208 },
209 SceneBeatOffset {
210 target: MidiSceneTarget,
211 },
212 SceneIgnoreMainDimmer {
213 target: MidiSceneTarget,
214 },
215 SceneSetOffsetOnFlash {
216 target: MidiSceneTarget,
217 },
218 SceneActive {
219 target: MidiSceneTarget,
220 },
221 SceneFlashed {
222 target: MidiSceneTarget,
223 },
224 SceneSelected {
226 target: MidiSceneTarget,
227 },
228 ModeActive {
230 mode: u8,
231 },
232 #[strum_discriminants(strum(serialize = "Scene Effect Setting (n,n) f32"))]
233 SceneEffectSettingF32 {
234 target: MidiSceneTarget,
235 #[serde(rename = "effect_index")]
236 effect: MidiEffectTarget,
237 setting_index: u8,
238 },
239 #[strum_discriminants(strum(serialize = "Effect Opacity"))]
240 SceneEffectOpacity {
241 target: MidiSceneTarget,
242 #[serde(rename = "effect_index")]
243 effect: MidiEffectTarget,
244 },
245 #[strum_discriminants(strum(serialize = "Effect Color Shift"))]
246 SceneEffectColorShift {
247 target: MidiSceneTarget,
248 #[serde(rename = "effect_index")]
249 effect: MidiEffectTarget,
250 },
251 #[strum_discriminants(strum(serialize = "Effect Beat Progression"))]
252 SceneEffectBeatProgression {
253 target: MidiSceneTarget,
254 #[serde(rename = "effect_index")]
255 effect: MidiEffectTarget,
256 },
257 #[strum_discriminants(strum(serialize = "Effect Beat Offset"))]
258 SceneEffectBeatOffset {
259 target: MidiSceneTarget,
260 #[serde(rename = "effect_index")]
261 effect: MidiEffectTarget,
262 },
263 #[strum_discriminants(strum(serialize = "Effect Speed Exponent"))]
264 SceneEffectSpeedExponent {
265 target: MidiSceneTarget,
266 #[serde(rename = "effect_index")]
267 effect: MidiEffectTarget,
268 },
269 #[serde(alias = "SceneEffectGroupIndex")]
273 #[strum_discriminants(strum(serialize = "Effect Layout"))]
274 SceneEffectLayout {
275 target: MidiSceneTarget,
276 #[serde(rename = "effect_index")]
277 effect: MidiEffectTarget,
278 },
279}
280
281impl Eq for MidiValueSource {}
282
283#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Display)]
284pub enum MidiColorSource {
285 #[strum(serialize = "Scene Color")]
286 SceneColor { target: MidiSceneTarget },
287}
288
289impl Default for MidiColorSource {
290 fn default() -> Self {
291 Self::SceneColor {
292 target: MidiSceneTarget::Selected,
293 }
294 }
295}
296
297#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
298pub struct MidiSceneColorValueOutput {
299 pub source: MidiColorSource,
300 pub mapping_name: String,
301 pub status: u8,
302 pub data1: u8,
303}
304
305impl Default for MidiSceneColorValueOutput {
306 fn default() -> Self {
307 Self {
308 source: MidiColorSource::default(),
309 mapping_name: String::new(),
310 status: 144,
311 data1: 0,
312 }
313 }
314}
315
316#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
317pub struct MidiNamedSceneColorMapping {
318 pub name: String,
319 pub active: MidiSceneColorMessageMap,
320 pub inactive: MidiSceneColorMessageMap,
321 pub flashed: MidiSceneColorMessageMap,
322}
323
324impl Default for MidiNamedSceneColorMapping {
325 fn default() -> Self {
326 let default_map = MidiSceneColorMessageMap::default();
327 Self {
328 name: "Color Mapping".to_owned(),
329 active: default_map.clone(),
330 inactive: default_map.clone(),
331 flashed: default_map,
332 }
333 }
334}
335
336#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
337pub struct MidiSceneColorMessage {
338 pub value: u8,
339}
340
341#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
342pub struct MidiSceneColorMessageMap {
343 pub red: MidiSceneColorMessage,
344 pub green: MidiSceneColorMessage,
345 pub blue: MidiSceneColorMessage,
346 pub white: MidiSceneColorMessage,
347 pub orange: MidiSceneColorMessage,
348 pub yellow: MidiSceneColorMessage,
349 pub purple: MidiSceneColorMessage,
350 pub pink: MidiSceneColorMessage,
351 pub black: MidiSceneColorMessage,
352}
353
354impl Default for MidiSceneColorMessageMap {
355 fn default() -> Self {
356 Self {
357 red: MidiSceneColorMessage { value: 5 },
358 green: MidiSceneColorMessage { value: 21 },
359 blue: MidiSceneColorMessage { value: 45 },
360 white: MidiSceneColorMessage { value: 3 },
361 orange: MidiSceneColorMessage { value: 9 },
362 yellow: MidiSceneColorMessage { value: 13 },
363 purple: MidiSceneColorMessage { value: 49 },
364 pink: MidiSceneColorMessage { value: 53 },
365 black: MidiSceneColorMessage { value: 0 },
366 }
367 }
368}
369
370impl MidiSceneColorMessageMap {
371 pub fn message_for_color(&self, color: SceneInstanceColor) -> &MidiSceneColorMessage {
372 match color {
373 SceneInstanceColor::Red => &self.red,
374 SceneInstanceColor::Green => &self.green,
375 SceneInstanceColor::Blue => &self.blue,
376 SceneInstanceColor::White => &self.white,
377 SceneInstanceColor::Orange => &self.orange,
378 SceneInstanceColor::Yellow => &self.yellow,
379 SceneInstanceColor::Purple => &self.purple,
380 SceneInstanceColor::Pink => &self.pink,
381 SceneInstanceColor::Black => &self.black,
382 }
383 }
384}