No internet connection
  1. Home
  2. How to

Using Colors of Tracks to Define Actions

By Philip weinrobe @Philip_weinrobe
    2023-08-03 12:55:08.368Z

    Hi Geniuses
    I have a bunch of scripts I run to prep a session. I run one script for each of my food groups (bass, guitars, drums, BVs, LVs, Keys, Etc)
    Before I run each of the food group scripts, i need to select the tracks in that food group.
    The thing is, the tracks in the food groups always have the exact same color (which i set with a soundflow command).
    So, in theory, I should be able to automate all those individual food group prep scripts by saying something like:

    "find all tracks with Red 3 color, then run "Bass Prep Script" > next find all tracks with Green 4 color, then run "Keys Prep Script, etc etc etc"

    problem is i don't know how to get this functionality into my scripts. is this possible?
    If so, can someone point me towards a way to select tracks based off color of track?

    • 28 replies

    There are 28 replies. Estimated reading time: 62 minutes

    1. Chad Wahlbrink @Chad2023-08-03 14:12:56.240Z

      Hey @Philip_weinrobe!

      To my knowledge, the color of a track in Pro Tools is not directly accessible. I believe the only way to do what you are asking would be to utilize @Andrew_Scheps' Scheps Color Deck, which is a "premium app" on the SoundFlow store. This app allows you to select tracks based on color, with the caveat that the tracks must be visible on the screen to register them.

      For more information on that app's functionality, check out the demo video here (I've cued up 4:21, where Andrew demonstrates the "select tracks by color" function) :
      https://youtu.be/a8dwa2A39Vo?t=259

      1. In reply toPhilip_weinrobe:
        Andrew Scheps @Andrew_Scheps
          2023-08-03 14:36:10.012Z

          Hi @Philip_weinrobe ,

          As @chadwahlbrink says, there is no way to do this directly other than my fabulous app. Ha! Can I suggest another way to approach it? Add all of the members of each food group to a group (which you can disable if you want). That way you can select all of the members of the group by clicking the dot to the left of the group name. If you use consistent group names then you can search for the name in the group list and then click the dot. As to how to code that, it's a bit tricky but not insanely so and I'm sure the forums will help you get there!

          Hope that helps!
          Andrew

          1. Chad Wahlbrink @Chad2023-08-03 15:40:40.789Z

            @Philip_weinrobe, Andrew's suggestion is a great alternative approach.

            You could take this idea further by having your scripts that color tracks add those tracks to specified groups.

            Here's an example of an implementation for selecting a specified group you could use. You can swap "ALL DRUMS" at the start of this for whichever group you'd like to prep.

            let groupNameToSelect = "ALL DRUMS";
            
            /////////////////////////////////////////////////////////////////////////////////////////////////////
            
            function main() {
                // Collect session group information
                let groups = getTrackGroups();
            
                // Showing all tracks to make sure the tracks in the group are ready to be processed
                sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Show All Tracks"] });
            
                // Filter for the desired group
                groups.filter(name => name.name === groupNameToSelect)[0].groupSelectionBtn.elementClick();
                let selectedTracks = sf.ui.proTools.selectedTracks;
            
                // Ensure those tracks are visible so you can start processing them. 
                ensureAnAudioTrackIsSelectedAndVisible(selectedTracks);
            
                // Uncomment if you want to restore previously shown tracks
                // sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Restore Previously Shown Tracks"] });
            }
            
            main();
            
            /////////////////////////////////////////////////////////////////////////////////////////////////////
            
            // Function - Get Track Group Props
            function getTrackGroups() {
                // Declare Group List
                const groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.is("Group List").first;
                const groupRows = groupList.childrenByRole("AXRow");
            
                sf.ui.proTools.groupsEnsureGroupListIsVisible();
            
                // Map Groups
                const groupsList = groupRows.allItems.map(group => {
            
                    const groupSelectionBtn = group.childrenByRole('AXCell').first.buttons.first;
                    const groupTitleBtnName = group.childrenByRole('AXCell').allItems[1].buttons.first.value.invalidate().value;
            
                    return {
                        name: groupTitleBtnName.split(' - ')[1],
                        groupID: groupTitleBtnName.split(' - ')[0].split(' ').slice(-1)[0],
                        groupSelectionBtn: groupSelectionBtn,
                    }
                });
                return groupsList;
            };
            
            /// Borrowing from Raphael Sepulveda https://forum.soundflow.org/-6034#post-9 to make sure tracks are in view
            
            /**
             * @param {object} arg
             * @param {AxPtTrackHeader[]} [arg.tracks] - Optional. If provided gets top most from those tracks.
             */
            function determineTopMostEditTrack({ tracks } = {}) {
                function getTopMostTrack(tracks) {
                    return tracks.filter(h => h.frame.y >= editTimeLineTopY)[0];
                }
            
                sf.ui.proTools.mainWindow.invalidate();
                const editTimeLineTopY = sf.ui.proTools.mainWindow.timelineFocusButton.frame.y;
                return getTopMostTrack(tracks || sf.ui.proTools.visibleTrackHeaders);
            };
            
            /** @param {AxPtTrackHeader} track */
            function isAudioTrack(track) {
                return track.title.value.endsWith('Audio Track ');
            }
            
            function ensureAnAudioTrackIsSelectedAndVisible(audioTracks) {
                if (!sf.ui.proTools.selectedTrackCount || !isAudioTrack(sf.ui.proTools.selectedTrack)) {
                    determineTopMostEditTrack({ tracks: audioTracks }).trackScrollToView();
                } else {
                    sf.ui.proTools.selectedTrack.trackScrollToView();
                }
            }
            
            1. Chad Wahlbrink @Chad2023-08-03 15:42:56.822Z

              Shout out to @raphaelsepulveda's brilliant code for the last couple of functions I'm using to ensure the tracks are in view after selection

              1. PPhilip weinrobe @Philip_weinrobe
                  2023-08-03 18:07:20.870Z

                  this is a great idea and one i was thinking of...since i'm already selecting tracks to color them.

                  weirdly when i run this script it doesn't do anything. for my workflow, i'd be looking for something that functioned like this:

                  1. I select a track(s)

                  2. I fire off a script that
                    A: colors tracks a specific color
                    B: adds track to a specific group (if group doesn't exist, creates that group)

                  3. Once I am done coloring (and therefore grouping) the tracks I fire off a new script that
                    A: selects tracks in an already created and populated specific group
                    B: runs an existing script I already have that's working great to do all the other prep things I do.

                  If I could get this working, I could build the big loop to make it do a whole song at once!
                  Any ideas?
                  I feel like this isn't that hard. I don't code myself, but can maybe try cobbling this together through functions and scripts I already have laying about :)

                  will report back!
                  Philip

                  1. You can all of this with track presets: track presets can set colors and groups. (If the group doesn’t exist it will create it). Make a preset for each food group. You can then make a deck with a with a button for each track type/food group.
                    This is how I prep my sessions.

                    1. In reply toPhilip_weinrobe:
                      Chad Wahlbrink @Chad2023-08-03 19:18:09.639Z

                      Hey @Philip_weinrobe!

                      Note that the code from this post: Using Colors of Tracks to Define Actions #post-4 will only run for you if you have a group in your group list called "ALL DRUMS."

                      I meant it to be a "template" for selecting a named group. You can swap the "ALL DRUMS" in the first line for whatever group you are trying to select for prepping.

                      let groupNameToSelect = "ALL DRUMS";
                      

                      @Chris_Shaw 's suggestion is great for this as well. Recalling a track preset for each "food group" can set the color and group in one go for all selected tracks.
                      1. Chad Wahlbrink @Chad2023-08-03 19:24:03.619Z

                        @Philip_weinrobe, you could use the built-in SoundFlow Template Command under "Track Functions" in the official Pro Tools Package for recalling track presets. This would allow you to build a deck similar to Chris' idea.


                        Alternatively, you could try the command in my CW Pro Tools Utilitiespackage for loading track presets for selected tracks by search.

                        1. Chad Wahlbrink @Chad2023-08-03 20:11:08.545Z2023-08-17 17:50:38.945Z

                          @Philip_weinrobe This is an example of how you could string things together.

                          Drop the names of your foodgroup groups into the array in line 3:

                          // Put All Names of Groups to Prep in the array below 
                          // (in the square brackets, in quotations marks, with commas separating) 
                          let groupsToPrep = ["BASS PREP", "DRUMS PREP", "PERC PREP", "WINDS PREP", "STRINGS PREP", "KEYS PREP", "GTR PREP", "BV PREP", "LV PREP"];
                          
                          let groups = getTrackGroups(),
                              groupNames = groups.map(x => x.name),
                              groupsInSessionToPrep = groupsToPrep.filter(item => groupNames.includes(item)),
                              numberOfGroups = groupsInSessionToPrep.length,
                              currentView = saveCurrentTrackView();
                          if (numberOfGroups == 0) {
                              throw "No Matching Groups Were Found In Session";
                          }
                          
                          try {
                              // For Loop to Repeat Setup action for each group
                              for (let i = 0; i < numberOfGroups; i++) {
                                  // try to select each group
                                  try {
                                      // ↓↓↓ PREP SCRIPT HERE 
                                      if (groupsInSessionToPrep[i] == "BASS PREP") {
                                          selectTracksInGroup(groupsInSessionToPrep[i]);
                                          // sf.soundflow.runCommand({ commandId: ""user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                          sf.ui.proTools.colorsSelect({
                                              colorNumber: 1,
                                              colorBrightness: "Dark",
                                          });
                                      }
                                      if (groupsInSessionToPrep[i] == "DRUMS PREP") {
                                          selectTracksInGroup(groupsInSessionToPrep[i]);
                                          // sf.soundflow.runCommand({ commandId: ""user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                          sf.ui.proTools.colorsSelect({
                                              colorNumber: 1,
                                              colorBrightness: "Light",
                                          });
                                      }
                                      if (groupsInSessionToPrep[i] == "ALL BASS") {
                                          selectTracksInGroup(groupsInSessionToPrep[i]);
                                          // sf.soundflow.runCommand({ commandId: ""user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                          sf.ui.proTools.colorsSelect({
                                              colorNumber: 10,
                                              colorBrightness: "Medium",
                                          });
                                      }
                                      //↑↑↑ PREP SCRIPT HERE ↑↑↑
                                  }
                                  catch (err) {
                                      throw err;
                                  }
                          
                              }
                          } catch (err) {
                              throw err;
                          } finally {
                              recallAndDeleteTrackView(currentView);
                          }
                          
                          /////////////////////////////////////////////////////////////////////////////////////////////////////
                          
                          // Function - Get Track Group Props
                          function getTrackGroups() {
                              // Declare Group List
                              const groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.is("Group List").first;
                              const groupRows = groupList.childrenByRole("AXRow");
                          
                              sf.ui.proTools.groupsEnsureGroupListIsVisible();
                          
                              // Map Groups
                              const groupsList = groupRows.allItems.map(group => {
                          
                                  const groupSelectionBtn = group.childrenByRole('AXCell').first.buttons.first;
                                  const groupTitleBtnName = group.childrenByRole('AXCell').allItems[1].buttons.first.value.invalidate().value;
                          
                                  return {
                                      name: groupTitleBtnName.split(' - ')[1],
                                      groupID: groupTitleBtnName.split(' - ')[0].split(' ').slice(-1)[0],
                                      groupSelectionBtn: groupSelectionBtn,
                                  }
                              });
                              return groupsList;
                          };
                          
                          /////////////////////////////////////////////////////////////////////////////////////////////////////
                          
                          function selectTracksInGroup(groupname) {
                              // Collect session group information
                              let groups = getTrackGroups();
                          
                              // Showing all tracks to make sure the tracks in the group are ready to be processed
                              sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Show All Tracks"] });
                          
                              // Filter for the desired group
                              groups.filter(name => name.name === groupname)[0].groupSelectionBtn.elementClick();
                              let selectedTracks = sf.ui.proTools.selectedTracks;
                          
                              // Ensure those tracks are visible so you can start processing them. 
                              ensureAnAudioTrackIsSelectedAndVisible(selectedTracks);
                          
                              // Uncomment if you want to restore previously shown tracks
                              // sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Restore Previously Shown Tracks"] });
                          }
                          
                          /// Borrowing from Raphael Sepulveda https://forum.soundflow.org/-6034#post-9 to make sure tracks are in view
                          
                          /**
                           * @param {object} arg
                           * @param {AxPtTrackHeader[]} [arg.tracks] - Optional. If provided gets top most from those tracks.
                           */
                          function determineTopMostEditTrack({ tracks } = {}) {
                              function getTopMostTrack(tracks) {
                                  return tracks.filter(h => h.frame.y >= editTimeLineTopY)[0];
                              }
                          
                              sf.ui.proTools.mainWindow.invalidate();
                              const editTimeLineTopY = sf.ui.proTools.mainWindow.timelineFocusButton.frame.y;
                              return getTopMostTrack(tracks || sf.ui.proTools.visibleTrackHeaders);
                          };
                          
                          /** @param {AxPtTrackHeader} track */
                          function isAudioTrack(track) {
                              return track.title.value.endsWith('Audio Track ');
                          }
                          
                          function ensureAnAudioTrackIsSelectedAndVisible(audioTracks) {
                              if (!sf.ui.proTools.selectedTrackCount || !isAudioTrack(sf.ui.proTools.selectedTrack)) {
                                  determineTopMostEditTrack({ tracks: audioTracks }).trackScrollToView();
                              } else {
                                  sf.ui.proTools.selectedTrack.trackScrollToView();
                              }
                          }
                          
                          /// Borrowing from Andrew Scheps https://soundflow.org/store/pkg/screen-layout-helper-functions to make sure tracks are in view
                          
                          function saveCurrentTrackView() {
                              sf.ui.proTools.appActivateMainWindow();
                          
                              let memLocWinExists = sf.ui.proTools.memoryLocationsWindow.exists;
                          
                              // create a new memory location
                              sf.keyboard.press({
                                  keys: "numpad enter",
                              });
                              sf.ui.proTools.newMemoryLocationDialog.elementWaitFor();
                              //Wait for the Mem Location dialog to appear and assign it to the memLocDlg variable
                              var memLocDlg = sf.ui.proTools.dialogWaitForManual({
                                  dialogTitle: 'New Memory Location'
                              }).dialog;
                          
                              // We only want to store the track visibilty so clear all check boxes and then check the appropriate one
                              var checkBoxes = memLocDlg.getElements("AXChildren").filter(function (e) { return e.fullRole == "AXCheckBox" });
                              for (var i = 0; i < 6; i++) {
                                  checkBoxes[i].checkboxSet({
                                      targetValue: "Disable",
                                  });
                              }
                              checkBoxes[2].checkboxSet({
                                  targetValue: "Enable",
                              });
                              checkBoxes[3].checkboxSet({
                                  targetValue: "Enable",
                              });
                          
                              //Name the Location Track Visibilty
                              sf.ui.proTools.newMemoryLocationDialog.textFields.allItems[0].elementSetTextFieldWithAreaValue({
                                  value: "Track Visibility",
                              });
                          
                              //Get the Location Number and pass it back so we can delete it when we're done
                              var locationNumber = sf.ui.proTools.newMemoryLocationDialog.textFields.allItems[1].value.value;
                          
                              // Set time Properties to none
                              sf.ui.proTools.newMemoryLocationDialog.radioButtons.allItems[2].elementClick();
                          
                              //Create the Location
                              sf.ui.proTools.newMemoryLocationDialog.buttons.whoseTitle.is('OK').first.elementClick();
                          
                              sf.ui.proTools.newMemoryLocationDialog.elementWaitFor({
                                  waitType: "Disappear",
                              });
                          
                              return { locationNumber, memLocWinExists };
                          }
                          
                          
                          function recallAndDeleteTrackView(lastView) {
                              sf.ui.proTools.memoryLocationsGoto({
                                  memoryLocationNumber: Number(lastView.locationNumber),
                              });
                          
                              sf.ui.proTools.memoryLocationsShowWindow();
                          
                              sf.ui.proTools.memoryLocationsWindow.popupButtons.first.popupMenuSelect({
                                  menuSelector: items => items.filter(i => i.names[0].match(/^Clear \"/))[0]
                              });
                          
                              if (!lastView.memLocWinExists) {
                                  sf.ui.proTools.menuClick({
                                      menuPath: ["Window", "Memory Locations"],
                                      targetValue: 'Disable'  //or 'Enable' or 'Toggle'
                                  });
                                  sf.ui.proTools.memoryLocationsWindow.elementWaitFor({
                                      waitType: "Disappear",
                                  });
                              }
                          }
                          
                          1. Chad Wahlbrink @Chad2023-08-03 20:13:20.025Z
                            1. Chad Wahlbrink @Chad2023-08-03 20:29:05.749Z

                              One final note on this... In the video, I mentioned that you'd need the group to be present in the session for this to work. That'd be super fiddly, so I changed that just now.

                              I tweaked the script so that you can list all of your "food group" track groups.

                              Now, the script tries to select each group and continues to the next one if the current group doesn't exist. That way, you could build this out to do everything you want and then have a button to prep all the groups in one go.

                              It's also possible that just setting up robust track presets is enough to get you the functionality you want. However, this more automated approach could be handy if you are trying to move tracks to specific folders or places in the session.

                              1. PPhilip weinrobe @Philip_weinrobe
                                  2023-08-17 14:58:42.567Z

                                  hi all!
                                  this is working great and i'm building it out.
                                  the only issue is it relies on me having all these track presets on my computer for the scripts to go find.
                                  when i am at other studios, this will fail.
                                  how do I make a script that creates the presets on the fly? i looked in the store for a tool like this.
                                  i know a lot of @Chris_Shaw scripts do this but couldn't find a tool to build my own from a template/preset system.

                                  any advice here appreciated!

                                  philip

                                  1. Chad Wahlbrink @Chad2023-08-17 15:21:31.481Z

                                    Would backing up the "Track Presets" folder from "~/Documents/Pro Tools/Track Presets" to an external hard drive be a valid option for this? Then you could just pop a folder of presets onto the studio computer and delete them at the end of the session if necessary.


                                    Building the presets on the fly would take a good amount of work since they may use "custom I/O" for sends, etc.

                                  2. In reply toChad:
                                    PPhilip weinrobe @Philip_weinrobe
                                      2023-08-17 15:20:44.820Z

                                      Hi Chad!
                                      i got the script working with presets but actually having trouble inserting my own "prep script" in now.
                                      i have a huge macro i am trying to call.
                                      Can i call it with a command ID?
                                      How do I do that?
                                      for example, I want ALL BASS to run a specific command ID in the place where you now have it simply changing the color.

                                      Thank you! I tried, but failed.

                                      1. Chad Wahlbrink @Chad2023-08-17 15:43:43.011Z2023-08-17 18:14:10.639Z

                                        Hey @Philip_weinrobe.

                                        You would need to use sf.sfoundflow.runcommand({}) to run a separate macro for each group. So the structure would look like this:

                                        // ↓↓↓ PREP SCRIPT HERE 
                                            if (groupsInSessionToPrep[i] == "ALL DRUMS") {
                                               selectTracksInGroup(groupsInSessionToPrep[i]); 
                                               sf.soundflow.runCommand({ commandId: "user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                            }
                                            if (groupsInSessionToPrep[i] == "ALL PERC") {
                                                selectTracksInGroup(groupsInSessionToPrep[i]);
                                        		sf.soundflow.runCommand({ commandId: "user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                            }
                                            if (groupsInSessionToPrep[i] == "ALL BASS") {
                                        		selectTracksInGroup(groupsInSessionToPrep[i]);
                                                sf.soundflow.runCommand({ commandId: "user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                            }
                                            //↑↑↑ PREP SCRIPT HERE ↑↑↑
                                        

                                        To get the command ID of the macros you'd like to run for each group, you can select the macro in SoundFlow, and click the menu item "Command" -> "Copy Command ID." This should copy a bit of text in the format of "user:xxxxxxxxxxxx:xxxxxxxxxxxx" to your clipboard to insert in each runCommand action.
                                        Let me know if that works for your scenario.
                                        1. PPhilip weinrobe @Philip_weinrobe
                                            2023-08-17 15:53:25.186Z

                                            this is working!
                                            only issue now is that somehwere in your script it is causing my hidden and inactive tracks to become visible.
                                            anyways to change that?

                                            1. In reply toPhilip_weinrobe:
                                              Chad Wahlbrink @Chad2023-08-17 16:44:05.660Z

                                              I updated the original script to restore your tracks shown at the end of the script.


                                              Note: I also tweaked the script to only run on groups that are present in the session. So it will only run 3 times if it only finds 3 of the possible groups. Previously, it would try to run for each group in line 3

                                              1. PPhilip weinrobe @Philip_weinrobe
                                                  2023-08-17 17:22:45.267Z

                                                  hi! amazing
                                                  just updated to the newest script but now it just follows the order in the array regardless of group name.
                                                  for example, my session had no "BASS" group but since "BASS" was first in my array it grabbed my actual first group (which was WINDS) and prepped it using the "BASS" commandID.

                                                  The last version of the script didn't do this. However, the last version did not skip a group if it wasn't present. Which is important since my array is exhaustive but each session usually doesn't have each "prep group" represented.

                                                  So close!

                                                  btw: here's where my script is at. maybe you could see if i did something wrong when inputting my variables?
                                                  i copied some over from an earlier version so i didn't have to type it all again? maybe i did that wrong

                                                  1. In reply toPhilip_weinrobe:
                                                    PPhilip weinrobe @Philip_weinrobe
                                                      2023-08-17 17:23:16.299Z
                                                      // Put All Names of Groups to Prep in the array below 
                                                      // (in the square brackets, in quotations marks, with commas separating) 
                                                      let groupsToPrep = ["BASS PREP", "DRUMS PREP", "PERC PREP", "WINDS PREP", "STRINGS PREP", "KEYS PREP", "GTR PREP", "BV PREP", "LV PREP"];
                                                      
                                                      let groups = getTrackGroups(),
                                                          groupNames = groups.map(x => x.name),
                                                          groupsInSessionToPrep = groupsToPrep.filter(item => groupNames.includes(item)),
                                                          numberOfGroups = groupsInSessionToPrep.length,
                                                          currentView = saveCurrentTrackView();
                                                      if (numberOfGroups == 0) {
                                                          throw "No Matching Groups Were Found In Session";
                                                      }
                                                      
                                                      try {
                                                          // For Loop to Repeat Setup action for each group
                                                          for (let i = 0; i < numberOfGroups; i++) {
                                                              // try to select each group
                                                              try {
                                                                  selectTracksInGroup(groupsInSessionToPrep[i]);
                                                      
                                                                  // ↓↓↓ PREP SCRIPT HERE 
                                                                  if (groupsToPrep[i] == "BASS PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurl84zv000j5a10hpxrowb1" });
                                                          }
                                                          if (groupsToPrep[i] == "DRUMS PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurl9hqm000k5a100o6u5vd2" });
                                                          }
                                                          if (groupsToPrep[i] == "PERC PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurdj4ei000f5a107oskemu9" });
                                                          }
                                                          if (groupsToPrep[i] == "WINDS PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckyj8fl9w000pzw10al04orr2" });
                                                          }
                                                          if (groupsToPrep[i] == "STRINGS PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckyj8i1r1000rzw10g1az86rq" });
                                                          }
                                                          if (groupsToPrep[i] == "KEYS PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurd9xkj00095a103lxmcvm5" });
                                                          }
                                                          if (groupsToPrep[i] == "GTR PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurdc58j000b5a10m0hivul1" });
                                                          }
                                                          if (groupsToPrep[i] == "BV PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurldlpx000n5a10nyehvf8v" });
                                                          }
                                                          if (groupsToPrep[i] == "LV PREP") {
                                                              sf.soundflow.runCommand({ commandId: "user:default:ckurdeln9000d5a10fx2wzso7" });
                                                          }
                                                          
                                                      
                                                                  //↑↑↑ PREP SCRIPT HERE ↑↑↑
                                                              }
                                                              catch (err) {
                                                                  throw err;
                                                              }
                                                      
                                                          }
                                                      } catch (err) {
                                                          throw err;
                                                      } finally {
                                                          recallAndDeleteTrackView(currentView);
                                                      }
                                                      
                                                      /////////////////////////////////////////////////////////////////////////////////////////////////////
                                                      
                                                      // Function - Get Track Group Props
                                                      function getTrackGroups() {
                                                          // Declare Group List
                                                          const groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.is("Group List").first;
                                                          const groupRows = groupList.childrenByRole("AXRow");
                                                      
                                                          sf.ui.proTools.groupsEnsureGroupListIsVisible();
                                                      
                                                          // Map Groups
                                                          const groupsList = groupRows.allItems.map(group => {
                                                      
                                                              const groupSelectionBtn = group.childrenByRole('AXCell').first.buttons.first;
                                                              const groupTitleBtnName = group.childrenByRole('AXCell').allItems[1].buttons.first.value.invalidate().value;
                                                      
                                                              return {
                                                                  name: groupTitleBtnName.split(' - ')[1],
                                                                  groupID: groupTitleBtnName.split(' - ')[0].split(' ').slice(-1)[0],
                                                                  groupSelectionBtn: groupSelectionBtn,
                                                              }
                                                          });
                                                          return groupsList;
                                                      };
                                                      
                                                      /////////////////////////////////////////////////////////////////////////////////////////////////////
                                                      
                                                      function selectTracksInGroup(groupname) {
                                                          // Collect session group information
                                                          let groups = getTrackGroups();
                                                      
                                                          // Showing all tracks to make sure the tracks in the group are ready to be processed
                                                          sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Show All Tracks"] });
                                                      
                                                          // Filter for the desired group
                                                          groups.filter(name => name.name === groupname)[0].groupSelectionBtn.elementClick();
                                                          let selectedTracks = sf.ui.proTools.selectedTracks;
                                                      
                                                          // Ensure those tracks are visible so you can start processing them. 
                                                          ensureAnAudioTrackIsSelectedAndVisible(selectedTracks);
                                                      
                                                          // Uncomment if you want to restore previously shown tracks
                                                          // sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Restore Previously Shown Tracks"] });
                                                      }
                                                      
                                                      /// Borrowing from Raphael Sepulveda https://forum.soundflow.org/-6034#post-9 to make sure tracks are in view
                                                      
                                                      /**
                                                       * @param {object} arg
                                                       * @param {AxPtTrackHeader[]} [arg.tracks] - Optional. If provided gets top most from those tracks.
                                                       */
                                                      function determineTopMostEditTrack({ tracks } = {}) {
                                                          function getTopMostTrack(tracks) {
                                                              return tracks.filter(h => h.frame.y >= editTimeLineTopY)[0];
                                                          }
                                                      
                                                          sf.ui.proTools.mainWindow.invalidate();
                                                          const editTimeLineTopY = sf.ui.proTools.mainWindow.timelineFocusButton.frame.y;
                                                          return getTopMostTrack(tracks || sf.ui.proTools.visibleTrackHeaders);
                                                      };
                                                      
                                                      /** @param {AxPtTrackHeader} track */
                                                      function isAudioTrack(track) {
                                                          return track.title.value.endsWith('Audio Track ');
                                                      }
                                                      
                                                      function ensureAnAudioTrackIsSelectedAndVisible(audioTracks) {
                                                          if (!sf.ui.proTools.selectedTrackCount || !isAudioTrack(sf.ui.proTools.selectedTrack)) {
                                                              determineTopMostEditTrack({ tracks: audioTracks }).trackScrollToView();
                                                          } else {
                                                              sf.ui.proTools.selectedTrack.trackScrollToView();
                                                          }
                                                      }
                                                      
                                                      /// Borrowing from Andrew Scheps https://soundflow.org/store/pkg/screen-layout-helper-functions to make sure tracks are in view
                                                      
                                                      function saveCurrentTrackView() {
                                                          sf.ui.proTools.appActivateMainWindow();
                                                      
                                                          let memLocWinExists = sf.ui.proTools.memoryLocationsWindow.exists;
                                                      
                                                          // create a new memory location
                                                          sf.keyboard.press({
                                                              keys: "numpad enter",
                                                          });
                                                          sf.ui.proTools.newMemoryLocationDialog.elementWaitFor();
                                                          //Wait for the Mem Location dialog to appear and assign it to the memLocDlg variable
                                                          var memLocDlg = sf.ui.proTools.dialogWaitForManual({
                                                              dialogTitle: 'New Memory Location'
                                                          }).dialog;
                                                      
                                                          // We only want to store the track visibilty so clear all check boxes and then check the appropriate one
                                                          var checkBoxes = memLocDlg.getElements("AXChildren").filter(function (e) { return e.fullRole == "AXCheckBox" });
                                                          for (var i = 0; i < 6; i++) {
                                                              checkBoxes[i].checkboxSet({
                                                                  targetValue: "Disable",
                                                              });
                                                          }
                                                          checkBoxes[2].checkboxSet({
                                                              targetValue: "Enable",
                                                          });
                                                          checkBoxes[3].checkboxSet({
                                                              targetValue: "Enable",
                                                          });
                                                      
                                                          //Name the Location Track Visibilty
                                                          sf.ui.proTools.newMemoryLocationDialog.textFields.allItems[0].elementSetTextFieldWithAreaValue({
                                                              value: "Track Visibility",
                                                          });
                                                      
                                                          //Get the Location Number and pass it back so we can delete it when we're done
                                                          var locationNumber = sf.ui.proTools.newMemoryLocationDialog.textFields.allItems[1].value.value;
                                                      
                                                          // Set time Properties to none
                                                          sf.ui.proTools.newMemoryLocationDialog.radioButtons.allItems[2].elementClick();
                                                      
                                                          //Create the Location
                                                          sf.ui.proTools.newMemoryLocationDialog.buttons.whoseTitle.is('OK').first.elementClick();
                                                      
                                                          sf.ui.proTools.newMemoryLocationDialog.elementWaitFor({
                                                              waitType: "Disappear",
                                                          });
                                                      
                                                          return { locationNumber, memLocWinExists };
                                                      }
                                                      
                                                      
                                                      function recallAndDeleteTrackView(lastView) {
                                                          sf.ui.proTools.memoryLocationsGoto({
                                                              memoryLocationNumber: Number(lastView.locationNumber),
                                                          });
                                                      
                                                          sf.ui.proTools.memoryLocationsShowWindow();
                                                      
                                                          sf.ui.proTools.memoryLocationsWindow.popupButtons.first.popupMenuSelect({
                                                              menuSelector: items => items.filter(i => i.names[0].match(/^Clear \"/))[0]
                                                          });
                                                      
                                                          if (!lastView.memLocWinExists) {
                                                              sf.ui.proTools.menuClick({
                                                                  menuPath: ["Window", "Memory Locations"],
                                                                  targetValue: 'Disable'  //or 'Enable' or 'Toggle'
                                                              });
                                                              sf.ui.proTools.memoryLocationsWindow.elementWaitFor({
                                                                  waitType: "Disappear",
                                                              });
                                                          }
                                                      }
                                                      
                                                      1. Chad Wahlbrink @Chad2023-08-17 17:49:09.124Z

                                                        Hey @Philip_weinrobe


                                                        Give this a shot:

                                                        // Put All Names of Groups to Prep in the array below 
                                                        // (in the square brackets, in quotations marks, with commas separating) 
                                                        let groupsToPrep = ["BASS PREP", "DRUMS PREP", "PERC PREP", "WINDS PREP", "STRINGS PREP", "KEYS PREP", "GTR PREP", "BV PREP", "LV PREP"];
                                                        
                                                        let groups = getTrackGroups(),
                                                            groupNames = groups.map(x => x.name),
                                                            groupsInSessionToPrep = groupsToPrep.filter(item => groupNames.includes(item)),
                                                            numberOfGroups = groupsInSessionToPrep.length,
                                                            currentView = saveCurrentTrackView();
                                                        if (numberOfGroups == 0) {
                                                            throw "No Matching Groups Were Found In Session";
                                                        }
                                                        
                                                        try {
                                                            // For Loop to Repeat Setup action for each group
                                                            for (let i = 0; i < numberOfGroups; i++) {
                                                                // try to select each group
                                                                try {
                                                                    // ↓↓↓ PREP SCRIPT HERE 
                                                                    if (groupsInSessionToPrep[i] == "BASS PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurl84zv000j5a10hpxrowb1" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "DRUMS PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurl9hqm000k5a100o6u5vd2" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "PERC PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurdj4ei000f5a107oskemu9" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "WINDS PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckyj8fl9w000pzw10al04orr2" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "STRINGS PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckyj8i1r1000rzw10g1az86rq" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "KEYS PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurd9xkj00095a103lxmcvm5" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "GTR PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurdc58j000b5a10m0hivul1" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "BV PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurldlpx000n5a10nyehvf8v" });
                                                                    }
                                                                    if (groupsInSessionToPrep[i] == "LV PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:default:ckurdeln9000d5a10fx2wzso7" });
                                                                    }
                                                                    //↑↑↑ PREP SCRIPT HERE ↑↑↑
                                                                }
                                                                catch (err) {
                                                                    throw err;
                                                                }
                                                        
                                                            }
                                                        } catch (err) {
                                                            throw err;
                                                        } finally {
                                                            recallAndDeleteTrackView(currentView);
                                                        }
                                                        
                                                        /////////////////////////////////////////////////////////////////////////////////////////////////////
                                                        
                                                        // Function - Get Track Group Props
                                                        function getTrackGroups() {
                                                            // Declare Group List
                                                            const groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.is("Group List").first;
                                                            const groupRows = groupList.childrenByRole("AXRow");
                                                        
                                                            sf.ui.proTools.groupsEnsureGroupListIsVisible();
                                                        
                                                            // Map Groups
                                                            const groupsList = groupRows.allItems.map(group => {
                                                        
                                                                const groupSelectionBtn = group.childrenByRole('AXCell').first.buttons.first;
                                                                const groupTitleBtnName = group.childrenByRole('AXCell').allItems[1].buttons.first.value.invalidate().value;
                                                        
                                                                return {
                                                                    name: groupTitleBtnName.split(' - ')[1],
                                                                    groupID: groupTitleBtnName.split(' - ')[0].split(' ').slice(-1)[0],
                                                                    groupSelectionBtn: groupSelectionBtn,
                                                                }
                                                            });
                                                            return groupsList;
                                                        };
                                                        
                                                        /////////////////////////////////////////////////////////////////////////////////////////////////////
                                                        
                                                        function selectTracksInGroup(groupname) {
                                                            // Collect session group information
                                                            let groups = getTrackGroups();
                                                        
                                                            // Showing all tracks to make sure the tracks in the group are ready to be processed
                                                            sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Show All Tracks"] });
                                                        
                                                            // Filter for the desired group
                                                            groups.filter(name => name.name === groupname)[0].groupSelectionBtn.elementClick();
                                                            let selectedTracks = sf.ui.proTools.selectedTracks;
                                                        
                                                            // Ensure those tracks are visible so you can start processing them. 
                                                            ensureAnAudioTrackIsSelectedAndVisible(selectedTracks);
                                                        
                                                            // Uncomment if you want to restore previously shown tracks
                                                            // sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Restore Previously Shown Tracks"] });
                                                        }
                                                        
                                                        /// Borrowing from Raphael Sepulveda https://forum.soundflow.org/-6034#post-9 to make sure tracks are in view
                                                        
                                                        /**
                                                         * @param {object} arg
                                                         * @param {AxPtTrackHeader[]} [arg.tracks] - Optional. If provided gets top most from those tracks.
                                                         */
                                                        function determineTopMostEditTrack({ tracks } = {}) {
                                                            function getTopMostTrack(tracks) {
                                                                return tracks.filter(h => h.frame.y >= editTimeLineTopY)[0];
                                                            }
                                                        
                                                            sf.ui.proTools.mainWindow.invalidate();
                                                            const editTimeLineTopY = sf.ui.proTools.mainWindow.timelineFocusButton.frame.y;
                                                            return getTopMostTrack(tracks || sf.ui.proTools.visibleTrackHeaders);
                                                        };
                                                        
                                                        /** @param {AxPtTrackHeader} track */
                                                        function isAudioTrack(track) {
                                                            return track.title.value.endsWith('Audio Track ');
                                                        }
                                                        
                                                        function ensureAnAudioTrackIsSelectedAndVisible(audioTracks) {
                                                            if (!sf.ui.proTools.selectedTrackCount || !isAudioTrack(sf.ui.proTools.selectedTrack)) {
                                                                determineTopMostEditTrack({ tracks: audioTracks }).trackScrollToView();
                                                            } else {
                                                                sf.ui.proTools.selectedTrack.trackScrollToView();
                                                            }
                                                        }
                                                        
                                                        /// Borrowing from Andrew Scheps https://soundflow.org/store/pkg/screen-layout-helper-functions to make sure tracks are in view
                                                        
                                                        function saveCurrentTrackView() {
                                                            sf.ui.proTools.appActivateMainWindow();
                                                        
                                                            let memLocWinExists = sf.ui.proTools.memoryLocationsWindow.exists;
                                                        
                                                            // create a new memory location
                                                            sf.keyboard.press({
                                                                keys: "numpad enter",
                                                            });
                                                            sf.ui.proTools.newMemoryLocationDialog.elementWaitFor();
                                                            //Wait for the Mem Location dialog to appear and assign it to the memLocDlg variable
                                                            var memLocDlg = sf.ui.proTools.dialogWaitForManual({
                                                                dialogTitle: 'New Memory Location'
                                                            }).dialog;
                                                        
                                                            // We only want to store the track visibilty so clear all check boxes and then check the appropriate one
                                                            var checkBoxes = memLocDlg.getElements("AXChildren").filter(function (e) { return e.fullRole == "AXCheckBox" });
                                                            for (var i = 0; i < 6; i++) {
                                                                checkBoxes[i].checkboxSet({
                                                                    targetValue: "Disable",
                                                                });
                                                            }
                                                            checkBoxes[2].checkboxSet({
                                                                targetValue: "Enable",
                                                            });
                                                            checkBoxes[3].checkboxSet({
                                                                targetValue: "Enable",
                                                            });
                                                        
                                                            //Name the Location Track Visibilty
                                                            sf.ui.proTools.newMemoryLocationDialog.textFields.allItems[0].elementSetTextFieldWithAreaValue({
                                                                value: "Track Visibility",
                                                            });
                                                        
                                                            //Get the Location Number and pass it back so we can delete it when we're done
                                                            var locationNumber = sf.ui.proTools.newMemoryLocationDialog.textFields.allItems[1].value.value;
                                                        
                                                            // Set time Properties to none
                                                            sf.ui.proTools.newMemoryLocationDialog.radioButtons.allItems[2].elementClick();
                                                        
                                                            //Create the Location
                                                            sf.ui.proTools.newMemoryLocationDialog.buttons.whoseTitle.is('OK').first.elementClick();
                                                        
                                                            sf.ui.proTools.newMemoryLocationDialog.elementWaitFor({
                                                                waitType: "Disappear",
                                                            });
                                                        
                                                            return { locationNumber, memLocWinExists };
                                                        }
                                                        
                                                        
                                                        function recallAndDeleteTrackView(lastView) {
                                                            sf.ui.proTools.memoryLocationsGoto({
                                                                memoryLocationNumber: Number(lastView.locationNumber),
                                                            });
                                                        
                                                            sf.ui.proTools.memoryLocationsShowWindow();
                                                        
                                                            sf.ui.proTools.memoryLocationsWindow.popupButtons.first.popupMenuSelect({
                                                                menuSelector: items => items.filter(i => i.names[0].match(/^Clear \"/))[0]
                                                            });
                                                        
                                                            if (!lastView.memLocWinExists) {
                                                                sf.ui.proTools.menuClick({
                                                                    menuPath: ["Window", "Memory Locations"],
                                                                    targetValue: 'Disable'  //or 'Enable' or 'Toggle'
                                                                });
                                                                sf.ui.proTools.memoryLocationsWindow.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                });
                                                            }
                                                        }
                                                        
                                                      2. In reply toPhilip_weinrobe:
                                                        Chad Wahlbrink @Chad2023-08-17 17:58:38.366Z

                                                        The issue was in this structure:

                                                        if (groupsInSessionToPrep[i] == "BASS PREP") {
                                                                        selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                        sf.soundflow.runCommand({ commandId: "user:xxxxxxxxxxxx:xxxxxxxxxxxx" });
                                                                    }
                                                        

                                                        Previously, the scripted pointed to both the non-filtered list (groupsToPrep) and the filtered list (groupsInSessionToPrep).

                                                        1. PPhilip weinrobe @Philip_weinrobe
                                                            2023-08-17 18:01:36.627Z

                                                            awesome, will try in next 10 minutes and report back :)

                                                            1. PPhilip weinrobe @Philip_weinrobe
                                                                2023-08-17 19:04:59.879Z

                                                                i think we are in business :)

                                                                1. PPhilip weinrobe @Philip_weinrobe
                                                                    2023-08-17 19:41:08.812Z

                                                                    ok, something keeps crashing when the script is interacting with your track visibility marker.
                                                                    i think, based on how i use this, it's not necessary.

                                                                    is there a way to remove that whole track visibility functionality?

                                                                    1. PPhilip weinrobe @Philip_weinrobe
                                                                        2023-08-17 19:43:37.882Z

                                                                        the script is failing randomly but each time i check the script line it fails at via the log it's something to do with the track visibility memory location. let's just try commenting all that stuff out. i bet it will work great.

                                                                        1. Chad Wahlbrink @Chad2023-08-17 20:27:39.199Z

                                                                          @Philip_weinrobe, heard! I was adapting that from an older script and didn't thoroughly test it. I had to update it for 2023.6 since the memory locations changed significantly for that release.

                                                                          Try this one:

                                                                          // Put All Names of Groups to Prep in the array below 
                                                                          // (in the square brackets, in quotations marks, with commas separating) 
                                                                          let groupsToPrep = ["BASS PREP", "DRUMS PREP", "PERC PREP", "WINDS PREP", "STRINGS PREP", "KEYS PREP", "GTR PREP", "BV PREP", "LV PREP"];
                                                                          
                                                                          let groups = getTrackGroups(),
                                                                              groupNames = groups.map(x => x.name),
                                                                              groupsInSessionToPrep = groupsToPrep.filter(item => groupNames.includes(item)),
                                                                              numberOfGroups = groupsInSessionToPrep.length
                                                                          if (numberOfGroups == 0) {
                                                                              throw "No Matching Groups Were Found In Session";
                                                                          }
                                                                          
                                                                          // For Loop to Repeat Setup action for each group
                                                                          for (let i = 0; i < numberOfGroups; i++) {
                                                                              // try to select each group
                                                                              try {
                                                                                  // ↓↓↓ PREP SCRIPT HERE 
                                                                                  if (groupsInSessionToPrep[i] == "BASS PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurl84zv000j5a10hpxrowb1" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "DRUMS PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurl9hqm000k5a100o6u5vd2" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "PERC PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurdj4ei000f5a107oskemu9" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "WINDS PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckyj8fl9w000pzw10al04orr2" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "STRINGS PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckyj8i1r1000rzw10g1az86rq" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "KEYS PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurd9xkj00095a103lxmcvm5" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "GTR PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurdc58j000b5a10m0hivul1" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "BV PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurldlpx000n5a10nyehvf8v" });
                                                                                  }
                                                                                  if (groupsInSessionToPrep[i] == "LV PREP") {
                                                                                      selectTracksInGroup(groupsInSessionToPrep[i]);
                                                                                      sf.soundflow.runCommand({ commandId: "user:default:ckurdeln9000d5a10fx2wzso7" });
                                                                                  }
                                                                                  //↑↑↑ PREP SCRIPT HERE ↑↑↑
                                                                              }
                                                                              catch (err) {
                                                                                  throw err;
                                                                              }
                                                                          }
                                                                          
                                                                          /////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                          
                                                                          // Function - Get Track Group Props
                                                                          function getTrackGroups() {
                                                                              // Declare Group List
                                                                              const groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.is("Group List").first;
                                                                              const groupRows = groupList.childrenByRole("AXRow");
                                                                          
                                                                              sf.ui.proTools.groupsEnsureGroupListIsVisible();
                                                                          
                                                                              // Map Groups
                                                                              const groupsList = groupRows.allItems.map(group => {
                                                                          
                                                                                  const groupSelectionBtn = group.childrenByRole('AXCell').first.buttons.first;
                                                                                  const groupTitleBtnName = group.childrenByRole('AXCell').allItems[1].buttons.first.value.invalidate().value;
                                                                          
                                                                                  return {
                                                                                      name: groupTitleBtnName.split(' - ')[1],
                                                                                      groupID: groupTitleBtnName.split(' - ')[0].split(' ').slice(-1)[0],
                                                                                      groupSelectionBtn: groupSelectionBtn,
                                                                                  }
                                                                              });
                                                                              return groupsList;
                                                                          };
                                                                          
                                                                          
                                                                          /////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                          
                                                                          function selectTracksInGroup(groupname) {
                                                                              // Collect session group information
                                                                              let groups = getTrackGroups();
                                                                          
                                                                              // Showing all tracks to make sure the tracks in the group are ready to be processed
                                                                              sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Show All Tracks"] });
                                                                          
                                                                              // Filter for the desired group
                                                                              groups.filter(name => name.name === groupname)[0].groupSelectionBtn.elementClick();
                                                                              let selectedTracks = sf.ui.proTools.selectedTracks;
                                                                          
                                                                              // Ensure those tracks are visible so you can start processing them. 
                                                                              ensureAnAudioTrackIsSelectedAndVisible(selectedTracks);
                                                                          
                                                                              // Uncomment if you want to restore previously shown tracks
                                                                              sf.ui.proTools.mainWindow.trackListPopupButton.popupMenuSelect({ menuPath: ["Restore Previously Shown Tracks"] });
                                                                          }
                                                                          
                                                                          /// Borrowing from Raphael Sepulveda https://forum.soundflow.org/-6034#post-9 to make sure tracks are in view
                                                                          
                                                                          /**
                                                                           * @param {object} arg
                                                                           * @param {AxPtTrackHeader[]} [arg.tracks] - Optional. If provided gets top most from those tracks.
                                                                           */
                                                                          function determineTopMostEditTrack({ tracks } = {}) {
                                                                              function getTopMostTrack(tracks) {
                                                                                  return tracks.filter(h => h.frame.y >= editTimeLineTopY)[0];
                                                                              }
                                                                          
                                                                              sf.ui.proTools.mainWindow.invalidate();
                                                                              const editTimeLineTopY = sf.ui.proTools.mainWindow.timelineFocusButton.frame.y;
                                                                              return getTopMostTrack(tracks || sf.ui.proTools.visibleTrackHeaders);
                                                                          };
                                                                          
                                                                          /** @param {AxPtTrackHeader} track */
                                                                          function isAudioTrack(track) {
                                                                              return track.title.value.endsWith('Audio Track ');
                                                                          }
                                                                          
                                                                          function ensureAnAudioTrackIsSelectedAndVisible(audioTracks) {
                                                                              if (!sf.ui.proTools.selectedTrackCount || !isAudioTrack(sf.ui.proTools.selectedTrack)) {
                                                                                  determineTopMostEditTrack({ tracks: audioTracks }).trackScrollToView();
                                                                              } else {
                                                                                  sf.ui.proTools.selectedTrack.trackScrollToView();
                                                                              }
                                                                          }
                                                                          
                                                                          1. PPhilip weinrobe @Philip_weinrobe
                                                                              2023-08-18 00:14:26.282Z

                                                                              ok! failure rate much better. still some random crashes, but not that bad. will keep an eye on it and see if i can figure anything out but using it as-is and it's wonderful and a HUGE timesaver. maybe i'll make a video of it in action. pretty fun to watch :)

                                                                              THANK YOU!

                                                                              1. Chad Wahlbrink @Chad2023-08-18 12:16:41.497Z

                                                                                Stoked it's working @Philip_weinrobe! If you notice any patterns with it failing, let me know and we can try to dial it in a bit more.