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