Go Back   Cockos Incorporated Forums > REAPER Forums > ReaScript, JSFX, REAPER Plug-in Extensions, Developer Forum

Reply
 
Thread Tools Display Modes
Old 08-07-2016, 04:35 AM   #1
Amberience
Human being with feelings
 
Amberience's Avatar
 
Join Date: Oct 2006
Location: swing on the spiral of our divinity
Posts: 2,242
Default Anyone got an example of reaper.GetSetTrackGroupMembership ??

Just want to see an example of this in use, so I can get my head around it. Anyone got an example?
Amberience is offline   Reply With Quote
Old 08-07-2016, 06:19 PM   #2
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

I was waiting to see an example myself, then Frank B asked about paste without removing existing parameters and I figured it was time for a puzzle. I'm noob with bitwise junk, so... I don't really know what you are supposed to put in parameter 3 of GSTGM. This is what I got so far. Seems ok, but have not tested much.

Code:
-- add grouping from track under mouse to selected tracks.lua

function copy_grp()
  local r = reaper
  t_strings = {
    "VOLUME_MASTER",
    "VOLUME_SLAVE",
    "VOLUME_VCA_MASTER",
    "VOLUME_VCA_SLAVE",
    "PAN_MASTER",
    "PAN_SLAVE",
    "WIDTH_MASTER",
    "WIDTH_SLAVE",
    "MUTE_MASTER",
    "MUTE_SLAVE",
    "SOLO_MASTER",
    "SOLO_SLAVE",
    "RECARM_MASTER",
    "RECARM_SLAVE",
    "POLARITY_MASTER",
    "POLARITY_SLAVE",
    "AUTOMODE_MASTER",
    "AUTOMODE_SLAVE",
    "VOLUME_REVERSE",
    "PAN_REVERSE",
    "WIDTH_REVERSE",
    "NO_MASTER_WHEN_SLAVE",
    "VOLUME_VCA_SLAVE_ISPREFX"
  }
  
  local ok = false
  local br_window, br_segment, br_details = r.BR_GetMouseCursorContext()
  if br_window == "tcp" or br_window == "mcp" then ok = true
  elseif  br_window == "arrange" and br_segment == "track" then ok = true end
  local cst = r.CountSelectedTracks(0)
  if ok == true and cst>0 then
    local trk = r.BR_GetMouseCursorContext_Track()
    if trk then
      r.Undo_BeginBlock2(0)
      t_a = {}
      for i=1,23 do t_a[i] = r.GetSetTrackGroupMembership(trk, t_strings[i], 0, 0) end      
      for i=1,cst do
        local strk = r.GetSelectedTrack(0, i-1)
        t_b = {}
        for j=1,23 do t_b[j] = r.GetSetTrackGroupMembership(strk, t_strings[j], 0, 0) end   
        for j=1,23 do
          if t_b[j] ~= t_a[j] then
            local c = t_a[j] | t_b[j]
            r.GetSetTrackGroupMembership(strk, t_strings[j], c, c)
          end
        end
      end
      r.Undo_EndBlock2(0, "copy track grouping", -1)
    end
  end
end

copy_grp()

Last edited by FnA; 08-07-2016 at 08:18 PM. Reason: more efficient?
FnA is offline   Reply With Quote
Old 08-13-2016, 07:44 AM   #3
Frank B
Human being with feelings
 
Frank B's Avatar
 
Join Date: Nov 2015
Posts: 137
Default

It does work as far as I can see in my test. Thanks.
The issue is the "under mouse" is there any other way to set copy/paste function?
scenario is:
save track template with grouping.
loading template selects the "parent" or "previous track" (which is how i have it set now) and copies the grouping then pastes it to the new track without removing the saved grouping it loads in with.
my work around now is.
as the template loads it selects the "parent" and opens the grouping dialog then reselects the new track. this way the dialog opens with the proper grouping and all i have to do is check the box to add the new track to the "parent" grouping.
this script would be risky as i would have to make sure as i loaded the track template i would have to have the mouse over the parent.
but at least we know it can be done, its not impossible, maybe i can mess with it.
Thanks again.
edit: or maybe even swapping the under mouse with "last touched track" ... since the track template usually loads in next to the parent track so i would select it before inserting track from template.

Last edited by Frank B; 08-13-2016 at 02:00 PM.
Frank B is offline   Reply With Quote
Old 08-13-2016, 07:41 PM   #4
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

Yeah, that was just the most basic simple way I could think of to try it out. I'm sure it could get grouping from 1 or more tracks and put it on several others. The number of scenarios and how various people might want various things deterred me from any further experiments.

There is get last touched track function. I don't know if inserting track template will change LTT to one of template tracks. If insert action could be used in same script between functions to get/set grouping, seems it would work without resorting to extstate storage of the info. Don't have time tonight. So, you would only want to get grouping from one track then? If extstate referral was necessary, storing track(s) GUID number(s) would probably be easiest.

