Old 02-01-2019, 02:50 PM   #1
andyp24
Human being with feelings
 
Join Date: Mar 2016
Posts: 612
Default Two scripts toggling each other

Hi

I'm trying to see if I can have two scripts, both with Defer functions in them, acting in such a way that:

Triggering Script A
If neither is running, A will run
If A is already running, A will terminate
If B is already running, B will terminate and A will run

Triggering Script B
If neither is running, B will run
If B is already running, B will terminate
If A is already running, A will terminate and B will run.

I've tried the following code, and it *sort of* works..... The console spews out "A running" messages continuously, and I can terminate it by calling the A script again. However when I terminate it by running script B, then there's a kind of "crossover confusion" where I'll get a couple of "B running" messages, followed by a single "A running" message, and then all "B running again". It seems that it takes script A a couple of cycles to "catch up" with the fact that B is running.

How can I prevent this? Obviously this is a trivial example, but for the scripts I actually want to use, preventing them both being active simultaneously even for a couple of cycles is important.

Thanks
Andy



---- SCRIPT A ----

if reaper.GetExtState("Double Defer", "B") == "Running" then
reaper.SetExtState("Double Defer", "B", "Stopped", false)
end


reaper.SetExtState("Double Defer", "A", "Running", false)

function Main()
reaper.ShowConsoleMsg("A running")
reaper.ShowConsoleMsg("\n")
if reaper.GetExtState("Double Defer", "A") == "Running" then
reaper.defer(Main)
end
end

Main()


---- SCRIPT B ----

if reaper.GetExtState("Double Defer", "A") == "Running" then
reaper.SetExtState("Double Defer", "A", "Stopped", false)
end

while reaper.GetExtState("Double Defer", "A") == "Running" do
end

reaper.SetExtState("Double Defer", "B", "Running", false)

function Main()
reaper.ShowConsoleMsg("B running")
reaper.ShowConsoleMsg("\n")
if reaper.GetExtState("Double Defer", "B") == "Running" then
reaper.defer(Main)
end
end

Main()

--------------
andyp24 is online now   Reply With Quote
Old 02-02-2019, 06:41 PM   #2
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,133
Default

Code:
reaper.defer(Main)
means run the function Main() in the (near, no more than a few dozen milliseconds) future. It does not refer to anything that has happened already.

Code:
Main()
means run Main() immediately. The reaper.defer(Main) line in it will trigger another repetition of Main() in the future. [Instead of Main(), you could write reaper.defer(Main), and it would cause a brief wait before the first execution of Main().]

So, Main() keeps happening every so often at intervals, as long as the "if" condition is met. You will have to prepare the function to fizzle out, by not calling itself again, if it finds, or fails to find, certain conditions, and also not doing things the other script should be handling now. In other words, you could stop the isolated "A running" console messages in this example by moving those ShowConsoleMessage lines to be after the "if" statement.

In some other cases maybe you would want it to suspend operations and keep freewheeling, so to speak, until it finds conditions change again. It would stop doing heavy processing or calling functions that affect the project, and just check one or more conditions, etc. Or, maybe you might have just one script running continuously that does something different under different conditions, such as the condition of an ExtState variable, and use different actions to set that; or the same script, if run a second time and ExtState exists, can just toggle it, etc...

.

Last edited by FnA; 02-02-2019 at 08:09 PM.
FnA is offline   Reply With Quote
Old 02-03-2019, 07:49 AM   #3
Vagelis
Human being with feelings
 
Join Date: Oct 2017
Location: Larisa, Greece
Posts: 172
Default

Reading this i have a question.Would it be possible to have something like a counter script where we could assign one or more actions and toggle between them?

That would be very useful because e.g we could have an action assigned to a key to toggle between split-split on grid-split on time selection etc.
Vagelis is offline   Reply With Quote
Old 02-03-2019, 10:17 AM   #4
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,133
Default

Quote:
Originally Posted by Vagelis View Post
Reading this i have a question.Would it be possible to have something like a counter script where we could assign one or more actions and toggle between them?

That would be very useful because e.g we could have an action assigned to a key to toggle between split-split on grid-split on time selection etc.
Yes, but I think the difficulty is in making a "slick" or "polished" interface to handle the assignments. Also, to provide a means to indicate what action is active at the moment.

