use gled_model::asset::midi_controller::{
MidiControllerMapping, MidiOutputBinding, MidiValueSource,
};
use super::actions::rule_action;
use super::{Members, member_source, remove_bindings};
use crate::ui::windows::midi_controllers::rules::{
controls::Control,
feedback::{FeedbackRole, new_feedback, pad_target, source_for},
naming::name_rules_of,
sentence::Numbers,
};
pub(crate) fn set_source(
mapping: &mut MidiControllerMapping,
controls: &[Control],
members: &Members,
position: usize,
template: &MidiValueSource,
numbers: &dyn Numbers,
) {
for (rule, n) in members.each() {
let Some(&output) = rule.feedback.get(position) else {
continue;
};
if let Some(source) = mapping.output_bindings[output].kind.source_mut() {
*source = member_source(template, numbers, n);
}
}
name_rules_of(mapping, controls, &members.keys());
}
pub(crate) fn add_feedback(
mapping: &mut MidiControllerMapping,
controls: &[Control],
members: &Members,
role: FeedbackRole,
mapping_name: &str,
) -> bool {
let mut all = true;
let mut added = Vec::new();
for rule in &members.rules {
let action = rule_action(mapping, rule);
let source = source_for(role, action).unwrap_or(MidiValueSource::SelectedSceneOpacity);
let target = pad_target(action);
let kind = new_feedback(&controls[rule.control], role, source, target, mapping_name);
if role != FeedbackRole::PadColor && source_for(role, action).is_none() {
all = false;
}
added.push(MidiOutputBinding {
name: String::new(),
kind,
mode: rule.mode,
});
}
mapping.output_bindings.extend(added);
name_rules_of(mapping, controls, &members.keys());
all
}
pub(crate) fn remove_feedback(
mapping: &mut MidiControllerMapping,
members: &Members,
position: usize,
) {
let outputs = members
.rules
.iter()
.filter_map(|rule| rule.feedback.get(position).copied())
.collect();
remove_bindings(mapping, Vec::new(), outputs);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ui::windows::midi_controllers::rules::{
build::build_rules, controls::controls_of, sentence::Plain, test_mappings::p1x,
};
use gled_model::asset::midi_controller::MidiOutputBindingKind;
#[test]
fn a_meter_can_show_the_main_dimmer() {
let mut mapping = p1x();
let controls = controls_of(&mapping);
let rules = build_rules(&mapping, &controls);
let fader = rules
.iter()
.find(|rule| controls[rule.control].name == "Fader 8" && rule.mode == Some(0))
.cloned()
.unwrap_or_else(|| panic!("no Fader 8"));
let meter = fader
.feedback
.iter()
.position(|&output| {
matches!(
mapping.output_bindings[output].kind,
MidiOutputBindingKind::Meter(_)
)
})
.unwrap_or_else(|| panic!("no meter"));
set_source(
&mut mapping,
&controls,
&Members::single(fader.clone()),
meter,
&MidiValueSource::MainDimmer,
&Plain,
);
let output = &mapping.output_bindings[fader.feedback[meter]];
assert_eq!(output.kind.source(), Some(&MidiValueSource::MainDimmer));
assert_eq!(output.name, "Fader 8 meter: the main dimmer");
}
}