Last edited by FnA; 08-13-2016 at 07:54 PM.
FnA is offline   Reply With Quote
Old 08-14-2016, 07:47 PM   #5
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

Quote:
Originally Posted by Frank B View Post
maybe even swapping the under mouse with "last touched track" ... since the track template usually loads in next to the parent track so i would select it before inserting track from template.
Seems to be ok. I'll let you test it out.

You can change the number 1 in this line-
Template_Slot = "1"
to the slot number you want.

Code:
-- add grouping from last touched track to imported track template.lua 
Template_Slot = "1" -- edit number in quotes to desired SWS Resources template slot number
----------------------------------------------------------------------------------------------------

s = "_S&M_ADD_TRTEMPLATE"..Template_Slot

function copy_grp()
  local r = reaper
  t_strings = {
    "VOLUME_MASTER",
    "VOLUME_SLAVE",
    "VOLUME_VCA_MASTER",
    "VOLUME_VCA_SLAVE",
    "PAN_MASTER",
    "PAN_SLAVE",
    "WIDTH_MASTER",
    "WIDTH_SLAVE",
    "MUTE_MASTER",
    "MUTE_SLAVE",
    "SOLO_MASTER",
    "SOLO_SLAVE",
    "RECARM_MASTER",
    "RECARM_SLAVE",
    "POLARITY_MASTER",
    "POLARITY_SLAVE",
    "AUTOMODE_MASTER",
    "AUTOMODE_SLAVE",
    "VOLUME_REVERSE",
    "PAN_REVERSE",
    "WIDTH_REVERSE",
    "NO_MASTER_WHEN_SLAVE",
    "VOLUME_VCA_SLAVE_ISPREFX"
  }
  
  LTT = r.GetLastTouchedTrack()
  if LTT then
      r.Undo_BeginBlock2(0)
      t_a = {}
      for i=1,23 do t_a[i] = r.GetSetTrackGroupMembership(LTT, t_strings[i], 0, 0) end
      r.Main_OnCommand(r.NamedCommandLookup(s),0)
      cst = r.CountSelectedTracks(0) 
      for i=1,cst do
        local strk = r.GetSelectedTrack(0, i-1)
        t_b = {}
        for j=1,23 do t_b[j] = r.GetSetTrackGroupMembership(strk, t_strings[j], 0, 0) end   
        for j=1,23 do
          if t_b[j] ~= t_a[j] then
            local c = t_a[j] | t_b[j]
            r.GetSetTrackGroupMembership(strk, t_strings[j], c, c)
          end
        end
      end
      r.Undo_EndBlock2(0, "copy grouping to template", -1)
    end
end

copy_grp()
FnA is offline   Reply With Quote
Old 09-13-2016, 01:25 PM   #6
Frank B
Human being with feelings
 
Frank B's Avatar
 
Join Date: Nov 2015
Posts: 137
Default

wow thanks.. i just got this email today, sorry I'm late. i will try it and get back
Frank B is offline   Reply With Quote
Old 01-24-2017, 10:44 AM   #7
storyteller
Human being with feelings
 
Join Date: Aug 2016
Posts: 232
Default

Quote:
Originally Posted by FnA View Post
I was waiting to see an example myself, then Frank B asked about paste without removing existing parameters and I figured it was time for a puzzle. I'm noob with bitwise junk, so... I don't really know what you are supposed to put in parameter 3 of GSTGM. This is what I got so far. Seems ok, but have not tested much.

Code:
-- add grouping from track under mouse to selected tracks.lua

function copy_grp()
  local r = reaper
  t_strings = {
    "VOLUME_MASTER",
    "VOLUME_SLAVE",
    "VOLUME_VCA_MASTER",
    "VOLUME_VCA_SLAVE",
    "PAN_MASTER",
    "PAN_SLAVE",
    "WIDTH_MASTER",
    "WIDTH_SLAVE",
    "MUTE_MASTER",
    "MUTE_SLAVE",
    "SOLO_MASTER",
    "SOLO_SLAVE",
    "RECARM_MASTER",
    "RECARM_SLAVE",
    "POLARITY_MASTER",
    "POLARITY_SLAVE",
    "AUTOMODE_MASTER",
    "AUTOMODE_SLAVE",
    "VOLUME_REVERSE",
    "PAN_REVERSE",
    "WIDTH_REVERSE",
    "NO_MASTER_WHEN_SLAVE",
    "VOLUME_VCA_SLAVE_ISPREFX"
  }
  
  local ok = false
  local br_window, br_segment, br_details = r.BR_GetMouseCursorContext()
  if br_window == "tcp" or br_window == "mcp" then ok = true
  elseif  br_window == "arrange" and br_segment == "track" then ok = true end
  local cst = r.CountSelectedTracks(0)
  if ok == true and cst>0 then
    local trk = r.BR_GetMouseCursorContext_Track()
    if trk then
      r.Undo_BeginBlock2(0)
      t_a = {}
      for i=1,23 do t_a[i] = r.GetSetTrackGroupMembership(trk, t_strings[i], 0, 0) end      
      for i=1,cst do
        local strk = r.GetSelectedTrack(0, i-1)
        t_b = {}
        for j=1,23 do t_b[j] = r.GetSetTrackGroupMembership(strk, t_strings[j], 0, 0) end   
        for j=1,23 do
          if t_b[j] ~= t_a[j] then
            local c = t_a[j] | t_b[j]
            r.GetSetTrackGroupMembership(strk, t_strings[j], c, c)
          end
        end
      end
      r.Undo_EndBlock2(0, "copy track grouping", -1)
    end
  end
