helgoboss / helgobox

Helgobox: ReaLearn & Playtime
https://www.helgoboss.org/projects/helgobox
GNU General Public License v3.0
211 stars 20 forks source link

Process "selected track" after other actions run? #395

Closed patmaddox closed 3 years ago

patmaddox commented 3 years ago

First I should acknowledge that I'm not quite sure how ReaLearn does multiple mappings - if it fires them off in parallel, or if they're guaranteed to be sequential. I'll look at the code! :)

I am running into a case where I have a script that changes the selected track, so that when I use a ReaLearn selected track action in combination with it, ReaLearn activates the incorrect track.

My setup uses the Cycle Siblings and Remember Child scripts that I put together - they provide the sort of behavior alluded to in #240. I still think it's worth discussing this issue separately, because I think it's reasonable for scripts to change the selected track, and for ReaLearn to keep up with it.

Here's the behavior that I've set up with my scripts and a custom action:

cycle-scripts

Here's the custom action:

Custom: Select Next Sibling and Remember - record arm
  Script: paat - Select Remembered Child.lua
  Xenakios/SWS: Set selected tracks record unarmed
  Script: paat - Select Next Sibling.lua
  Xenakios/SWS: Set selected tracks record armed
  Script: paat - Remember Child.lua

Then I thought I could use ReaLearn's built-in "Track: Arm/disarm" action. My custom action then removes the "Xenakios/SWS: Set selected tracks record unarmed/armed" steps.

Here's what happens:

cycle-realearn

It appears that ReaLearn decides what is the Selected Track once when it runs the mappings - rather than looking at which track is selected at the time it runs the mapping (assuming that mappings are run sequentially... which may not be true).

So I am hoping to start a discussion on a way to proceed here. I can see value in ReaLearn having a consistent Selected Track for all of the mappings. I can also see value in ReaLearn knowing what is the current selected track. It's also possible that I'm just making a silly mistake!

Here are the relevant mappings for reference:

image

helgoboss commented 3 years ago

Mappings are at the moment not run sequentially. There's no guarantee when a mapping will be processed.

Whenever ReaLearn needs to know the currently selected track, it asks REAPER. It doesn't hold the currently selected track as internal state.

patmaddox commented 3 years ago

Mappings are at the moment not run sequentially. There's no guarantee when a mapping will be processed.

Good to know, thanks!

I think I have an idea for how I can make the arm/disarm selected run after the scripts. Something about setting a parameter. Will give it a shot and report back...

patmaddox commented 3 years ago

tl;dr: is there any mechanism for creating dependencies between mappings, to ensure that one mapping doesn't run until another one (or set of other ones) has completed? Specifically to check if a REAPER command mapping has finished.


Okay I tried it and I don't think it's going to work...

Here's what I did, it involves using "Action Layers"

I see the exact same behavior as before. Which is maybe not surprising - I'm guessing that running the script is the slowest operation, and so that mapping doesn't get processed until after the parameter has changed to 3.

So this would seem that any command that changes the selection has to be last in line - anything that depends on the track selection would be wrong.

What is interesting to me is that every layer up until that last one works as I expect. They transition from layer to layer, performing the behaviors. If I move my controller really fast, it's possible to see it get mixed up and perform the actions out of order, which is why I suspect that the script call is so much slower relatively.

Anyway, I'm wondering if there's a way to specify that some mapping should occur after another one has completed. Specifically, I want to run the "Arm/disarm selected track" mapping after my "Select next/previous sibling" command has finished.

image

helgoboss commented 3 years ago

I think I should just guarantee that mappings are processed in the order in which they are specified. That would be the most intuitive thing I guess.

helgoboss commented 3 years ago

@patmaddox In upcoming 1.10.0-pre.4 this should work.

New guarantees

If one incoming message (MIDI, OSC, virtual etc.) triggers multiple mappings, we call this a transaction.

  1. Mappings in one transaction are now executed in the order in which they are defined in the corresponding compartment.
  2. If the execution of one mapping affects a subsequent mapping within that transaction (e.g. because that mapping causes selection of a different track), subsequent mappings will take this into account.
    • Notable exception: This isn't yet true for ReaLearn parameters. If you have one mapping that changes a ReaLearn parameter and a subsequent mapping in that transaction which relies on that parameter (either by an activation condition or by a <Dynamic> selector, this won't work yet!.

Example scenario which works now and hasn't worked before:

patmaddox commented 3 years ago

Very cool! I look forward to trying this out, thank you.