From c6e8c67ce2c9d2e807d34e1ac1698f90689e2de4 Mon Sep 17 00:00:00 2001 From: Benjamin Klum Date: Tue, 13 Sep 2022 13:10:08 +0200 Subject: [PATCH] #660 Almost finish implementing X-Touch Mackie LCD color feedback --- main/lib/helgoboss-learn | 2 +- main/src/application/session.rs | 14 +-- main/src/domain/control_surface.rs | 14 +-- main/src/domain/feedback_collector.rs | 118 ++++++++++++++++++ main/src/domain/main_processor.rs | 78 +++++++----- main/src/domain/mapping.rs | 54 ++++---- main/src/domain/mod.rs | 3 + main/src/domain/realearn_source_context.rs | 6 +- main/src/infrastructure/test/mod.rs | 14 +-- .../ui/sound_util [conflicted].rs | 16 --- 10 files changed, 226 insertions(+), 93 deletions(-) create mode 100644 main/src/domain/feedback_collector.rs delete mode 100644 main/src/infrastructure/ui/sound_util [conflicted].rs diff --git a/main/lib/helgoboss-learn b/main/lib/helgoboss-learn index 4e51c8911..1233b2068 160000 --- a/main/lib/helgoboss-learn +++ b/main/lib/helgoboss-learn @@ -1 +1 @@ -Subproject commit 4e51c891132a5233fdd1c2bcb65604f02c7d9095 +Subproject commit 1233b2068a223499bca6e395802a6c2b06a4db4a diff --git a/main/src/application/session.rs b/main/src/application/session.rs index 797693eb4..07b37fbe3 100644 --- a/main/src/application/session.rs +++ b/main/src/application/session.rs @@ -13,12 +13,12 @@ use crate::domain::{ convert_plugin_param_index_range_to_iter, BackboneState, BasicSettings, Compartment, CompartmentParamIndex, CompartmentParams, CompoundMappingSource, ControlContext, ControlInput, DomainEvent, DomainEventHandler, ExtendedProcessorContext, FeedbackAudioHookTask, - FeedbackOutput, FeedbackRealTimeTask, GroupId, GroupKey, IncomingCompoundSourceValue, - InputDescriptor, InstanceContainer, InstanceId, InstanceState, MainMapping, MappingId, - MappingKey, MappingMatchedEvent, MessageCaptureEvent, MidiControlInput, NormalMainTask, - NormalRealTimeTask, OscFeedbackTask, ParamSetting, PluginParams, ProcessorContext, - ProjectionFeedbackValue, QualifiedMappingId, RealearnClipMatrix, RealearnTarget, ReaperTarget, - SharedInstanceState, SourceFeedbackValue, StayActiveWhenProjectInBackground, Tag, + FeedbackOutput, FeedbackRealTimeTask, FinalSourceFeedbackValue, GroupId, GroupKey, + IncomingCompoundSourceValue, InputDescriptor, InstanceContainer, InstanceId, InstanceState, + MainMapping, MappingId, MappingKey, MappingMatchedEvent, MessageCaptureEvent, MidiControlInput, + NormalMainTask, NormalRealTimeTask, OscFeedbackTask, ParamSetting, PluginParams, + ProcessorContext, ProjectionFeedbackValue, QualifiedMappingId, RealearnClipMatrix, + RealearnTarget, ReaperTarget, SharedInstanceState, StayActiveWhenProjectInBackground, Tag, TargetValueChangedEvent, VirtualControlElementId, VirtualFx, VirtualSource, VirtualSourceValue, }; use derivative::Derivative; @@ -2196,7 +2196,7 @@ impl Session { /// Good for checking produced feedback when doing integration testing. pub fn use_integration_test_feedback_sender( &self, - sender: SenderToNormalThread, + sender: SenderToNormalThread, ) { self.normal_main_task_sender .send_complaining(NormalMainTask::UseIntegrationTestFeedbackSender(sender)); diff --git a/main/src/domain/control_surface.rs b/main/src/domain/control_surface.rs index d01fdd197..2068969d8 100644 --- a/main/src/domain/control_surface.rs +++ b/main/src/domain/control_surface.rs @@ -2,12 +2,12 @@ use crate::base::{Global, NamedChannelSender, SenderToNormalThread}; use crate::domain::{ BackboneState, CompoundMappingSource, ControlEvent, ControlEventTimestamp, DeviceChangeDetector, DeviceControlInput, DeviceFeedbackOutput, DomainEventHandler, - EelTransformation, FeedbackOutput, FeedbackRealTimeTask, InstanceId, LifecycleMidiData, - MainProcessor, MidiCaptureSender, MidiDeviceChangePayload, NormalRealTimeTask, OscDeviceId, - OscInputDevice, OscScanResult, QualifiedClipMatrixEvent, RealTimeCompoundMappingTarget, - RealTimeMapping, RealTimeMappingUpdate, RealTimeTargetUpdate, ReaperConfigChangeDetector, - ReaperMessage, ReaperTarget, SharedMainProcessors, SharedRealTimeProcessor, - SourceFeedbackValue, TouchedTrackParameterType, + EelTransformation, FeedbackOutput, FeedbackRealTimeTask, FinalSourceFeedbackValue, InstanceId, + LifecycleMidiData, MainProcessor, MidiCaptureSender, MidiDeviceChangePayload, + NormalRealTimeTask, OscDeviceId, OscInputDevice, OscScanResult, QualifiedClipMatrixEvent, + RealTimeCompoundMappingTarget, RealTimeMapping, RealTimeMappingUpdate, RealTimeTargetUpdate, + ReaperConfigChangeDetector, ReaperMessage, ReaperTarget, SharedMainProcessors, + SharedRealTimeProcessor, TouchedTrackParameterType, }; use crossbeam_channel::Receiver; use helgoboss_learn::{AbstractTimestamp, ModeGarbage, RawMidiEvents}; @@ -149,7 +149,7 @@ pub struct IoUpdatedEvent { pub struct SourceReleasedEvent { pub instance_id: InstanceId, pub feedback_output: FeedbackOutput, - pub feedback_value: SourceFeedbackValue, + pub feedback_value: FinalSourceFeedbackValue, } #[derive(Debug)] diff --git a/main/src/domain/feedback_collector.rs b/main/src/domain/feedback_collector.rs new file mode 100644 index 000000000..32bec6791 --- /dev/null +++ b/main/src/domain/feedback_collector.rs @@ -0,0 +1,118 @@ +use crate::domain::{ + FeedbackOutput, FinalRealFeedbackValue, FinalSourceFeedbackValue, MidiDestination, + PreliminaryRealFeedbackValue, PreliminarySourceFeedbackValue, RealearnSourceState, +}; +use helgoboss_learn::devices::x_touch::XTouchMackieLcdState; +use helgoboss_learn::{ + MackieLcdScope, MidiSourceValue, PreliminaryMidiSourceFeedbackValue, RawMidiEvent, + XTouchMackieLcdColorRequest, +}; +use std::collections::HashSet; + +/// Responsible for collecting non-final feedback values and aggregating them into final ones. +pub struct FeedbackCollector<'a> { + x_touch_mackie_lcd_feedback_collector: Option>, +} + +struct XTouchMackieLcdFeedbackCollector<'a> { + state: &'a mut XTouchMackieLcdState, + changed_x_touch_mackie_lcd_extenders: HashSet, +} + +impl<'a> FeedbackCollector<'a> { + pub fn new( + global_source_state: &'a mut RealearnSourceState, + feedback_output: Option, + ) -> Self { + let x_touch_mackie_lcd_state = match feedback_output { + Some(FeedbackOutput::Midi(MidiDestination::Device(dev_id))) => { + Some(global_source_state.get_x_touch_mackie_lcd_state_mut(dev_id)) + } + // No or no direct MIDI device output. Then we can ignore this because + // the X-Touch! + _ => None, + }; + Self { + x_touch_mackie_lcd_feedback_collector: x_touch_mackie_lcd_state.map(|state| { + XTouchMackieLcdFeedbackCollector { + state, + changed_x_touch_mackie_lcd_extenders: Default::default(), + } + }), + } + } + + pub fn process( + &mut self, + preliminary_feedback_value: PreliminaryRealFeedbackValue, + ) -> Option { + match preliminary_feedback_value.source { + // Has projection part only. + None => FinalRealFeedbackValue::new(preliminary_feedback_value.projection, None), + Some(preliminary_source_feedback_value) => match preliminary_source_feedback_value { + PreliminarySourceFeedbackValue::Midi(v) => match v { + // Is final MIDI value already. + PreliminaryMidiSourceFeedbackValue::Final(v) => FinalRealFeedbackValue::new( + preliminary_feedback_value.projection, + Some(FinalSourceFeedbackValue::Midi(v)), + ), + // Is non-final. + PreliminaryMidiSourceFeedbackValue::XTouchMackieLcdColor(req) => { + self.process_x_touch_mackie_lcd_color_request(req); + None + } + }, + // Is final OSC value already. + PreliminarySourceFeedbackValue::Osc(v) => FinalRealFeedbackValue::new( + preliminary_feedback_value.projection, + Some(FinalSourceFeedbackValue::Osc(v)), + ), + }, + } + } + + /// Takes the collected and aggregated material and produces the final feedback values. + pub fn generate_final_feedback_values(self) -> impl Iterator { + self.x_touch_mackie_lcd_feedback_collector + .into_iter() + .flat_map(|x_touch_collector| { + x_touch_collector + .changed_x_touch_mackie_lcd_extenders + .into_iter() + .filter_map(|extender_index| { + let sysex = x_touch_collector.state.sysex(extender_index); + let midi_event = RawMidiEvent::try_from_iter(0, sysex).ok()?; + let source_feedback_value = FinalSourceFeedbackValue::Midi( + MidiSourceValue::single_raw(None, midi_event), + ); + FinalRealFeedbackValue::new(None, Some(source_feedback_value)) + }) + }) + } + + fn process_x_touch_mackie_lcd_color_request(&mut self, req: XTouchMackieLcdColorRequest) { + let collector = match &mut self.x_touch_mackie_lcd_feedback_collector { + None => return, + Some(c) => c, + }; + let channels = match req.channel { + None => (0..MackieLcdScope::CHANNEL_COUNT), + Some(ch) => (ch..ch + 1), + }; + let mut at_least_one_color_change = false; + for ch in channels { + let changed = + collector + .state + .notify_color_requested(req.extender_index, ch, req.color_index); + if changed { + at_least_one_color_change = true; + } + } + if at_least_one_color_change { + collector + .changed_x_touch_mackie_lcd_extenders + .insert(req.extender_index); + } + } +} diff --git a/main/src/domain/main_processor.rs b/main/src/domain/main_processor.rs index 9156f4241..c81c43970 100644 --- a/main/src/domain/main_processor.rs +++ b/main/src/domain/main_processor.rs @@ -4,18 +4,19 @@ use crate::domain::{ CompoundMappingSourceAddress, CompoundMappingTarget, ControlContext, ControlEvent, ControlEventTimestamp, ControlInput, ControlMode, ControlOutcome, DeviceFeedbackOutput, DomainEvent, DomainEventHandler, ExtendedProcessorContext, FeedbackAudioHookTask, - FeedbackDestinations, FeedbackOutput, FeedbackRealTimeTask, FeedbackResolution, - FeedbackSendBehavior, GroupId, HitInstructionContext, HitInstructionResponse, - InstanceContainer, InstanceOrchestrationEvent, InstanceStateChanged, IoUpdatedEvent, - KeyMessage, LimitedAsciiString, MainMapping, MainSourceMessage, MappingActivationEffect, + FeedbackCollector, FeedbackDestinations, FeedbackOutput, FeedbackRealTimeTask, + FeedbackResolution, FeedbackSendBehavior, FinalRealFeedbackValue, FinalSourceFeedbackValue, + GroupId, HitInstructionContext, HitInstructionResponse, InstanceContainer, + InstanceOrchestrationEvent, InstanceStateChanged, IoUpdatedEvent, KeyMessage, + LimitedAsciiString, MainMapping, MainSourceMessage, MappingActivationEffect, MappingControlResult, MappingId, MappingInfo, MessageCaptureEvent, MessageCaptureResult, MidiControlInput, MidiDestination, MidiScanResult, NormalRealTimeTask, OrderedMappingIdSet, OrderedMappingMap, OscDeviceId, OscFeedbackTask, PluginParamIndex, PluginParams, ProcessorContext, ProjectOptions, ProjectionFeedbackValue, QualifiedClipMatrixEvent, - QualifiedMappingId, QualifiedSource, RawParamValue, RealFeedbackValue, RealTimeMappingUpdate, + QualifiedMappingId, QualifiedSource, RawParamValue, RealTimeMappingUpdate, RealTimeTargetUpdate, RealearnMonitoringFxParameterValueChangedEvent, RealearnParameterChangePayload, ReaperConfigChange, ReaperMessage, ReaperTarget, - SharedInstanceState, SourceFeedbackValue, SourceReleasedEvent, SpecificCompoundFeedbackValue, + SharedInstanceState, SourceReleasedEvent, SpecificCompoundFeedbackValue, TargetValueChangedEvent, UpdatedSingleMappingOnStateEvent, VirtualControlElement, VirtualSourceValue, }; @@ -90,12 +91,15 @@ struct Basics { // "experiment/feedback-change-detection-mutable") but it the end it turned out to be impossible // because the reaper-rs control surface doesn't emit feedback-triggering events in a mutable // context. Rightfully so, because it's potentially reentrant! + // TODO-low This reason is now outdated. We detected a general issue with reentrancy. + // https://github.com/helgoboss/reaper-rs/issues/54 last_feedback_checksum_by_address: RefCell>, target_based_conditional_activation_processors: EnumMap, } +/// Used for detecting and preventing subsequent duplicate feedback. #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum FeedbackChecksum { MidiPlain(RawShortMessage), @@ -106,11 +110,10 @@ enum FeedbackChecksum { } impl FeedbackChecksum { - fn from_value(v: &SourceFeedbackValue) -> Self { - use SourceFeedbackValue::*; + fn from_value(v: &FinalSourceFeedbackValue) -> Self { match v { - Midi(v) => Self::from_midi(v), - Osc(v) => Self::from_osc(v), + FinalSourceFeedbackValue::Midi(v) => Self::from_midi(v), + FinalSourceFeedbackValue::Osc(v) => Self::from_osc(v), } } @@ -230,7 +233,7 @@ struct Channels { osc_feedback_task_sender: SenderToNormalThread, additional_feedback_event_sender: SenderToNormalThread, instance_orchestration_event_sender: SenderToNormalThread, - integration_test_feedback_sender: Option>, + integration_test_feedback_sender: Option>, } impl MainProcessor { @@ -361,7 +364,7 @@ impl MainProcessor { pub fn finally_switch_off_source( &self, feedback_output: FeedbackOutput, - feedback_value: SourceFeedbackValue, + feedback_value: FinalSourceFeedbackValue, ) { debug!( self.basics.logger, @@ -2643,7 +2646,7 @@ pub enum NormalMainTask { }, DisableControl, ReturnToControlMode, - UseIntegrationTestFeedbackSender(SenderToNormalThread), + UseIntegrationTestFeedbackSender(SenderToNormalThread), } #[derive(Copy, Clone, Debug, Default)] @@ -3402,6 +3405,9 @@ impl Basics { feedback_reason: FeedbackReason, feedback_values: impl IntoIterator, ) { + let mut global_source_state = BackboneState::source_state().borrow_mut(); + let mut feedback_collector = + FeedbackCollector::new(&mut global_source_state, self.settings.feedback_output); for feedback_value in feedback_values.into_iter() { match feedback_value.value { SpecificCompoundFeedbackValue::Virtual { @@ -3438,36 +3444,48 @@ impl Basics { &self.source_context, ); if let Some(SpecificCompoundFeedbackValue::Real( - final_feedback_value, + preliminary_feedback_value, )) = compound_feedback_value { // Successful virtual-to-real feedback - self.send_direct_feedback( - feedback_reason, - final_feedback_value, - feedback_value.is_feedback_after_control, - ); + if let Some(final_feedback_value) = + feedback_collector.process(preliminary_feedback_value) + { + self.send_direct_feedback( + feedback_reason, + final_feedback_value, + feedback_value.is_feedback_after_control, + ); + } } } } } } - SpecificCompoundFeedbackValue::Real(final_feedback_value) => { - self.send_direct_feedback( - feedback_reason, - final_feedback_value, - feedback_value.is_feedback_after_control, - ); + SpecificCompoundFeedbackValue::Real(preliminary_feedback_value) => { + if let Some(final_feedback_value) = + feedback_collector.process(preliminary_feedback_value) + { + self.send_direct_feedback( + feedback_reason, + final_feedback_value, + feedback_value.is_feedback_after_control, + ); + } } } } + // Send special collected feedback + for final_feedback_value in feedback_collector.generate_final_feedback_values() { + self.send_direct_feedback(feedback_reason, final_feedback_value, false); + } } pub fn send_direct_source_feedback( &self, feedback_output: FeedbackOutput, feedback_reason: FeedbackReason, - source_feedback_value: SourceFeedbackValue, + source_feedback_value: FinalSourceFeedbackValue, is_feedback_after_control: bool, ) { if feedback_reason.is_reset_because_of_source_release() @@ -3507,7 +3525,7 @@ impl Basics { } else { // Production match (source_feedback_value, feedback_output) { - (SourceFeedbackValue::Midi(v), FeedbackOutput::Midi(midi_output)) => { + (FinalSourceFeedbackValue::Midi(v), FeedbackOutput::Midi(midi_output)) => { match midi_output { MidiDestination::FxOutput => { if self.settings.real_output_logging_enabled { @@ -3545,7 +3563,7 @@ impl Basics { } } } - (SourceFeedbackValue::Osc(msg), FeedbackOutput::Osc(dev_id)) => { + (FinalSourceFeedbackValue::Osc(msg), FeedbackOutput::Osc(dev_id)) => { if self.settings.real_output_logging_enabled { log_real_feedback_output(&self.instance_id, format_osc_message(&msg)); } @@ -3561,7 +3579,7 @@ impl Basics { fn send_direct_feedback( &self, feedback_reason: FeedbackReason, - feedback_value: RealFeedbackValue, + feedback_value: FinalRealFeedbackValue, is_feedback_after_control: bool, ) { self.send_direct_device_feedback( @@ -3584,7 +3602,7 @@ impl Basics { fn send_direct_device_feedback( &self, feedback_reason: FeedbackReason, - feedback_value: Option, + feedback_value: Option, is_feedback_after_control: bool, ) { if !feedback_reason.is_always_allowed() && !self.instance_feedback_is_effectively_enabled() diff --git a/main/src/domain/mapping.rs b/main/src/domain/mapping.rs index 2090bbdb6..83e67471b 100644 --- a/main/src/domain/mapping.rs +++ b/main/src/domain/mapping.rs @@ -18,8 +18,8 @@ use helgoboss_learn::{ format_percentage_without_unit, parse_percentage_without_unit, AbsoluteValue, ControlResult, ControlType, ControlValue, FeedbackValue, GroupInteraction, MidiSourceAddress, MidiSourceValue, ModeControlOptions, ModeControlResult, ModeFeedbackOptions, NumericFeedbackValue, NumericValue, - OscSource, OscSourceAddress, PropValue, RawMidiEvent, SourceCharacter, SourceContext, Target, - UnitValue, ValueFormatter, ValueParser, + OscSource, OscSourceAddress, PreliminaryMidiSourceFeedbackValue, PropValue, RawMidiEvent, + SourceCharacter, SourceContext, Target, UnitValue, ValueFormatter, ValueParser, }; use helgoboss_midi::{Channel, RawShortMessage, ShortMessage}; use num_enum::{IntoPrimitive, TryFromPrimitive}; @@ -1577,12 +1577,11 @@ impl CompoundMappingSource { /// Used for: /// /// - Source takeover (feedback) - /// - pub fn has_same_feedback_address_as_value(&self, value: &SourceFeedbackValue) -> bool { + pub fn has_same_feedback_address_as_value(&self, value: &FinalSourceFeedbackValue) -> bool { use CompoundMappingSource::*; match (self, value) { - (Osc(s), SourceFeedbackValue::Osc(v)) => s.has_same_feedback_address_as_value(v), - (Midi(s), SourceFeedbackValue::Midi(v)) => s.has_same_feedback_address_as_value(v), + (Osc(s), FinalSourceFeedbackValue::Osc(v)) => s.has_same_feedback_address_as_value(v), + (Midi(s), FinalSourceFeedbackValue::Midi(v)) => s.has_same_feedback_address_as_value(v), _ => false, } } @@ -1689,15 +1688,15 @@ impl CompoundMappingSource { &self, feedback_value: Cow, source_context: &SourceContext, - ) -> Option { + ) -> Option { use CompoundMappingSource::*; match self { Midi(s) => s .feedback_flexible(feedback_value.into_owned(), source_context) - .map(SourceFeedbackValue::Midi), + .map(PreliminarySourceFeedbackValue::Midi), Osc(s) => s .feedback(feedback_value.into_owned()) - .map(SourceFeedbackValue::Osc), + .map(PreliminarySourceFeedbackValue::Osc), // This is handled in a special way by consumers. Virtual(_) => None, // No feedback for never source. @@ -1756,7 +1755,7 @@ pub enum SpecificCompoundFeedbackValue { value: VirtualFeedbackValue, destinations: FeedbackDestinations, }, - Real(RealFeedbackValue), + Real(PreliminaryRealFeedbackValue), } #[derive(Clone, PartialEq, Debug)] @@ -1808,14 +1807,19 @@ impl SpecificCompoundFeedbackValue { } else { None }; - SpecificCompoundFeedbackValue::Real(RealFeedbackValue::new(projection, source)?) + SpecificCompoundFeedbackValue::Real(PreliminaryRealFeedbackValue::new( + projection, source, + )?) }; Some(val) } } +pub type PreliminaryRealFeedbackValue = AbstractRealFeedbackValue; +pub type FinalRealFeedbackValue = AbstractRealFeedbackValue; + #[derive(Clone, PartialEq, Debug)] -pub struct RealFeedbackValue { +pub struct AbstractRealFeedbackValue { /// Feedback to be sent to projection. /// /// This is an option because there are situations when we don't want projection feedback but @@ -1825,14 +1829,11 @@ pub struct RealFeedbackValue { /// /// This is an option because there are situations when we don't want source feedback but /// projection feedback (e.g. if "MIDI feedback output" is set to None). - pub source: Option, + pub source: Option, } -impl RealFeedbackValue { - pub fn new( - projection: Option, - source: Option, - ) -> Option { +impl AbstractRealFeedbackValue { + pub fn new(projection: Option, source: Option) -> Option { if projection.is_none() && source.is_none() { return None; } @@ -1859,19 +1860,26 @@ impl ProjectionFeedbackValue { } #[derive(Clone, PartialEq, Debug)] -pub enum SourceFeedbackValue { +pub enum PreliminarySourceFeedbackValue { + Midi(PreliminaryMidiSourceFeedbackValue<'static, RawShortMessage>), + Osc(OscMessage), +} + +#[derive(Clone, PartialEq, Debug)] +pub enum FinalSourceFeedbackValue { Midi(MidiSourceValue<'static, RawShortMessage>), Osc(OscMessage), } -impl SourceFeedbackValue { +impl FinalSourceFeedbackValue { pub fn extract_address(&self) -> Option { - use SourceFeedbackValue::*; match self { - Midi(v) => v + FinalSourceFeedbackValue::Midi(v) => v .extract_feedback_address() .map(CompoundMappingSourceAddress::Midi), - Osc(v) => Some(CompoundMappingSourceAddress::Osc(v.addr.clone())), + FinalSourceFeedbackValue::Osc(v) => { + Some(CompoundMappingSourceAddress::Osc(v.addr.clone())) + } } } } diff --git a/main/src/domain/mod.rs b/main/src/domain/mod.rs index e7773ffdf..b6fab7e59 100644 --- a/main/src/domain/mod.rs +++ b/main/src/domain/mod.rs @@ -10,6 +10,9 @@ pub use mapping::*; mod control_surface; pub use control_surface::*; +mod feedback_collector; +pub use feedback_collector::*; + mod audio_hook; pub use audio_hook::*; diff --git a/main/src/domain/realearn_source_context.rs b/main/src/domain/realearn_source_context.rs index fca382725..452003d39 100644 --- a/main/src/domain/realearn_source_context.rs +++ b/main/src/domain/realearn_source_context.rs @@ -12,7 +12,9 @@ impl RealearnSourceState { pub fn get_x_touch_mackie_lcd_state_mut( &mut self, device: MidiOutputDeviceId, - ) -> Option<&mut XTouchMackieLcdState> { - self.x_touch_mackie_lcd_state_by_device.get_mut(&device) + ) -> &mut XTouchMackieLcdState { + self.x_touch_mackie_lcd_state_by_device + .entry(device) + .or_default() } } diff --git a/main/src/infrastructure/test/mod.rs b/main/src/infrastructure/test/mod.rs index 62931d6c7..ef6ee9c76 100644 --- a/main/src/infrastructure/test/mod.rs +++ b/main/src/infrastructure/test/mod.rs @@ -1,5 +1,5 @@ use crate::base::{Global, SenderToNormalThread}; -use crate::domain::{with_fx_name, SourceFeedbackValue, PLUGIN_PARAMETER_COUNT}; +use crate::domain::{with_fx_name, FinalSourceFeedbackValue, PLUGIN_PARAMETER_COUNT}; use crate::infrastructure::plugin::{App, SET_STATE_PARAM_NAME}; use approx::assert_abs_diff_eq; use helgoboss_learn::{MidiSourceValue, BASE_EPSILON, FEEDBACK_EPSILON}; @@ -10,8 +10,8 @@ use reaper_medium::{Db, ReaperPanValue, StuffMidiMessageTarget}; use std::ffi::CString; use std::future::Future; use tokio::time::Duration; +use FinalSourceFeedbackValue::Midi; use MidiSourceValue::{ParameterNumber, Plain}; -use SourceFeedbackValue::Midi; pub fn register_test_action() { Reaper::get().register_action( @@ -149,7 +149,7 @@ async fn setup() -> RealearnTestInstance { struct RealearnTestInstance { fx: Fx, - feedback_receiver: crossbeam_channel::Receiver, + feedback_receiver: crossbeam_channel::Receiver, } impl RealearnTestInstance { @@ -164,7 +164,7 @@ impl RealearnTestInstance { } /// Returns all recorded feedback and removes it from the list. - fn pop_feedback(&self) -> Vec { + fn pop_feedback(&self) -> Vec { self.feedback_receiver.try_iter().collect() } } @@ -994,7 +994,7 @@ async fn fx_by_id() { // Then assert_eq!( realearn.pop_feedback(), - // vec![Midi(Plain(note_on(0, 64, 0)))], + // vec![concrete_midi(Plain(note_on(0, 64, 0)))], vec![], "gone feedback" ); @@ -1141,7 +1141,7 @@ async fn conditional_activation_modifiers() { assert_eq!( realearn.pop_feedback(), // TODO-medium Why no gone feedback!? When I test this in real, it works! - // vec![Midi(Plain(note_on(0, 64, 0)))], + // vec![concrete_midi(Plain(note_on(0, 64, 0)))], vec![], "gone feedback finally here, hooray" ); @@ -1171,7 +1171,7 @@ async fn conditional_activation_modifiers() { realearn.pop_feedback(), // If the "gone" feedback above would work, this would be sent. Right now, it's omitted // because of duplicate-feedback prevention measures - which in itself is correct. - // vec![Midi(Plain(note_on(0, 64, 10))),], + // vec![concrete_midi(Plain(note_on(0, 64, 10))),], vec![], "feedback should be sent as soon as activation condition is met (met again)" ); diff --git a/main/src/infrastructure/ui/sound_util [conflicted].rs b/main/src/infrastructure/ui/sound_util [conflicted].rs deleted file mode 100644 index 39dd188be..000000000 --- a/main/src/infrastructure/ui/sound_util [conflicted].rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::infrastructure::plugin::App; -use reaper_high::Reaper; -use reaper_medium::{FlexibleOwnedPcmSource, MidiImportBehavior, OwnedPreviewRegister, ReaperVolumeValue}; - -pub fn play_sound(file_name: &str) -> Result<(), &'static str>{ - let mut register = OwnedPreviewRegister::new(); - let success_sound_path = App::realearn_sound_dir_path().join(file_name); - let source = Reaper::get() - .medium_reaper() - .pcm_source_create_from_file_ex(&success_sound_path, MidiImportBehavior::UsePreference) - .map_err(|e| e.message())?; - register.set_src(Some(FlexibleOwnedPcmSource::Reaper(source))); - register.set_volume() - // Reaper::get().medium_session().play_preview_ex() - // TODO-high Implement CONTINUE -}