end

copy_grp()
Parameter 3 took me a few tries to figure out, and it may take a minute to explain, so try to stay with me through the explanation.

Much like each of the variables is held in an array 23 variables like you demonstrated with t_strings, positions 3 tells Reaper whether the bit variable is on or off. HOWEVER - unlike the typical concept of 1s and 0s, position 3 tells you exactly where in the bit matrix the values are held. So 0 is off, but there is another integer value that represents on. Sound confusing? It was for me too, but I pounded through it. So here is the explanation.

If you imagine the group matrix grid GUI in reaper, you can imagine a bit grid. Essentially, there is a single ID (an int in this case) that represents each combination of group assignments. At first it is simple to think about - group 1 has an ID, group 2 has an ID and so on. This is 32 separate IDs. Quite frankly, this is all you will need if you build your grouping appropriately, but it goes further. If a track is assigned to groups 1 AND 2, the ID Reaper receives is not an array of the IDs for group 1 & 2. Instead, there is a separate number ID that represents this combination. Groups 1 & 3 have a separate combination and so on. It is a brilliant and efficient way to program this feature into Reaper actually.

Assuming you are not doing something inherently wacky with your grouping (which would break the way this feature is intended), you can get by with knowing the separate 33 group IDs in the bit grid. The first 32 are for each individual group. The 33rd ID represents "all groups." Cool. That sounds easy. So what are the 32 group ids? Well, it looks something like this.

1
2
4
8
16
32
64
...etc

It is a doubling function where each number represents one of the bits in the byte's register. So if you wanted to turn group id 3 off for a track, you would use 0. If you wanted to turn it on, you'd use 4 (its ID). This number would be placed in the array of 23 variables where the variable would be "on."

The 33rd group ID that represents ALL 32 groups is the sum of the first 32 integers. If you're feeling groovy you can write a function that will loop through all of the bitmask IDs since it is mostly a summing function. For example, the ID that represents groups 1 & 2 together in the matrix is 3 (1 + 2). But it gets complicated fairly quickly.

I hope this helps! It took me a bit to figure out. You will need something like 3 or 4 functions to loop through everything programmatically. If you are brute forcing it, then just create an array of 23 variables with the group ID you plan on using. The reaper API refers to this as the BITMASK since you are essentially masking the 1 with the group combination ID. When I get a chance, I'll find my code to share. Let me know if you have any questions though!

Last edited by storyteller; 01-24-2017 at 11:17 AM.
storyteller is offline   Reply With Quote
Old 02-12-2017, 08:18 PM   #8
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 2,173
Default

Thanks, I missed this when you posted, and just stumbled back into it by accident just now.

I do have a question...

Some of the preferences you can access with SNM_GetIntConfigVar use these bitmask deals. I know a way to do it by converting to string, but I would like to know how to get the various positions in the most efficient manner. For example:

x = reaper.SNM_GetIntConfigVar("defsendflag", 999888)

Say x = 515...

Send type (prefader, etc)uses the right most two bits. The red ones here:
...00000000001000000011
(something like that anyway)

I can make it work with a function that converts integer to that ^^^ but there must be a slicker way.

I'll try to disect what you wrote above now...

edit. This is what I came up with for that. Is this a good way to do it? I don't know.
Code:
// toggle send preference.eel
// skips the deprecated one.

function FnA()
(
  a = extension_api("SNM_GetIntConfigVar", "defsendflag", 1);
  b = a >> 2 << 2;
  c = a-b;
  c == 3 ? (a=a-3):(
    c == 1 ? (a=a+2):
    a=a+1;
  );
  extension_api("SNM_SetIntConfigVar", "defsendflag", a);
);
defer("FnA()");

Last edited by FnA; 02-12-2017 at 10:57 PM.
FnA is offline   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 05:18 AM.


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