From 2c0104b30ef8889008fc4fdcaabfafa7753f8b8e Mon Sep 17 00:00:00 2001 From: Benjamin Klum Date: Tue, 5 Nov 2024 21:50:32 +0100 Subject: [PATCH] #1308 Add source "ReaLearn compartment loaded" --- api/src/persistence/source.rs | 1 + main/src/application/source_model.rs | 23 ++++++++++++++++--- main/src/application/unit_model.rs | 6 +++++ main/src/domain/main_processor.rs | 8 +++++++ main/src/domain/mapping.rs | 3 ++- main/src/domain/reaper_source.rs | 17 ++++++++++++-- .../api/convert/from_data/source.rs | 1 + .../api/convert/to_data/source.rs | 10 +++++--- main/src/infrastructure/data/unit_data.rs | 2 ++ .../src/infrastructure/ui/stream_deck_tool.rs | 7 ++++-- 10 files changed, 67 insertions(+), 11 deletions(-) diff --git a/api/src/persistence/source.rs b/api/src/persistence/source.rs index 0b8a2c54b..3c2808ebf 100644 --- a/api/src/persistence/source.rs +++ b/api/src/persistence/source.rs @@ -14,6 +14,7 @@ pub enum Source { // REAPER MidiDeviceChanges, RealearnInstanceStart, + RealearnCompartmentLoaded, Timer(TimerSource), RealearnParameter(RealearnParameterSource), Speech, diff --git a/main/src/application/source_model.rs b/main/src/application/source_model.rs index 3dc36d6d9..9f8abda59 100644 --- a/main/src/application/source_model.rs +++ b/main/src/application/source_model.rs @@ -590,7 +590,11 @@ impl SourceModel { RealearnParameter(p) => { self.parameter_index = p.parameter_index; } - MidiDeviceChanges | RealearnInstanceStart | Timer(_) | Speech(_) => {} + MidiDeviceChanges + | RealearnInstanceStart + | RealearnCompartmentLoaded + | Timer(_) + | Speech(_) => {} } } StreamDeck(s) => { @@ -760,6 +764,7 @@ impl SourceModel { let reaper_source = match self.reaper_source_type { MidiDeviceChanges => ReaperSource::MidiDeviceChanges, RealearnUnitStart => ReaperSource::RealearnInstanceStart, + RealearnCompartmentLoaded => ReaperSource::RealearnCompartmentLoaded, Timer => ReaperSource::Timer(self.create_timer_source()), RealearnParameter => { ReaperSource::RealearnParameter(self.create_realearn_parameter_source()) @@ -1314,6 +1319,9 @@ pub enum ReaperSourceType { #[serde(rename = "realearn-instance-start")] #[display(fmt = "ReaLearn unit start")] RealearnUnitStart, + #[serde(rename = "realearn-compartment-loaded")] + #[display(fmt = "ReaLearn compartment loaded")] + RealearnCompartmentLoaded, #[serde(rename = "timer")] #[display(fmt = "Timer")] Timer, @@ -1331,6 +1339,7 @@ impl ReaperSourceType { match source { MidiDeviceChanges => Self::MidiDeviceChanges, RealearnInstanceStart => Self::RealearnUnitStart, + RealearnCompartmentLoaded => Self::RealearnCompartmentLoaded, Timer(_) => Self::Timer, RealearnParameter(_) => Self::RealearnParameter, Speech(_) => Self::Speech, @@ -1340,7 +1349,11 @@ impl ReaperSourceType { pub fn supports_control(self) -> bool { use ReaperSourceType::*; match self { - MidiDeviceChanges | RealearnUnitStart | Timer | RealearnParameter => true, + MidiDeviceChanges + | RealearnUnitStart + | RealearnCompartmentLoaded + | Timer + | RealearnParameter => true, Speech => false, } } @@ -1348,7 +1361,11 @@ impl ReaperSourceType { pub fn supports_feedback(self) -> bool { use ReaperSourceType::*; match self { - MidiDeviceChanges | RealearnUnitStart | Timer | RealearnParameter => false, + MidiDeviceChanges + | RealearnUnitStart + | RealearnCompartmentLoaded + | Timer + | RealearnParameter => false, Speech => true, } } diff --git a/main/src/application/unit_model.rs b/main/src/application/unit_model.rs index fa5ce0d6c..f904b43e7 100644 --- a/main/src/application/unit_model.rs +++ b/main/src/application/unit_model.rs @@ -2283,6 +2283,12 @@ impl UnitModel { } self.reset_parameters(compartment); self.notify_everything_has_changed(); + self.notify_compartment_loaded(compartment); + } + + pub fn notify_compartment_loaded(&self, compartment: CompartmentKind) { + self.normal_main_task_sender + .send_complaining(NormalMainTask::NotifyRealearnCompartmentLoaded(compartment)); } fn reset_parameters(&self, compartment: CompartmentKind) { diff --git a/main/src/domain/main_processor.rs b/main/src/domain/main_processor.rs index 437d3481c..dd0d9ac96 100644 --- a/main/src/domain/main_processor.rs +++ b/main/src/domain/main_processor.rs @@ -1242,6 +1242,12 @@ impl MainProcessor { let evt = ControlEvent::new(&ReaperMessage::RealearnUnitStarted, timestamp); self.process_reaper_message(evt); } + NotifyRealearnCompartmentLoaded(kind) => { + debug!("NotifyRealearnCompartmentLoaded received"); + let message = ReaperMessage::RealearnCompartmentLoaded(kind); + let evt = ControlEvent::new(&message, timestamp); + self.process_reaper_message(evt); + } HitTarget { id, value } => { self.hit_target(id, value); } @@ -2879,6 +2885,8 @@ pub enum NormalMainTask { }, /// Invokes the "ReaLearn instance started" source. NotifyRealearnUnitStarted, + /// Invokes the "ReaLearn compartment loaded" source. + NotifyRealearnCompartmentLoaded(CompartmentKind), /// Instructs the main processor to hit the target directly. /// /// This doesn't invoke group interaction because it's meant to totally skip the mode. diff --git a/main/src/domain/mapping.rs b/main/src/domain/mapping.rs index 26e0860c2..1b2c73395 100644 --- a/main/src/domain/mapping.rs +++ b/main/src/domain/mapping.rs @@ -1369,7 +1369,8 @@ impl<'a> MainSourceMessage<'a> { MidiDevicesConnected(_) | MidiDevicesDisconnected(_) | StreamDeckDevicesConnected(_) - | RealearnUnitStarted => return None, + | RealearnUnitStarted + | RealearnCompartmentLoaded(_) => return None, RealearnParameterChange(payload) => { MessageCaptureResult::RealearnParameter(*payload) } diff --git a/main/src/domain/reaper_source.rs b/main/src/domain/reaper_source.rs index 29ecb0fa4..cc99f1d12 100644 --- a/main/src/domain/reaper_source.rs +++ b/main/src/domain/reaper_source.rs @@ -18,6 +18,7 @@ use std::time::{Duration, Instant}; pub enum ReaperSource { MidiDeviceChanges, RealearnInstanceStart, + RealearnCompartmentLoaded, Timer(TimerSource), RealearnParameter(RealearnParameterSource), Speech(SpeechSource), @@ -150,6 +151,7 @@ impl ReaperSource { match self { MidiDeviceChanges => vec![DetailedSourceCharacter::MomentaryOnOffButton], RealearnInstanceStart => vec![DetailedSourceCharacter::MomentaryOnOffButton], + RealearnCompartmentLoaded => vec![DetailedSourceCharacter::Trigger], Timer(_) => vec![DetailedSourceCharacter::Trigger], RealearnParameter(_) => vec![ DetailedSourceCharacter::RangeControl, @@ -173,7 +175,7 @@ impl ReaperSource { pub fn character(&self) -> SourceCharacter { use ReaperSource::*; match self { - MidiDeviceChanges | RealearnInstanceStart | Timer(_) => { + MidiDeviceChanges | RealearnInstanceStart | RealearnCompartmentLoaded | Timer(_) => { SourceCharacter::MomentaryButton } RealearnParameter(_) => SourceCharacter::RangeElement, @@ -214,6 +216,12 @@ impl ReaperSource { } _ => return None, }, + RealearnCompartmentLoaded(kind) => match self { + ReaperSource::RealearnCompartmentLoaded if *kind == compartment => { + ControlValue::AbsoluteContinuous(UnitValue::MAX) + } + _ => return None, + }, RealearnParameterChange(c) => match self { ReaperSource::RealearnParameter(s) if c.compartment == compartment && c.parameter_index == s.parameter_index => @@ -229,7 +237,11 @@ impl ReaperSource { pub fn feedback(&self, feedback_value: &FeedbackValue) -> Option { use ReaperSource::*; match self { - MidiDeviceChanges | RealearnInstanceStart | Timer(_) | RealearnParameter(_) => None, + MidiDeviceChanges + | RealearnInstanceStart + | RealearnCompartmentLoaded + | Timer(_) + | RealearnParameter(_) => None, Speech(s) => Some(ReaperSourceFeedbackValue::Speech( s.feedback(feedback_value), )), @@ -262,6 +274,7 @@ pub enum ReaperMessage { #[display(fmt = "MidiDevicesDisconnected ({_0})")] MidiDevicesDisconnected(MidiDeviceChangePayload), RealearnUnitStarted, + RealearnCompartmentLoaded(CompartmentKind), RealearnParameterChange(RealearnParameterChangePayload), StreamDeckDevicesConnected(StreamDeckDevicePayload), } diff --git a/main/src/infrastructure/api/convert/from_data/source.rs b/main/src/infrastructure/api/convert/from_data/source.rs index 5a8b4e5b9..c24823689 100644 --- a/main/src/infrastructure/api/convert/from_data/source.rs +++ b/main/src/infrastructure/api/convert/from_data/source.rs @@ -235,6 +235,7 @@ pub fn convert_source( match data.reaper_source_type { MidiDeviceChanges => persistence::Source::MidiDeviceChanges, RealearnUnitStart => persistence::Source::RealearnInstanceStart, + RealearnCompartmentLoaded => persistence::Source::RealearnCompartmentLoaded, Timer => persistence::Source::Timer(persistence::TimerSource { duration: data.timer_millis, }), diff --git a/main/src/infrastructure/api/convert/to_data/source.rs b/main/src/infrastructure/api/convert/to_data/source.rs index 6826a742d..b2b57cbd7 100644 --- a/main/src/infrastructure/api/convert/to_data/source.rs +++ b/main/src/infrastructure/api/convert/to_data/source.rs @@ -146,6 +146,7 @@ pub fn convert_source(s: Source) -> ConversionResult { Source::RealearnInstanceStart => ReaperSourceType::RealearnUnitStart, Source::Timer(_) => ReaperSourceType::Timer, Source::RealearnParameter(_) => ReaperSourceType::RealearnParameter, + Source::RealearnCompartmentLoaded => ReaperSourceType::RealearnCompartmentLoaded, _ => Default::default(), }, timer_millis: match &s { @@ -166,9 +167,12 @@ fn convert_category(s: &Source) -> SourceCategory { use Source::*; match s { None => SourceCategory::Never, - MidiDeviceChanges | RealearnInstanceStart | Timer(_) | RealearnParameter(_) | Speech => { - SourceCategory::Reaper - } + MidiDeviceChanges + | RealearnInstanceStart + | RealearnCompartmentLoaded + | Timer(_) + | RealearnParameter(_) + | Speech => SourceCategory::Reaper, MidiNoteVelocity(_) | MidiNoteKeyNumber(_) | MidiPolyphonicKeyPressureAmount(_) diff --git a/main/src/infrastructure/data/unit_data.rs b/main/src/infrastructure/data/unit_data.rs index 61825796e..7110901f0 100644 --- a/main/src/infrastructure/data/unit_data.rs +++ b/main/src/infrastructure/data/unit_data.rs @@ -603,6 +603,8 @@ impl UnitData { } // Notify session.notify_everything_has_changed(); + session.notify_compartment_loaded(CompartmentKind::Main); + session.notify_compartment_loaded(CompartmentKind::Controller); Ok(()) } diff --git a/main/src/infrastructure/ui/stream_deck_tool.rs b/main/src/infrastructure/ui/stream_deck_tool.rs index a10367c09..8fac6320f 100644 --- a/main/src/infrastructure/ui/stream_deck_tool.rs +++ b/main/src/infrastructure/ui/stream_deck_tool.rs @@ -20,7 +20,6 @@ pub fn create_stream_deck_compartment_reflecting_toolbar( // Those don't ever send feedback because there's no current value, and as such there's also no feedback value // and the screen stays as it is. // TODO-high CONTINUE Toolbar images should be slided, not faded - // TODO-high CONTINUE "ReaLearn Unit Start" should be replaced with "ReaLearn Compartment load" let button_mappings = items.enumerate().map(|(i, item)| { let action = Reaper::get() .main_section() @@ -76,6 +75,7 @@ pub fn create_stream_deck_compartment_reflecting_toolbar( ..Default::default() }, ActionCharacter::Trigger => Glue { + // TODO-high CONTINUE This is obsolete for Trigger as soon as the feedback prob is solved button_filter: Some(ButtonFilter::PressOnly), ..Default::default() }, @@ -91,6 +91,9 @@ pub fn create_stream_deck_compartment_reflecting_toolbar( }; Some(cmd) }, + // TODO-high CONTINUE This should be Trigger for trigger-like actions, as soon as the feedback prob is solved + // TODO-high CONTINUE It might be a problem in general that non-trigger actions are not retriggerable. + // Because the value can't usually be relied on! Only in case of toggle actions. invocation: Some(ActionInvocationKind::Absolute7Bit), ..Default::default() }; @@ -104,7 +107,7 @@ pub fn create_stream_deck_compartment_reflecting_toolbar( }); let set_brightness_to_max_mapping = Mapping { name: Some("Set brightness to max".to_string()), - source: Some(Source::RealearnInstanceStart), + source: Some(Source::RealearnCompartmentLoaded), target: Some(Target::StreamDeckBrightness(Default::default())), ..Default::default() };