The cycle action editor comes to mind as the interface model. To some extent some similar things are already possible with it. You could use the IF functionality to make certain actions happen when a Dummy Toggle is ON for example. We talked about using it with the (fairly) new Arm Next Action feature here:
https://forum.cockos.com/showthread.php?t=209863

juliansader has an FR for setting toolbar button text that might be helpful for the indication part: https://forum.cockos.com/showthread.php?t=200142
FnA is offline   Reply With Quote
Old 02-04-2019, 12:33 PM   #5
Vagelis
Human being with feelings
 
Join Date: Oct 2017
Location: Larisa, Greece
Posts: 172
Default

Thanks a lot for the info, much appreciated
I'll make a test with cycle action editor and will check out the links.
Vagelis is offline   Reply With Quote
Old 02-04-2019, 07:36 PM   #6
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,133
Default

You're welcome. Here is a bare bones approach to doing with scripts. I guess it could be better, but all I can think of to improve it would be more work than I want to get into, and would still leave a lot to be desired.

Code:
-- vagelis ExtState A1.lua

local t_cmdIDs = {
  "40012",
  "40061",
  "40932",
  "_SWS_BRSPLITSELECTEDTEMPO",
  "_RS6dd6cbc52ca732899f08d9a73f804b1e1bde4399",
}

--------------------------

local r = reaper
local x,idx
if r.HasExtState("Vagelis_A1_s","Vagelis_A1_k") then
  idx = tonumber(r.GetExtState("Vagelis_A1_s","Vagelis_A1_k"))
else
  idx = 1
end

x = tonumber(t_cmdIDs[idx])
if x then -- REAPER factory actions
  r.Main_OnCommand(x, 0)
else -- SWS/custom/script actions
  x = r.NamedCommandLookup(t_cmdIDs[idx])
  if x ~= 0 then r.Main_OnCommand(x, 0) end
end

function noundo() end
r.defer(noundo)
Code:
-- vagelis ExtState A1 increment.lua

local num_increments = 3

-------------------------------

local r = reaper
local idx
if r.HasExtState("Vagelis_A1_s","Vagelis_A1_k") then
  idx = tonumber(r.GetExtState("Vagelis_A1_s","Vagelis_A1_k"))
  if idx >= num_increments then
    idx = 1
  else
    idx = idx + 1
  end
else
  idx = 2
end

r.SetExtState("Vagelis_A1_s","Vagelis_A1_k", tostring(idx), false)

function noundo() end
r.defer(noundo)
First script has the command IDs for the three actions you mentioned plus those for an SWS action and a script command ID, which looks the same as a Custom Action ID, in a table at the top of the script. So 5 actions in it. The second script will set the ExtState variable one higher than it is currently set, going back to 1 when reaching the limit set in the num_increments variable. So as is, it will set the ExtState variable such that only the first three actions in the table in the other script can be used. If you set it to 5 it would work for the SWS action, if you have SWS, but fail on the custom action ID, because those will change in every REAPER install. Its just there for information, you can edit it to something that will work if you like.

You can add more actions to the table. Use the quotation marks and commas the same way, pasting the ID between the quotes. Can optionally omit the last comma only. You can make more of these by copying the two scripts and changing the ExtState variables. I guess you could just replace all A1s with A2s or B1s or whatever, in the lines that refer to ExtState.

Last edited by FnA; 02-04-2019 at 07:42 PM.
FnA is offline   Reply With Quote
Old 02-05-2019, 01:48 PM   #7
Vagelis
Human being with feelings
 
Join Date: Oct 2017
Location: Larisa, Greece
Posts: 172
Default

Great!I'm gonna try it tommorow, thanks a lot!
Vagelis is offline   Reply With Quote
Old 02-11-2019, 02:31 PM   #8
andyp24
Human being with feelings
 
Join Date: Mar 2016
Posts: 612
Default

Thanks, I did eventually get time to come back to this and test.

Easiest way I could find was simply to put the whole of the code in the main() function in an if/then condition which tests whether the other script has updated the ExtState that shows it's stopped.

Seems to work fine. Thanks for all the input.
andyp24 is online now   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 09:36 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.