Skip to content

Commit

Permalink
#840 Ignore target touch caused by ReaLearn when learning target in i…
Browse files Browse the repository at this point in the history
…nstance
  • Loading branch information
helgoboss committed Apr 8, 2023
1 parent 7591afb commit f66de12
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 58 deletions.
44 changes: 21 additions & 23 deletions main/src/application/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use crate::domain::{
ParamSetting, PluginParams, ProcessorContext, ProjectionFeedbackValue, QualifiedMappingId,
RealearnClipMatrix, RealearnControlSurfaceMainTask, RealearnTarget, ReaperTarget,
ReaperTargetType, SharedInstanceState, StayActiveWhenProjectInBackground, Tag,
TargetControlEvent, TargetValueChangedEvent, VirtualControlElementId, VirtualFx, VirtualSource,
VirtualSourceValue,
TargetControlEvent, TargetTouchEvent, TargetValueChangedEvent, VirtualControlElementId,
VirtualFx, VirtualSource, VirtualSourceValue,
};
use derivative::Derivative;
use enum_map::EnumMap;
Expand Down Expand Up @@ -1451,11 +1451,12 @@ impl Session {
compartment,
qualified_mapping_id.id,
)));
let filter = (ReaperTargetType::all(), TargetTouchCause::Reaper);
session.start_learning_target_internal(
Rc::downgrade(&shared_session),
qualified_mapping_id,
false,
None,
filter,
);
});
}
Expand Down Expand Up @@ -1714,7 +1715,8 @@ impl Session {
return;
}
}
self.start_learning_target_internal(session, mapping_id, true, None);
let filter = (ReaperTargetType::all(), TargetTouchCause::Reaper);
self.start_learning_target_internal(session, mapping_id, true, filter);
}

