Skip to content

Commit

Permalink
Playtime: Make it possible to record using the "Trigger" target
Browse files Browse the repository at this point in the history
  • Loading branch information
helgoboss committed Feb 12, 2024
1 parent 2f82745 commit 008b3a5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 26 deletions.
31 changes: 25 additions & 6 deletions main/src/domain/real_time_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1400,13 +1400,14 @@ fn process_real_mapping(mapping: &mut RealTimeMapping, args: ProcessRtMappingArg
{
// We have a real-time-capable target
if reaper_target.wants_real_time_control(args.caller, args.is_rendering) {

Check failure on line 1402 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Clippy

this `if` statement can be collapsed
process_real_mapping_in_real_time(
if process_real_mapping_in_real_time(
&mut mapping.core,
&args,
pure_control_event,
reaper_target,
);
return;
) {
return;
}
}
}
// It's either a real-time-capable target that currently doesn't want real-time control or it's not a
Expand All @@ -1423,14 +1424,23 @@ fn process_real_mapping(mapping: &mut RealTimeMapping, args: ProcessRtMappingArg
);
}

enum RealTimeControlOutcome {

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Check

enum `RealTimeControlOutcome` is never used

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Check

enum `RealTimeControlOutcome` is never used

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Build

enum `RealTimeControlOutcome` is never used

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Test

enum `RealTimeControlOutcome` is never used

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Test

enum `RealTimeControlOutcome` is never used

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Test

enum `RealTimeControlOutcome` is never used

Check warning on line 1427 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Test

enum `RealTimeControlOutcome` is never used
/// Nothing more to do.
Done,
/// Real
StillForwardToMainThread,
}

/// This returns `false` if real-time contrl was not possible **and** the consumer should
/// try main-thread control instead (used for example for Playtime's trigger-slot action in order to possibly record
/// when slot empty).
fn process_real_mapping_in_real_time(
mapping_core: &mut MappingCore,
args: &ProcessRtMappingArgs,
pure_control_event: ControlEvent<ControlValue>,
reaper_target: &mut RealTimeReaperTarget,
) {
) -> bool {
// REAPER real-time target actually wants real-time control. Try to process directly here in real-time.
mapping_core.increase_invocation_count();
let control_context = RealTimeControlContext {
instance: args.instance,
_p: &(),
Expand Down Expand Up @@ -1462,7 +1472,14 @@ fn process_real_mapping_in_real_time(
args.rt_feedback_sender,
args.value_event.payload(),
),
RealTimeReaperTarget::ClipTransport(t) => t.hit(control_value, control_context),
RealTimeReaperTarget::ClipTransport(t) => {
let result = t.hit(control_value, control_context);
if result.is_ok_and(|v| v == false) {

Check failure on line 1477 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Check

mismatched types

Check failure on line 1477 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Clippy

mismatched types

Check failure on line 1477 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Test

mismatched types

Check failure on line 1477 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Build

mismatched types

Check failure on line 1477 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Build

mismatched types

Check failure on line 1477 in main/src/domain/real_time_processor.rs

View workflow job for this annotation

GitHub Actions / Build

mismatched types
// Important: We must forward to main thread in this case in order to possibly record!
return false;
}
result.map(|_| ())
}
RealTimeReaperTarget::ClipColumn(t) => t.hit(control_value, control_context),
RealTimeReaperTarget::ClipRow(t) => t.hit(control_value, control_context),
RealTimeReaperTarget::ClipMatrix(t) => t.hit(control_value, control_context),
Expand All @@ -1478,6 +1495,7 @@ fn process_real_mapping_in_real_time(
}
}
};
mapping_core.increase_invocation_count();
if args.log_options.target_control_logging_enabled {
let entry = ControlLogEntry {
kind: log_entry_kind,
Expand All @@ -1492,6 +1510,7 @@ fn process_real_mapping_in_real_time(
entry,
});
}
true
}

// TODO-medium Also keep this more local to SendMidiTarget, just like ClipTransportTarget.
Expand Down
34 changes: 15 additions & 19 deletions main/src/domain/targets/playtime_slot_transport_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,11 +456,13 @@ mod playtime_impl {
}

impl RealTimeSlotTransportTarget {
/// This returns `Ok(false)` if real-time trigger was not possible **and** the consumer should
/// try main-thread control instead (used for trigger action in order to possibly record when slot empty).
pub fn hit(
&mut self,
value: ControlValue,
context: RealTimeControlContext,
) -> Result<(), &'static str> {
) -> Result<bool, &'static str> {
use PlaytimeSlotTransportAction::*;
let on = value.is_on();
let matrix = context.clip_matrix()?;
Expand All @@ -469,37 +471,39 @@ mod playtime_impl {
Trigger => matrix.trigger_slot(self.basics.slot_coordinates, on),
PlayStop => {
if on {
matrix.play_slot(self.basics.slot_coordinates, self.basics.play_options())
matrix
.play_slot(self.basics.slot_coordinates, self.basics.play_options())?;
} else {
matrix.stop_slot(
self.basics.slot_coordinates,
self.basics.options.play_stop_timing,
)
)?;
}
Ok(true)
}
PlayPause => {
if on {
matrix.play_slot(self.basics.slot_coordinates, self.basics.play_options())
matrix
.play_slot(self.basics.slot_coordinates, self.basics.play_options())?;
} else {
matrix.pause_slot(self.basics.slot_coordinates)
matrix.pause_slot(self.basics.slot_coordinates)?;
}
Ok(true)
}
Stop => {
if on {
matrix.stop_slot(
self.basics.slot_coordinates,
self.basics.options.play_stop_timing,
)
} else {
Ok(())
)?;
}
Ok(true)
}
Pause => {
if on {
matrix.pause_slot(self.basics.slot_coordinates)
} else {
Ok(())
matrix.pause_slot(self.basics.slot_coordinates)?;
}
Ok(true)
}
RecordStop | RecordPlayStop => Err("record not supported for real-time target"),
Looped => Err("setting looped not supported for real-time target"),
Expand All @@ -515,14 +519,6 @@ mod playtime_impl {
let matrix = context.clip_matrix().ok()?;
let matrix = matrix.lock();
let column = matrix.column(self.basics.slot_coordinates.column()).ok()?;
// Performance hint: This *will* sometimes be blocking IF we have live FX multiprocessing
// turned on in REAPER. That's because then multiple threads will prepare stuff for the
// main audio callback. According to Justin this is not a big deal though (given that we
// lock only very shortly), so we allow blocking here. The only other alternative would be
// to not acquire the value at this point and design the real-time clip transport target
// in a way that the glue section doesn't need to know the current target value, leaving
// the glue section powerless and making things such as "Toggle button" not work. This
// would hurt the usual ReaLearn experience.
let column = column.blocking_lock();
let slot = column.slot(self.basics.slot_coordinates.row()).ok()?;
let Some(first_clip) = slot.first_clip() else {
Expand Down
2 changes: 1 addition & 1 deletion playtime-clip-engine

0 comments on commit 008b3a5

Please sign in to comment.