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 {
197 start_beat: f32,
198 end_beat: f32,
199 blackout_blink_value: Option<u8>,
200 #[serde(default)]
201 every_beat: bool,
202 },
203 Blackout {
204 inverted: bool,
205 blink: bool,
206 },
207 SceneOpacity {
208 target: MidiSceneTarget,
209 },
210 SceneOpacityLive {
213 target: MidiSceneTarget,
214 },
215 SceneInputDimmer {
216 target: MidiSceneTarget,
217 },
218 SceneBeatOffset {
219 target: MidiSceneTarget,
220 },
221 SceneIgnoreMainDimmer {
222 target: MidiSceneTarget,
223 },
224 SceneSetOffsetOnFlash {
225 target: MidiSceneTarget,
226 },
227 SceneActive {
228 target: MidiSceneTarget,
229 },
230 SceneFlashed {
231 target: MidiSceneTarget,
232 },
233 SceneSelected {
235 target: MidiSceneTarget,
236 },
237 ModeActive {
239 mode: u8,
240 },
241 #[strum_discriminants(strum(serialize = "Scene Effect Setting (n,n) f32"))]
242 SceneEffectSettingF32 {
243 target: MidiSceneTarget,
244 #[serde(rename = "effect_index")]
245 effect: MidiEffectTarget,
246 setting_index: u8,
247 },
248 #[strum_discriminants(strum(serialize = "Effect Opacity"))]
249 SceneEffectOpacity {
250 target: MidiSceneTarget,
251 #[serde(rename = "effect_index")]
252 effect: MidiEffectTarget,
253 },
254 #[strum_discriminants(strum(serialize = "Effect Color Shift"))]
255 SceneEffectColorShift {
256 target: MidiSceneTarget,
257 #[serde(rename = "effect_index")]
258 effect: MidiEffectTarget,
259 },
260 #[strum_discriminants(strum(serialize = "Effect Beat Progression"))]
261 SceneEffectBeatProgression {
262 target: MidiSceneTarget,
263 #[serde(rename = "effect_index")]
264 effect: MidiEffectTarget,
265 },
266 #[strum_discriminants(strum(serialize = "Effect Beat Offset"))]
267 SceneEffectBeatOffset {
268 target: MidiSceneTarget,
269 #[serde(rename = "effect_index")]
270 effect: MidiEffectTarget,
271 },
272 #[strum_discriminants(strum(serialize = "Effect Speed Exponent"))]
273 SceneEffectSpeedExponent {
274 target: MidiSceneTarget,
275 #[serde(rename = "effect_index")]
276 effect: MidiEffectTarget,
277 },
278 #[serde(alias = "SceneEffectGroupIndex")]
282 #[strum_discriminants(strum(serialize = "Effect Layout"))]
283 SceneEffectLayout {
284 target: MidiSceneTarget,
285 #[serde(rename = "effect_index")]
286 effect: MidiEffectTarget,
287 },
288}
289
290impl Eq for MidiValueSource {}
291
292#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Display)]
293pub enum MidiColorSource {
294 #[strum(serialize = "Scene Color")]
295 SceneColor { target: MidiSceneTarget },
296}
297
298impl Default for MidiColorSource {
299 fn default() -> Self {
300 Self::SceneColor {
301 target: MidiSceneTarget::Selected,
302 }
303 }
304}
305
306#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
307pub struct MidiSceneColorValueOutput {
308 pub source: MidiColorSource,
309 pub mapping_name: String,
310 pub status: u8,
311 pub data1: u8,
312}
313
314impl Default for MidiSceneColorValueOutput {
315 fn default() -> Self {
316 Self {
317 source: MidiColorSource::default(),
318 mapping_name: String::new(),
319 status: 144,
320 data1: 0,
321 }
322 }
323}
324
325#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
326pub struct MidiNamedSceneColorMapping {
327 pub name: String,
328 pub active: MidiSceneColorMessageMap,
329 pub inactive: MidiSceneColorMessageMap,
330 pub flashed: MidiSceneColorMessageMap,
331}
332
333impl Default for MidiNamedSceneColorMapping {
334 fn default() -> Self {
335 let default_map = MidiSceneColorMessageMap::default();
336 Self {
337 name: "Color Mapping".to_owned(),
338 active: default_map.clone(),
339 inactive: default_map.clone(),
340 flashed: default_map,
341 }
342 }
343}
344
345#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
346pub struct MidiSceneColorMessage {
347 pub value: u8,
348}
349
350#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
351pub struct MidiSceneColorMessageMap {
352 pub red: MidiSceneColorMessage,
353 pub green: MidiSceneColorMessage,
354 pub blue: MidiSceneColorMessage,
355 pub white: MidiSceneColorMessage,
356 pub orange: MidiSceneColorMessage,
357 pub yellow: MidiSceneColorMessage,
358 pub purple: MidiSceneColorMessage,
359 pub pink: MidiSceneColorMessage,
360 pub black: MidiSceneColorMessage,
361}
362
363impl Default for MidiSceneColorMessageMap {
364 fn default() -> Self {
365 Self {
366 red: MidiSceneColorMessage { value: 5 },
367 green: MidiSceneColorMessage { value: 21 },
368 blue: MidiSceneColorMessage { value: 45 },
369 white: MidiSceneColorMessage { value: 3 },
370 orange: MidiSceneColorMessage { value: 9 },
371 yellow: MidiSceneColorMessage { value: 13 },
372 purple: MidiSceneColorMessage { value: 49 },
373 pink: MidiSceneColorMessage { value: 53 },
374 black: MidiSceneColorMessage { value: 0 },
375 }
376 }
377}
378
379impl MidiSceneColorMessageMap {
380 pub fn message_for_color(&self, color: SceneInstanceColor) -> &MidiSceneColorMessage {
381 match color {
382 SceneInstanceColor::Red => &self.red,
383 SceneInstanceColor::Green => &self.green,
384 SceneInstanceColor::Blue => &self.blue,
385 SceneInstanceColor::White => &self.white,
386 SceneInstanceColor::Orange => &self.orange,
387 SceneInstanceColor::Yellow => &self.yellow,
388 SceneInstanceColor::Purple => &self.purple,
389 SceneInstanceColor::Pink => &self.pink,
390 SceneInstanceColor::Black => &self.black,
391 }
392 }
393}