/// Not setting `included_targets` means all targets are potentially included. This should
Expand All @@ -1725,7 +1727,7 @@ impl Session {
weak_session: WeakSession,
mapping_id: QualifiedMappingId,
handle_control_disabling: bool,
filter: Option<(HashSet<ReaperTargetType>, TargetTouchCause)>,
filter: (HashSet<ReaperTargetType>, TargetTouchCause),
) {
let instance_id = self.instance_id;
if handle_control_disabling {
Expand All @@ -1740,27 +1742,23 @@ impl Session {
.ok_or(SESSION_GONE)?
.borrow()
.control_surface_main_task_sender
.request_next_reaper_targets(Some(instance_id));
while let Ok(target) = receiver.recv().await {
if let Some(filter) = &filter {
let filter = LastTouchedTargetFilter {
included_target_types: &filter.0,
touch_cause: filter.1,
};
if !filter.matches(&target) {
continue;
}
.capture_targets(Some(instance_id));
while let Ok(event) = receiver.recv().await {
let filter = LastTouchedTargetFilter {
included_target_types: &filter.0,
touch_cause: filter.1,
};
if !filter.matches(&event) {
continue;
}
// TODO-high CONTINUE Make it possible to learn transport/actions.
// TODO-high CONTINUE Make it still possible to have normal control while
// learning a target (as before, at least for instance target learning, but
// different than before for global target learning). Low-prio.
// => Test global learning and Learn many!
// TODO-high Ignore touch events caused by ReaLearn when doing global target capturing
// and local UI-triggered learning
let session = weak_session.upgrade().ok_or(SESSION_GONE)?;
let mut session = session.borrow_mut();
session.learn_target(&target, weak_session.clone());
session.learn_target(&event.target, weak_session.clone());
session.stop_learning_target();
}
Ok(())
Expand All @@ -1783,7 +1781,7 @@ impl Session {

fn stop_learning_target(&self) {
self.control_surface_main_task_sender
.stop_learning_targets(Some(self.instance_id));
.stop_capturing_targets(Some(self.instance_id));
self.instance_state
.borrow_mut()
.set_mapping_which_learns_target(None);
Expand Down Expand Up @@ -2637,7 +2635,7 @@ impl DomainEventHandler for WeakSession {
.map(ReaperTargetType::from_learnable_target_kinds)
.unwrap_or_else(ReaperTargetType::all);
let filter = (included_targets, m.touch_cause.unwrap_or_default());
s.start_learning_target_internal(self.clone(), id, false, Some(filter));
s.start_learning_target_internal(self.clone(), id, false, filter);
} else {
s.stop_learning_target();
}
Expand Down Expand Up @@ -2823,10 +2821,10 @@ pub type RealearnControlSurfaceMainTaskSender =
SenderToNormalThread<RealearnControlSurfaceMainTask<WeakSession>>;

impl RealearnControlSurfaceMainTaskSender {
pub fn request_next_reaper_targets(
pub fn capture_targets(
&self,
instance_id: Option<InstanceId>,
) -> async_channel::Receiver<ReaperTarget> {
) -> async_channel::Receiver<TargetTouchEvent> {
let (sender, receiver) = async_channel::bounded(500);
self.send_complaining(RealearnControlSurfaceMainTask::StartCapturingTargets(
instance_id,
Expand All @@ -2835,7 +2833,7 @@ impl RealearnControlSurfaceMainTaskSender {
receiver
}

pub fn stop_learning_targets(&self, instance_id: Option<InstanceId>) {
pub fn stop_capturing_targets(&self, instance_id: Option<InstanceId>) {
self.send_complaining(RealearnControlSurfaceMainTask::StopCapturingTargets(
instance_id,
));
Expand Down
12 changes: 10 additions & 2 deletions main/src/domain/backbone_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,15 @@ pub struct LastTouchedTargetFilter<'a> {
}

impl<'a> LastTouchedTargetFilter<'a> {
pub fn matches(&self, target: &ReaperTarget) -> bool {
let actual_target_type = ReaperTargetType::from_target(target);
pub fn matches(&self, event: &TargetTouchEvent) -> bool {
// Check touch cause
match self.touch_cause {
TargetTouchCause::Realearn if !event.caused_by_realearn => return false,
TargetTouchCause::Reaper if event.caused_by_realearn => return false,
_ => {}
}
// Check target types
let actual_target_type = ReaperTargetType::from_target(&event.target);
self.included_target_types.contains(&actual_target_type)
}
}
Expand Down Expand Up @@ -535,6 +542,7 @@ const REFERENCED_INSTANCE_NOT_AVAILABLE: &str = "other instance not available";
const REFERENCED_CLIP_MATRIX_NOT_AVAILABLE: &str = "clip matrix of other instance not available";
const NESTED_CLIP_BORROW_NOT_SUPPORTED: &str = "clip matrix of other instance also borrows";

#[derive(Clone, Debug)]
pub struct TargetTouchEvent {
pub target: ReaperTarget,
pub caused_by_realearn: bool,
Expand Down
8 changes: 4 additions & 4 deletions main/src/domain/control_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use std::collections::HashMap;
use std::mem;

type OscCaptureSender = async_channel::Sender<OscScanResult>;
type TargetCaptureSender = async_channel::Sender<ReaperTarget>;
type TargetCaptureSender = async_channel::Sender<TargetTouchEvent>;

const CONTROL_SURFACE_MAIN_TASK_BULK_SIZE: usize = 10;
const ADDITIONAL_FEEDBACK_EVENT_BULK_SIZE: usize = 30;
Expand Down Expand Up @@ -376,13 +376,13 @@ impl<EH: DomainEventHandler> RealearnControlSurfaceMiddleware<EH> {
{
self.rx_middleware.handle_change(e.clone());
if let Some(target) = ReaperTarget::touched_from_change_event(e) {
for sender in self.target_capture_senders.values() {
let _ = sender.try_send(target.clone());
}
let touch_event = TargetTouchEvent {
target,
caused_by_realearn,
};
for sender in self.target_capture_senders.values() {
let _ = sender.try_send(touch_event.clone());
}
BackboneState::get().notify_target_touched(touch_event);
}
}
Expand Down
28 changes: 16 additions & 12 deletions main/src/infrastructure/plugin/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,14 +1194,15 @@ impl App {
self.show_message_panel("ReaLearn", "Touch some targets!", || {
App::get()
.control_surface_main_task_sender
.stop_learning_targets(None);
.stop_capturing_targets(None);
});
let receiver = self
.control_surface_main_task_sender
.request_next_reaper_targets(None);
while let Ok(target) = receiver.recv().await {
let receiver = self.control_surface_main_task_sender.capture_targets(None);
while let Ok(event) = receiver.recv().await {
if event.caused_by_realearn {
continue;
}
if let Some((session, mapping)) =
self.find_first_relevant_session_with_target(compartment, &target)
self.find_first_relevant_session_with_target(compartment, &event.target)
{
self.close_message_panel();
session
Expand Down Expand Up @@ -1361,13 +1362,16 @@ impl App {
self.show_message_panel("ReaLearn", msg, || {
App::get()
.control_surface_main_task_sender
.stop_learning_targets(None);
.stop_capturing_targets(None);
});
self.control_surface_main_task_sender
.request_next_reaper_targets(None)
.recv()
.await
.map_err(|_| "stopped learning")
let receiver = self.control_surface_main_task_sender.capture_targets(None);
while let Ok(event) = receiver.recv().await {
if event.caused_by_realearn {
continue;
}
return Ok(event.target);
}
Err("capturing ended")
}

fn start_learning_source_for_target(&self, compartment: Compartment, target: &ReaperTarget) {
Expand Down
56 changes: 39 additions & 17 deletions resources/test-projects/issue-840-async-target-learning.RPP
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<REAPER_PROJECT 0.1 "6.78+dev0406/macOS-arm64" 1680958919
<REAPER_PROJECT 0.1 "6.78+dev0406/macOS-arm64" 1680965968
<NOTES 0 2
>
RIPPLE 0
GROUPOVERRIDE 0 0 0
AUTOXFADE 1
AUTOXFADE 129
ENVATTACH 3
POOLEDENVATTACH 0
MIXERUIFLAGS 11 48
Expand All @@ -16,7 +16,7 @@
TIMEMODE 1 5 -1 30 0 0 -1
VIDEO_CONFIG 0 0 256
PANMODE 3
CURSOR 6
CURSOR 6.5
ZOOM 100 0 0
VZOOMEX 6 0
USE_REC_CFG 0
Expand Down Expand Up @@ -69,7 +69,7 @@
MASTERTRACKVIEW 0 0.6667 0.5 0.5 0 0 0 0 0 0 0 0 0 0
MASTERHWOUT 0 0 1 0 0 0 0 -1
MASTER_NCH 2 2
MASTER_VOLUME 1 0 -1 -1 1
MASTER_VOLUME 0.77019387072009 0 -1 -1 1
MASTER_PANMODE 3
MASTER_FX 1
MASTER_SEL 0
Expand All @@ -83,7 +83,7 @@
>
<TEMPOENVEX
EGUID {13BDD549-D15D-744C-A49F-2C96BA8468C0}
ACT 1 -1
ACT 0 -1
VIS 1 0 1
LANEHEIGHT 0 0
ARM 0
Expand All @@ -96,7 +96,7 @@
PEAKCOL 16576
BEAT -1
AUTOMODE 0
VOLPAN 0.24956353399499 0 -1 -1 1
VOLPAN 0.00000003162278 0 -1 -1 1
MUTESOLO 0 0 0
IPHASE 0
PLAYOFFS 0 1
Expand All @@ -116,25 +116,47 @@
MIDIOUT -1
MAINSEND 1 0
<FXCHAIN
SHOW 0
LASTSEL 0
WNDRECT 335 418 724 393
SHOW 2
LASTSEL 1
DOCKED 0
BYPASS 0 0 0
<VST "VSTi: ReaLearn (Helgoboss)" realearn.vst.dylib 0 "" 1751282284<5653546862726C7265616C6561726E00> ""
bHJiaO5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAAAAAAC5AgAAAQAAAAAAEAA=
bHJiaO5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAAAAAACoBAAAAQAAAAAAEAA=
eyJ2ZXJzaW9uIjoiMi4xNS4wLXByZS4yIiwiaWQiOiJJQTJsWTFSdCIsInN0YXlBY3RpdmVXaGVuUHJvamVjdEluQmFja2dyb3VuZCI6Ik9ubHlJZkJhY2tncm91bmRQ
cm9qZWN0SXNSdW5uaW5nIiwic2VuZEZlZWRiYWNrT25seUlmQXJtZWQiOnRydWUsImRlZmF1bHRHcm91cCI6e30sImRlZmF1bHRDb250cm9sbGVyR3JvdXAiOnt9LCJt
YXBwaW5ncyI6W3siaWQiOiJMdnQwaXd4cEZJTG9lSXVuUnNhU3MiLCJuYW1lIjoiMSIsInNvdXJjZSI6eyJjYXRlZ29yeSI6Im5ldmVyIiwiaXNSZWdpc3RlcmVkIjpm
YWxzZSwiaXMxNEJpdCI6ZmFsc2UsIm9zY0FyZ0luZGV4IjowfSwibW9kZSI6eyJtYXhTdGVwU2l6ZSI6MC4wNSwibWluU3RlcEZhY3RvciI6MSwibWF4U3RlcEZhY3Rv
ciI6NX0sInRhcmdldCI6eyJ0eXBlIjo1MywiZnhBbmNob3IiOiJpZCIsInVzZVNlbGVjdGlvbkdhbmdpbmciOmZhbHNlLCJ1c2VUcmFja0dyb3VwaW5nIjpmYWxzZSwi
c2Vla0JlaGF2aW9yIjoiSW1tZWRpYXRlIiwidXNlUHJvamVjdCI6dHJ1ZSwibW92ZVZpZXciOnRydWUsInNlZWtQbGF5Ijp0cnVlLCJvc2NBcmdJbmRleCI6MCwibW91
c2VBY3Rpb24iOnsia2luZCI6Ik1vdmVUbyIsImF4aXMiOiJZIn0sInRha2VNYXBwaW5nU25hcHNob3QiOnsia2luZCI6Ikxhc3RMb2FkZWQifX19XSwiaW5zdGFuY2VG
eCI6eyJhZGRyZXNzIjoiRm9jdXNlZCJ9fQ==
cm9qZWN0SXNSdW5uaW5nIiwiY29udHJvbERldmljZUlkIjoia2V5Ym9hcmQiLCJkZWZhdWx0R3JvdXAiOnt9LCJkZWZhdWx0Q29udHJvbGxlckdyb3VwIjp7fSwibWFw
cGluZ3MiOlt7ImlkIjoiTHZ0MGl3eHBGSUxvZUl1blJzYVNzIiwibmFtZSI6IjEiLCJzb3VyY2UiOnsiY2F0ZWdvcnkiOiJuZXZlciIsImlzUmVnaXN0ZXJlZCI6ZmFs
c2UsImlzMTRCaXQiOmZhbHNlLCJvc2NBcmdJbmRleCI6MH0sIm1vZGUiOnsibWF4U3RlcFNpemUiOjAuMDUsIm1pblN0ZXBGYWN0b3IiOjEsIm1heFN0ZXBGYWN0b3Ii
OjV9LCJ0YXJnZXQiOnsidHlwZSI6MiwiZnhBbmNob3IiOiJpZCIsInVzZVNlbGVjdGlvbkdhbmdpbmciOmZhbHNlLCJ1c2VUcmFja0dyb3VwaW5nIjpmYWxzZSwic2Vl
a0JlaGF2aW9yIjoiSW1tZWRpYXRlIiwidXNlUHJvamVjdCI6dHJ1ZSwibW92ZVZpZXciOnRydWUsInNlZWtQbGF5Ijp0cnVlLCJvc2NBcmdJbmRleCI6MCwibW91c2VB
Y3Rpb24iOnsia2luZCI6Ik1vdmVUbyIsImF4aXMiOiJZIn0sInRha2VNYXBwaW5nU25hcHNob3QiOnsia2luZCI6Ikxhc3RMb2FkZWQifX19LHsiaWQiOiJJQ2ZhNEh3
ZmM4aEpORy1teUJOMlciLCJuYW1lIjoiMiIsInNvdXJjZSI6eyJjYXRlZ29yeSI6ImtleWJvYXJkIiwiaXNSZWdpc3RlcmVkIjpmYWxzZSwiaXMxNEJpdCI6ZmFsc2Us
Im9zY0FyZ0luZGV4IjowLCJrZXlzdHJva2UiOnsibW9kaWZpZXJzIjoxLCJrZXkiOjY1fX0sIm1vZGUiOnsibWF4U3RlcFNpemUiOjAuMDUsIm1pblN0ZXBGYWN0b3Ii
OjEsIm1heFN0ZXBGYWN0b3IiOjV9LCJ0YXJnZXQiOnsidHlwZSI6MiwiZnhBbmNob3IiOiJpZCIsInVzZVNlbGVjdGlvbkdhbmdpbmciOmZhbHNlLCJ1c2VUcmFja0dy
b3VwaW5nIjpmYWxzZSwic2Vla0JlaGF2aW9yIjoiSW1tZWRpYXRlIiwidXNlUHJvamVjdCI6dHJ1ZSwibW92ZVZpZXciOnRydWUsInNlZWtQbGF5Ijp0cnVlLCJvc2NB
cmdJbmRleCI6MCwibW91c2VBY3Rpb24iOnsia2luZCI6Ik1vdmVUbyIsImF4aXMiOiJZIn0sInRha2VNYXBwaW5nU25hcHNob3QiOnsia2luZCI6Ikxhc3RMb2FkZWQi
fX19XSwiaW5zdGFuY2VGeCI6eyJhZGRyZXNzIjoiRm9jdXNlZCJ9fQ==
AFByb2dyYW0gMQAQAAAA
>
FLOAT 32 168 752 675
FLOAT 303 168 752 675
FXID {191DE3E1-C97D-9743-8751-F95351890D4F}
WAK 0 0
BYPASS 0 0 0
<VST "VSTi: ReaLearn (Helgoboss)" realearn.vst.dylib 0 "" 1751282284<5653546862726C7265616C6561726E00> ""
bHJiaO5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAAAAAADeAgAAAQAAAAAAEAA=
eyJ2ZXJzaW9uIjoiMi4xNS4wLXByZS4yIiwiaWQiOiJIM3h3Sjl0ayIsInN0YXlBY3RpdmVXaGVuUHJvamVjdEluQmFja2dyb3VuZCI6Ik9ubHlJZkJhY2tncm91bmRQ
cm9qZWN0SXNSdW5uaW5nIiwiY29udHJvbERldmljZUlkIjoia2V5Ym9hcmQiLCJkZWZhdWx0R3JvdXAiOnt9LCJkZWZhdWx0Q29udHJvbGxlckdyb3VwIjp7fSwibWFw
cGluZ3MiOlt7ImlkIjoiSmJTTTM1ZXFEY2hsNVFRQnF5eEJ1IiwibmFtZSI6IjEiLCJzb3VyY2UiOnsiY2F0ZWdvcnkiOiJrZXlib2FyZCIsImlzUmVnaXN0ZXJlZCI6
ZmFsc2UsImlzMTRCaXQiOmZhbHNlLCJvc2NBcmdJbmRleCI6MCwia2V5c3Ryb2tlIjp7Im1vZGlmaWVycyI6MSwia2V5Ijo2Nn19LCJtb2RlIjp7Im1heFN0ZXBTaXpl
IjowLjA1LCJtaW5TdGVwRmFjdG9yIjoxLCJtYXhTdGVwRmFjdG9yIjo1fSwidGFyZ2V0Ijp7InR5cGUiOjIsImZ4QW5jaG9yIjoiaWQiLCJ1c2VTZWxlY3Rpb25HYW5n
aW5nIjpmYWxzZSwidXNlVHJhY2tHcm91cGluZyI6ZmFsc2UsInNlZWtCZWhhdmlvciI6IkltbWVkaWF0ZSIsInVzZVByb2plY3QiOnRydWUsIm1vdmVWaWV3Ijp0cnVl
LCJzZWVrUGxheSI6dHJ1ZSwib3NjQXJnSW5kZXgiOjAsIm1vdXNlQWN0aW9uIjp7ImtpbmQiOiJNb3ZlVG8iLCJheGlzIjoiWSJ9LCJ0YWtlTWFwcGluZ1NuYXBzaG90
Ijp7ImtpbmQiOiJMYXN0TG9hZGVkIn19fV0sImluc3RhbmNlRngiOnsiYWRkcmVzcyI6IkZvY3VzZWQifX0=
AFByb2dyYW0gMQAQAAAA
>
FLOAT 229 72 752 675
FXID {5BE6F29F-D216-B543-A3BC-D920C1C287CB}
WAK 0 0
>
>
<EXTENSIONS
Expand Down

0 comments on commit f66de12

Please sign in to comment.