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