No internet connection
  1. Home
  2. How to

Select all/ONLY active tracks?

By Joe Costable @Joe_Costable
    2021-09-02 15:15:39.250Z

    Can't seem to find a solution that works here-

    For context:
    I've created a larger script to deal with archiving a session- Before it gets into "Save Copy In", I'd like it to select all the visible tracks. (it's already hidden inactive and only showing what I am using in the session) This way in the "save copy in" dialog I can check "Selected tracks only".

    I've gotten as far as selecting the ALL group, however it would then require clicking somewhere in the timeline to select all the visible tracks- Which would work except if it clicks on an aux, it will only select auxes. It needs to click on an audio track to grab all of the tracks-

    If I use "click ui element" "First button", it selects even the unused tracks, which won't work for me here.

    There must be a simpler way to select all tracks, or select active tracks in a group, no?

    My other thought is to do a "Save as" and delete the inactive tracks first; but then of course I need to only show inactive tracks and still select/delete them...

    Solved in post #2, click to view
    • 18 replies

    There are 18 replies. Estimated reading time: 53 minutes

    1. Hey Joe,

      The following script will select all visible and active tracks for ya!

      const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
      
      /** @param {{ track: AxPtTrackHeader}} arg */
      function isTrackActive({ track }) {
          if (track.muteButton.exists) {
              return track.muteButton.value.value !== 'inactive';
          }
          return track.outputWindowButton.value.value !== 'inactive';
      }
      
      function getVisibleActiveTracks() {
          let visibleActiveTracks = { trackHeaders: [], trackListItems: [], names: [] };
      
          visibleTracks.trackHeaders.forEach((trackHeader, i) => {
              if (isTrackActive({ track: trackHeader })) {
                  visibleActiveTracks["trackHeaders"].push(trackHeader)
                  visibleActiveTracks["trackListItems"].push(visibleTracks.trackListItems[i])
                  visibleActiveTracks["names"].push(visibleTracks.names[i])
              }
          });
      
          return visibleActiveTracks
      }
      
      /** @param {AxPtTrackListItem} trackListItem */
      function selectTrack(trackListItem) {
          trackListItem.children.whoseRole.is("AXCell").allItems[1].buttons.first.elementClick();
      }
      
      function selectAllVisibleActiveTracks() {
          sf.ui.proTools.appActivateMainWindow();
          sf.ui.proTools.trackDeselectAll();
          getVisibleActiveTracks().trackListItems.forEach(selectTrack)
      }
      
      selectAllVisibleActiveTracks();
      
      Reply2 LikesSolution
      1. Joe Costable @Joe_Costable
          2021-09-02 18:33:39.698Z

          Awesome- Thank you!

          1. Hey @raphaelsepulveda ! How can this script be tweaked to just select all visible tracks regardless of active state?

            1. @Brett_Ryan_Stewart, something simple like this should do!

              sf.ui.proTools.appActivateMainWindow();
              sf.ui.proTools.mainWindow.invalidate();
              
              
              sf.ui.proTools.trackSelectByName({
                  names: sf.ui.proTools.visibleTrackNames
              });
              
              1. You're the best Raphael, thank you!

            2. Yujiro Yonetsu @Yujiro_Yonetsu
                2022-06-25 16:14:25.681Z

                Hello,
                Excuse me for cutting in.

                I am taking advantage of your nice script too and trying to incorporate this into a script that works across multiple sessions.

                But for some reason it does not work.

                Error Message says
                "ReferenceError: visibleTracks is not denied"

                The script I am making is so long that I hesitate to reproduce it here, but in the meantime, here it is
                The error occurs at line 595.

                Script for routing and coloring tracks while automatically switching between multiple sessions.

                
                
                const specificName = event.props.specificName
                
                
                ///////////////////////Basci function
                //comfirmation dialog
                function dismissConfirmationDialog(btn) {
                    if (sf.ui.proTools.confirmationDialog.invalidate().buttons.whoseTitle.is(btn).first.exists) {
                        sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is(btn).first.elementClick();
                    }
                };
                
                
                //save color to preset
                function saveTrackPreset() {
                
                    const tracks = sf.ui.proTools.selectedTrackHeaders
                
                    sf.file.directoryCreate({ path: "~/Documents/Pro Tools/Track Presets/Avid/SF" })
                
                    const presetName = "SF_TrackColorTemp"
                
                    //Scroll firsr track to View
                    tracks[0].trackScrollToView()
                
                    sf.ui.proTools.menuClick({ menuPath: ["Track", "Save Track Preset..."] })
                
                    const saveTrackPresetWin = sf.ui.proTools.windows.whoseTitle.is("Save Track Preset ").first.elementWaitFor({}, "Save Track Preset Win didn't Open.").element
                
                    // Category, choose SF folder
                    if (saveTrackPresetWin.popupButtons.first.value.invalidate().value != "SF") {
                        saveTrackPresetWin.popupButtons.first.popupMenuSelect({ menuPath: ["Avid", "SF"] });
                    }
                
                    // Name preset
                    saveTrackPresetWin.textFields.first.elementSetTextFieldWithAreaValue({ value: presetName });
                
                    //Disable all checkboxes
                    saveTrackPresetWin.checkBoxes.map(cb => cb.checkboxSet({ targetValue: "Disable" }))
                
                    /////
                    //Open track data to recall
                    sf.ui.proTools.windows.whoseTitle.is("Save Track Preset ").first.buttons.whoseTitle.is("Track Data to Recall...").first.elementClick();
                
                    const trackDataToRecallWin = sf.ui.proTools.windows.whoseTitle.is("Track Data to Recall").first.elementWaitFor({}, "Track Data to Recall Win didn't Open.").element
                
                    //Disable all checkboxes
                    trackDataToRecallWin.groups.map(gr => gr.checkBoxes.map(cb => cb.checkboxSet({ targetValue: "Disable" })))
                
                    // Set no offset
                    trackDataToRecallWin.groups.whoseTitle.is("Track Offset Options").first.radioButtons.whoseTitle.is("No Offset").first.checkboxSet({
                        targetValue: "Disable",
                    });
                
                    // Enable track colors
                    trackDataToRecallWin.groups.whoseTitle.is("Track Data").first.checkBoxes.whoseTitle.is("Track Colors").first.checkboxSet({
                        targetValue: "Enable",
                    });
                
                    // Ok 
                    trackDataToRecallWin.buttons.whoseTitle.is("OK").first.elementClick();
                    trackDataToRecallWin.elementWaitFor({ waitType: "Disappear" })
                    /////
                
                
                    saveTrackPresetWin.buttons.whoseTitle.is("OK").first.elementClick();
                    saveTrackPresetWin.elementWaitFor({ waitType: "Disappear" })
                
                    dismissConfirmationDialog("Replace")
                }
                
                
                //coloring by preset
                function recallTrackPreset() {
                
                    const presetName = "SF_TrackColorTemp"
                
                    const tracks = sf.ui.proTools.invalidate().selectedTrackHeaders
                
                    if (sf.ui.proTools.confirmationDialog.exists) {
                        sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is("OK").first.elementClick();
                    }
                
                    tracks[0].popupButtons.first.popupMenuSelect({ menuPath: ["Recall Track Preset", "Avid", "SF", presetName], isRightClick: true })
                
                    dismissConfirmationDialog("OK")
                };
                
                
                //select only audio track in folder
                /**
                     * @param {AxPtTrackHeader} track
                     */
                function getTrackDepth(track) {
                    return Math.floor((track.titleButton.frame.x - track.frame.x) / 15);
                }
                
                function getTrackFolderStructure() {
                    var root = { children: [] };
                    var stack = [];
                    stack[0] = root;
                    var flatList = sf.ui.proTools.visibleTrackHeaders.map(t => ({ track: t, depth: getTrackDepth(t) }));
                    for (var i = 0; i < flatList.length; i++) {
                        var flatItem = flatList[i];
                        var node = {
                            name: flatItem.track.normalizedTrackName,
                            type: flatItem.track.title.value.match(/ - (.*)$/)[1].trim().replace(/track$/i, '').trim().toLowerCase(),
                            track: flatItem.track,
                            children: []
                        };
                        stack[flatItem.depth] = node;
                        stack[flatItem.depth - 1].children.push(node);
                    }
                    return root;
                }
                
                
                function findNearestParentFolder(root, trackName) {
                    var folderStack = [];
                    function walk(node) {
                        var isFolder = node.type && node.type.indexOf('folder') >= 0;
                        if (isFolder) {
                            folderStack.push(node);
                        }
                        if (node.name === trackName) {
                            return folderStack.slice(-1)[0];
                        }
                        for (var i = 0; i < node.children.length; i++) {
                            var res = walk(node.children[i]);
                            if (res) return res;
                        }
                        if (isFolder) {
                            folderStack.pop();
                        }
                    }
                    return walk(root);
                }
                
                /**
                 * @return {AxPtTrackHeader[]}
                 */
                function getTracksInCurrentFolderOfType(trackType) {
                    sf.ui.proTools.mainWindow.invalidate();
                
                    var root = getTrackFolderStructure();
                
                    var nearestFolder = findNearestParentFolder(root, sf.ui.proTools.selectedTrack.normalizedTrackName);
                    if (!nearestFolder)
                        return [];
                
                    return nearestFolder.children.filter(i => i.type === trackType).map(i => i.track);
                }
                
                function selectTracksInCurrentFolderOfType(trackType) {
                    sf.ui.proTools.trackSelectByName({
                        names: getTracksInCurrentFolderOfType('audio').map(t => t.normalizedTrackName),
                    });
                }
                
                function getInputPathOfSelectedTrack() {
                    sf.ui.proTools.appActivateMainWindow();
                    var path = sf.ui.proTools.selectedTrack.inputPathButton.popupMenuFetchAllItems().menuItems.filter(mi => mi.element.isMenuChecked)[0].names;
                    sf.ui.proTools.appActivateMainWindow();
                    return path;
                }
                ////////////////////////Basic function
                
                ///////function for multiple
                
                function closeWindows() {
                    //Close audio plug-in windows
                    sf.ui.proTools.floatingWindows.whoseTitle.startsWith('Plug-in:').allItems.forEach(function (win) {
                        try { win.windowClose(); } catch (err) { }
                    });
                
                    //Close audio suite windows
                    sf.ui.proTools.floatingWindows.whoseTitle.startsWith('Audio Suite').allItems.forEach(function (win) {
                        try { win.windowClose(); } catch (err) { }
                    });
                
                    //close task manager
                    if (sf.ui.proTools.windows.whoseTitle.is("Task Manager").first.exists) {
                        sf.ui.proTools.windows.whoseTitle.is("Task Manager").first.getElement("AXCloseButton").elementClick();
                        sf.ui.proTools.windows.whoseTitle.is("Task Manager").first.elementWaitFor({
                            waitType: "Disappear",
                        });
                    }
                    sf.wait({ intervalMs: 300, });
                
                    //close memory location
                    if (sf.ui.proTools.memoryLocationsWindow.exists) {
                        sf.ui.proTools.memoryLocationsWindow.getElement("AXCloseButton").elementClick();
                        sf.ui.proTools.memoryLocationsWindow.elementWaitFor({
                            waitType: "Disappear",
                        });
                    }
                    sf.wait({ intervalMs: 300, });
                
                    //close transport
                    if (sf.ui.proTools.getMenuItem('Window', 'Transport').isMenuChecked) {
                        sf.ui.proTools.menuClick({
                            menuPath: ['Window', 'Transport'],
                        });
                    }
                    sf.wait({ intervalMs: 200, });
                
                    //close Big Counter
                    if (sf.ui.proTools.getMenuItem('Window', 'Big Counter').isMenuChecked) {
                        sf.ui.proTools.menuClick({
                            menuPath: ['Window', 'Big Counter'],
                        });
                    }
                    sf.wait({ intervalMs: 200, });
                
                    //close Automation setting
                    if (sf.ui.proTools.automationWindow.exists) {
                        sf.ui.proTools.automationWindow.getElement("AXCloseButton").elementClick();
                        sf.ui.proTools.automationWindow.elementWaitFor({
                            waitType: "Disappear",
                        });
                    }
                    sf.wait({ intervalMs: 300, });
                
                    //close Color Palette
                    if (sf.ui.proTools.colorPaletteWindow.exists) {
                        sf.ui.proTools.colorPaletteWindow.getElement("AXCloseButton").elementClick();
                        sf.ui.proTools.colorPaletteWindow.elementWaitFor({
                            waitType: "Disappear",
                        });
                    }
                    sf.wait({ intervalMs: 300, });
                
                    //close System Usage
                    if (sf.ui.proTools.windows.whoseTitle.is("System Usage").first.exists) {
                        sf.ui.proTools.windows.whoseTitle.is("System Usage").first.getElement("AXCloseButton").elementClick();
                        sf.ui.proTools.windows.whoseTitle.is("System Usage").first.elementWaitFor({
                            waitType: "Disappear",
                        });
                    }
                    sf.wait({ intervalMs: 300, });
                
                    //close sessionsetup
                    if (sf.ui.proTools.windows.whoseTitle.is("Session Setup").first.exists) {
                        sf.ui.proTools.windows.whoseTitle.is("Session Setup").first.getElement("AXCloseButton").elementClick();
                        sf.ui.proTools.windows.whoseTitle.is("Session Setup").first.elementWaitFor({
                            waitType: "Disappear",
                        });
                    }
                    sf.wait({ intervalMs: 300, });
                
                    //Hide all floating windows
                    if (sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isMenuChecked) {
                    } else {
                        sf.ui.proTools.menuClick({
                            menuPath: ['Window', 'Hide All Floating Windows'],
                        });
                    }
                    sf.wait({ intervalMs: 200, });
                }
                
                
                function closeOutputWindow() {
                    if (sf.ui.proTools.mainTrackOutputWindow.exists) {
                        sf.ui.proTools.mainTrackOutputWindow.windowClose();
                    }
                    sf.wait({ intervalMs: 90, });
                }
                
                
                
                function saveAndClose() {
                
                    sf.ui.proTools.windows.whoseTitle.is("Task Manager").first.elementWaitFor({
                        waitType: "Appear",
                    });
                
                
                    if (sf.ui.proTools.windows.whoseTitle.is("Task Manager").first.tables.whoseTitle.is("Active Tasks.").first.children.whoseRole.is("AXColumn").whoseTitle.is("TTextGridView_Column ").first.children.whoseRole.is("AXRow").whoseValue.is("# 0 row Queued. ").first.children.whoseRole.is("AXCell").first.children.whoseRole.is("AXStaticText").first.value.invalidate().value == "") {
                        //// save and exit procedures
                        if ((sf.ui.proTools.mainWindow.invalidate().sessionPath !== null || sf.ui.proTools.getMenuItem('File', 'Close Session').isEnabled)
                            || sf.ui.proTools.confirmationDialog.exists) {
                
                            sf.wait({
                                intervalMs: 90,
                            });
                
                            sf.ui.proTools.menuClick({ menuPath: ["File", "Save"] });
                
                            sf.ui.proTools.menuClick({ menuPath: ["File", "Close Session"] });
                
                            if (sf.ui.proTools.confirmationDialog.invalidate().buttons.whoseTitle.is('Save').first.exists) {
                                sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('Save').first.elementClick();
                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: "Disappear", onError: "Continue" });
                            }
                
                            sf.ui.proTools.waitForNoModals();
                
                        }
                    }
                    else {
                        sf.wait({
                            intervalMs: 90,
                        });
                        sf.keyboard.press({
                            keys: "cmd+shift+3",
                        });
                        sf.wait({
                            intervalMs: 90,
                        });
                        if ((sf.ui.proTools.mainWindow.invalidate().sessionPath !== null || sf.ui.proTools.getMenuItem('File', 'Close Session').isEnabled)
                            || sf.ui.proTools.confirmationDialog.exists) {
                
                            sf.wait({
                                intervalMs: 90,
                            });
                
                            sf.ui.proTools.menuClick({ menuPath: ["File", "Save"] });
                
                            sf.ui.proTools.menuClick({ menuPath: ["File", "Close Session"] });
                
                            if (sf.ui.proTools.confirmationDialog.invalidate().buttons.whoseTitle.is('Save').first.exists) {
                                sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('Save').first.elementClick();
                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: "Disappear", onError: "Continue" });
                            }
                            if (sf.ui.proTools.confirmationDialog.invalidate().buttons.whoseTitle.is('Close').first.exists) {
                                sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('Close').first.elementClick();
                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: "Disappear", onError: "Continue" });
                            }
                
                            sf.ui.proTools.waitForNoModals();
                        }
                
                    }
                    sf.wait({ intervalMs: 500 })
                }
                
                
                function waitForOpenSession() {
                
                    while (true) {
                
                        if (sf.ui.proTools.windows.whoseTitle.is("Session Notes").first.exists) {
                            sf.ui.proTools.windows.whoseTitle.is("Session Notes").first.buttons.whoseTitle.is("No").first.elementClick();
                            sf.ui.proTools.windows.whoseTitle.is("Session Notes").first.elementWaitFor({
                                waitType: "Disappear",
                            });
                        }
                        sf.wait({ intervalMs: 3000 })
                
                        if (sf.ui.proTools.windows.whoseTitle.is("Missing Files").first.exists) {
                            sf.ui.proTools.windows.whoseTitle.is("Missing Files").first.radioButtons.whoseTitle.is("Automatically Find & Relink").first.elementClick();
                            sf.ui.proTools.windows.whoseTitle.is("Missing Files").first.buttons.whoseTitle.is("OK").first.elementClick();
                            sf.ui.proTools.windows.whoseTitle.is("Missing Files").first.elementWaitFor({
                                waitType: "Disappear",
                            });
                            sf.wait({
                                intervalMs: 3000,
                            });
                            //show edit window
                            sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"] });
                            sf.wait({
                                intervalMs: 3000,
                            });
                            sf.ui.proTools.mainWindow.counterDisplay.mouseClickElement({
                                relativePosition: { x: 237, y: 66 },
                            });
                            sf.ui.proTools.windows.whoseTitle.is("Relink").first.elementWaitFor({
                                waitType: "Appear",
                            });
                            sf.wait({
                                intervalMs: 90,
                            });
                            sf.keyboard.press({
                                keys: "cmd+shift+3",
                            });
                            sf.wait({
                                intervalMs: 90,
                            });
                            sf.ui.proTools.windows.whoseTitle.is("Relink").first.getElement("AXCloseButton").elementClick();
                        }
                        sf.wait({ intervalMs: 500 })
                
                        if ((sf.ui.proTools.mainWindow.invalidate().sessionPath !== null
                            || sf.ui.proTools.getMenuItem('File', 'Close Session').isEnabled)
                        ) {
                            log("session open")
                
                            break;
                        }
                        sf.wait({ intervalMs: 500 })
                    }
                }
                
                
                function closeTaskManager() {
                    if (sf.ui.proTools.getMenuItem('Window', 'Task Manager').isMenuChecked) {
                        sf.ui.proTools.menuClick({
                            menuPath: ['Window', 'Task Manager'],
                        });
                    }
                }
                
                
                function movetaskmanager() {
                    var taskManager = sf.ui.proTools.windows.whoseTitle.is("Task Manager").first.frame;
                    sf.mouse.simulateDrag({
                        startPosition: { "x": taskManager.x + 119, "y": taskManager.y + 8 },
                        endPosition: { "x": taskManager.x + 1000, "y": taskManager.y + 700 },
                    });
                }
                ////////////////////////////////function for multiple
                
                
                
                //active finder
                sf.ui.app('com.apple.finder').appActivateMainWindow();
                
                
                //search session
                function getMakeStemSessions(selectedFolders) {
                    const sessionPath = sf.file.directoryGetFiles({
                        searchPattern: "*" + specificName,
                        path: selectedFolders,
                        isRecursive: true,
                    }).paths[0]
                    allPath.push(sessionPath)
                }
                
                let allPath = []
                
                sf.ui.finder.selectedPaths.forEach(getMakeStemSessions)
                
                
                ////start dialog
                const myDialog = sf.interaction.displayDialog({
                
                    buttons: ["Cancel", "OK"],
                    defaultButton: "OK",
                    cancelButton: "Cancel",
                    title: "Are you ready?",
                    prompt: allPath.length + " Songs, right?"
                
                });
                
                
                
                ////////////////////////////////////////////////Main
                if (myDialog.button == "OK") {
                
                    sf.ui.proTools.appActivate();
                
                    sf.wait({ intervalMs: 300, });
                
                    closeTaskManager();
                
                    sf.wait({ intervalMs: 90, });
                
                    for (var i = 0; i < allPath.length; i++) {
                
                        //session open
                        sf.file.open({
                            path: allPath[i],
                            applicationPath: "/Applications/Pro Tools.app",
                        });
                
                        //  Wait fo menus to become enabled, thus sessioon is fully opened
                        waitForOpenSession();
                
                        sf.wait({ intervalMs: 1000, });
                
                        /////////////////////////////////////////////////////////////////////session start prepare
                        //focus protools
                        sf.ui.proTools.appActivateMainWindow();
                        sf.ui.proTools.mainWindow.invalidate();
                
                        sf.wait({ intervalMs: 90, });
                
                        closeWindows();
                
                        closeOutputWindow();
                
                
                
                
                
                        //go to Edit Win
                        const isEditWin = sf.ui.proTools.focusedWindow.title.value.startsWith("Edit")
                        if (!isEditWin) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"] }) }
                
                        sf.keyboard.press({
                            keys: "p",
                        });
                
                        sf.ui.proTools.selectedTrack.invalidate().trackScrollToView();
                
                
                        //set track height
                        sf.ui.proTools.menuClick({
                            menuPath: ["Edit", "Selection", "Extend Edit Up"],
                        });
                
                        sf.wait({ intervalMs: 80, });
                
                        let trackHeaderFrameWidth = sf.ui.proTools.selectedTrack.frame.w
                
                
                        sf.ui.proTools.invalidate().selectedTrack.popupMenuSelect({
                            relativePosition: { x: trackHeaderFrameWidth - 10, y: 10 },
                            menuPath: ['small'],
                            isOption: true,
                        });
                
                        sf.wait({ intervalMs: 80, });
                
                
                        //close all folder tracks
                        function selectAllFolderTracks() {
                
                            var visibleTracks = sf.ui.proTools.invalidate().trackGetVisibleTracks().names
                            var firstTrackFound;
                            let foundTracks = [];
                
                            while (true) {
                                sf.ui.proTools.trackDeselectAll();
                
                                for (var i = 0; i < visibleTracks.length; i++) {
                
                                    var trackIsFolder = sf.ui.proTools.trackGetByName({ name: visibleTracks[i] }).track.children.whoseRole.is("AXDisclosureTriangle").whoseTitle.is('Close Folder')
                
                                    if (trackIsFolder.exists)
                
                                        if (trackIsFolder) {
                                            if (!firstTrackFound) { // Scroll to first track found
                                                sf.ui.proTools.trackGetByName({ name: visibleTracks[i], }).track.trackScrollToView();
                                                firstTrackFound = !firstTrackFound;
                                            } else {
                                                sf.ui.proTools.trackSelectByName({ names: [visibleTracks[i]], deselectOthers: false });
                                            }
                                            foundTracks.push(visibleTracks[i]);
                                        }
                                }
                                if (foundTracks.length !== 0) {
                                    break;
                                }
                                throw 0;
                            }
                        }
                
                
                        function closeAllFolderTracks() {
                            sf.ui.proTools.appActivateMainWindow();
                            sf.ui.proTools.windows.invalidate();
                
                            selectAllFolderTracks()
                
                            const selectedTracks = sf.ui.proTools.selectedTrackNames.reverse()
                
                            for (var i = 0; i < selectedTracks.length; i++) {
                
                                sf.ui.proTools.invalidate().trackGetByName({ name: selectedTracks[i] }).track.folderTrackSetOpen({
                                    targetValue: 'Disable',
                                });
                            }
                        }
                
                        closeAllFolderTracks()
                
                
                        //select all tracks
                        sf.keyboard.press({
                            keys: "return",
                        });
                
                        sf.ui.proTools.menuClick({
                            menuPath: ["Edit", "Select All"],
                        });
                
                
                        //select only active track
                        const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                
                
                        /** @param {{ track: AxPtTrackHeader}} arg */
                        function isTrackActive({ track }) {
                            if (track.muteButton.exists) {
                                return track.muteButton.value.value !== 'inactive';
                            }
                            return track.outputWindowButton.value.value !== 'inactive';
                        }
                
                        function getVisibleActiveTracks() {
                            let visibleActiveTracks = { trackHeaders: [], trackListItems: [], names: [] };
                
                            visibleTracks.trackHeaders.forEach((trackHeader, i) => {
                                if (isTrackActive({ track: trackHeader })) {
                                    visibleActiveTracks["trackHeaders"].push(trackHeader)
                                    visibleActiveTracks["trackListItems"].push(visibleTracks.trackListItems[i])
                                    visibleActiveTracks["names"].push(visibleTracks.names[i])
                                }
                            });
                
                            return visibleActiveTracks
                        }
                
                        /** @param {AxPtTrackListItem} trackListItem */
                        function selectTrack(trackListItem) {
                            trackListItem.children.whoseRole.is("AXCell").allItems[1].buttons.first.elementClick();
                        }
                
                        function selectAllVisibleActiveTracks() {
                            sf.ui.proTools.appActivateMainWindow();
                            sf.ui.proTools.trackDeselectAll();
                            getVisibleActiveTracks().trackListItems.forEach(selectTrack)
                        }
                
                        selectAllVisibleActiveTracks();
                
                
                        //select only routing folder
                        const selectedHeaders = sf.ui.proTools.selectedTrackHeaders
                        sf.ui.invalidate().proTools.trackSelectByName({ names: selectedHeaders.filter(t => t.title.value.endsWith("Routing Folder Track ")).map(t => t.normalizedTrackName) })
                
                
                        ///////////////////////////////////////////do for all selected track
                        function doForAllSelectedTracks(action) {
                            var originallySelectedTrackNames = sf.ui.proTools.invalidate().selectedTrackNames;
                
                            try {
                                sf.ui.proTools.selectedTrackHeaders.forEach(track => {
                                    track.trackSelect();
                                    action(track);
                                });
                            }
                            finally {
                                sf.ui.proTools.trackSelectByName({ names: originallySelectedTrackNames });
                            }
                        }
                
                
                        //LOOP CONTENTS
                        /**@param {AxPtTrackHeader} track */
                        function trackFunc(track) {
                            if (sf.ui.proTools.confirmationDialog.exists) {
                                sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is("OK").first.elementClick();
                            }
                
                
                            // if visible, hide floating windows
                            const areFloatingWindowsVisible = sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isEnabled
                            if (areFloatingWindowsVisible) {
                                sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'] })
                            };
                
                
                            const origSelectedTracks = sf.ui.proTools.selectedTrackNames;
                            const firstSelectedTrack = origSelectedTracks[0];
                
                
                            //TO SCROLL
                            /**
                            * @param {string} trackName
                            * @param {string[]} selectedTracks
                            */
                            function scrollToTrackNamed(trackName, selectedTracks) {
                                // Open scroll to track dialog and enter track name
                                sf.ui.proTools.menuClick({ menuPath: ['Track', 'Scroll to Track...'] });
                                var confirmationDialogWin = sf.ui.proTools.confirmationDialog;
                
                                confirmationDialogWin.elementWaitFor();
                
                                confirmationDialogWin.textFields.first.elementSetTextFieldWithAreaValue({ value: trackName });
                
                                confirmationDialogWin.buttons.whoseTitle.is('OK').first.elementClick();
                
                                confirmationDialogWin.elementWaitFor({ waitType: 'Disappear' });
                
                                //Re-select originally selected tracks
                                sf.ui.proTools.trackSelectByName({ names: origSelectedTracks })
                            };
                
                            scrollToTrackNamed(firstSelectedTrack, origSelectedTracks);
                
                
                            sf.ui.proTools.trackSelectByName({ names: origSelectedTracks })
                
                
                            //Make sure current folder is open
                            sf.ui.proTools.selectedTrack.folderTrackSetOpen({
                                targetValue: "Enable",
                            });
                
                
                            //Get the input path of this folder
                            var folderInputPath = getInputPathOfSelectedTrack();
                            var folderInputPathTrue = folderInputPath[1].split(" (").slice(0, -1).join("");
                
                
                            /// store selected track names
                            //const selectedTracks = sf.ui.proTools.selectedTrackNames
                
                
                            // Save track color as preset
                            saveTrackPreset()
                
                
                            //Select all audio tracks in folder
                            selectTracksInCurrentFolderOfType('audio');
                
                
                            const childSelectedTracks = sf.ui.proTools.selectedTrackNames;
                
                
                            //Select all audio tracks in folder
                            //selectTracksInCurrentFolderOfType('audio');
                
                
                            // Recall Color
                            try {
                                recallTrackPreset()
                            } catch (err) { }
                
                
                            sf.ui.proTools.trackSelectByName({ names: childSelectedTracks })
                
                
                            //Route all selected tracks to the folder
                            //sf.ui.proTools.selectedTrack.trackOutputSelect({
                            //    outputPath: ["bus", folderInputPathTrue + " (Stereo)"],
                            //    selectForAllSelectedTracks: true,
                            //});
                
                
                            //if (sf.ui.proTools.selectedTrackNames.slice().length != 0)
                            //    sf.ui.proTools.selectedTrack.trackOutputSelect({
                            //        outputSelector: items => items.filter(p => p.path[1] && p.path[1].split("(").slice(0, 1).join("(") === folderInputPathTrue)[0],
                            //        selectForAllSelectedTracks: true
                            //    }); else { }
                
                            //log(sf.ui.proTools.selectedTrackNames.slice().length)
                
                
                            try {
                                sf.ui.proTools.selectedTrack.trackOutputSelect({
                                    outputSelector: items => items.filter(p => p.path[1] && p.path[1].split("(").slice(0, 1).join("(") === folderInputPathTrue)[0],
                                    selectForAllSelectedTracks: true
                                });
                            } catch (err) { }
                
                            // Recall Color
                            //recallTrackPreset()
                        }
                
                        doForAllSelectedTracks(trackFunc);
                
                        if (sf.ui.proTools.confirmationDialog.exists) {
                            sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is("OK").first.elementClick();
                        }
                
                        sf.wait({
                            intervalMs: 3000,
                        });
                
                
                        /// Need task manager to close sessions
                        if (!sf.ui.proTools.getMenuItem("Window", "Task Manager").isMenuChecked) {
                            sf.ui.proTools.menuClick({ menuPath: ["Window", "Task Manager"], targetValue: "Enable" });
                        }
                
                        saveAndClose()
                
                        closeWindows();
                
                        sf.ui.proTools.mainWindow.elementWaitFor({ waitType: "Disappear", timeout: -1 });
                
                    }
                }
                log("FINISH")
                
                1. Raphael Sepulveda @raphaelsepulveda2022-06-25 17:42:47.069Z2022-06-25 18:28:21.431Z

                  Hey @Yujiro_Yonetsu, the first thing I would do to troubleshoot this is to isolate the part that is giving you the error and make sure it works on its own.

                  Open one of your sessions and run the script below. Does it successfully log data regarding the visible tracks?

                  sf.ui.proTools.appActivateMainWindow();
                  sf.ui.proTools.mainWindow.invalidate();
                  
                  //select only active track
                  const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                  
                  /** @param {{ track: AxPtTrackHeader}} arg */
                  function isTrackActive({ track }) {
                      if (track.muteButton.exists) {
                          return track.muteButton.value.value !== 'inactive';
                      }
                      return track.outputWindowButton.value.value !== 'inactive';
                  }
                  
                  function getVisibleActiveTracks() {
                      let visibleActiveTracks = { trackHeaders: [], trackListItems: [], names: [] };
                  
                      visibleTracks.trackHeaders.forEach((trackHeader, i) => {
                          if (isTrackActive({ track: trackHeader })) {
                              visibleActiveTracks["trackHeaders"].push(trackHeader)
                              visibleActiveTracks["trackListItems"].push(visibleTracks.trackListItems[i])
                              visibleActiveTracks["names"].push(visibleTracks.names[i])
                          }
                      });
                  
                      return visibleActiveTracks;
                  }
                  
                  log(getVisibleActiveTracks())
                  

                  If that doesn't work, then I would try placing the following code on line 574 of the full script: sf.ui.proTools.mainWindow.invalidate();
                  That's right before the code regarding visibleTracks.

                  I'm suggesting that because you're closing folders in the previous part and that's going to change the track structure. Invalidating here will make sure that SoundFlow has refreshed its awareness of the tracks running the next part.

                  Hopefully that helps!

                  1. Yujiro Yonetsu @Yujiro_Yonetsu
                      2022-06-25 18:10:22.950Z

                      Hello
                      Thanks for your help.

                      It acquires the header correctly in a single session.
                      But I still get the same error when I put it in a script for multiple sessions......

                      visibleTracks.trackHeaders.forEach((trackHeader, i) => {
                      

                      As before, this line produces an error.
                      Is there any solution?

                      1. Sorry if it didn't come across before but can you try adding sf.ui.proTools.mainWindow.invalidate(); before this:

                                //select only active track
                                const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                        
                        1. Yujiro Yonetsu @Yujiro_Yonetsu
                            2022-06-25 18:39:32.417Z

                            I'm trying to do exactly what you've described, but it's not working.

                            Here is a partial excerpt.

                            //select all tracks
                                    sf.keyboard.press({
                                        keys: "return",
                                    });
                            
                                    sf.ui.proTools.menuClick({
                                        menuPath: ["Edit", "Select All"],
                                    });
                            
                            
                                    sf.ui.proTools.appActivateMainWindow();
                                    sf.ui.proTools.mainWindow.invalidate();
                                    
                            
                                    //select only active track
                                    const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                            
                                    /** @param {{ track: AxPtTrackHeader}} arg */
                                    function isTrackActive({ track }) {
                                        if (track.muteButton.exists) {
                                            return track.muteButton.value.value !== 'inactive';
                                        }
                                        return track.outputWindowButton.value.value !== 'inactive';
                                    }
                            
                                    function getVisibleActiveTracks() {
                                        let visibleActiveTracks = { trackHeaders: [], trackListItems: [], names: [] };
                            
                                        visibleTracks.trackHeaders.forEach((trackHeader, i) => {
                                            if (isTrackActive({ track: trackHeader })) {
                                                visibleActiveTracks["trackHeaders"].push(trackHeader)
                                                visibleActiveTracks["trackListItems"].push(visibleTracks.trackListItems[i])
                                                visibleActiveTracks["names"].push(visibleTracks.names[i])
                                            }
                                        });
                            
                                        return visibleActiveTracks;
                                    }
                            
                                    log(getVisibleActiveTracks())
                            
                                    /** @param {AxPtTrackListItem} trackListItem */
                                    function selectTrack(trackListItem) {
                                        trackListItem.children.whoseRole.is("AXCell").allItems[1].buttons.first.elementClick();
                                    }
                            
                                    function selectAllVisibleActiveTracks() {
                                        sf.ui.proTools.appActivateMainWindow();
                                        sf.ui.proTools.trackDeselectAll();
                                        getVisibleActiveTracks().trackListItems.forEach(selectTrack)
                                    }
                            
                                    selectAllVisibleActiveTracks();
                            
                            1. Ok, gotcha. I think I know why this is happening. Try this.

                              Take this line:

                              const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                              

                              And put it inside the getVisibleActiveTracks() function, like so:

                              function getVisibleActiveTracks() {
                                  const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                                  let visibleActiveTracks = { trackHeaders: [], trackListItems: [], names: [] };
                              
                                  visibleTracks.trackHeaders.forEach((trackHeader, i) => {
                                      if (isTrackActive({ track: trackHeader })) {
                                          visibleActiveTracks["trackHeaders"].push(trackHeader)
                                          visibleActiveTracks["trackListItems"].push(visibleTracks.trackListItems[i])
                                          visibleActiveTracks["names"].push(visibleTracks.names[i])
                                      }
                                  });
                              
                                  return visibleActiveTracks
                              }
                              
                              1. Yujiro Yonetsu @Yujiro_Yonetsu
                                  2022-06-26 15:11:37.177Z

                                  Thank you!
                                  I don't understand how it happened, but it's solved :)

                                  1. Jjulien creus @julien_creus
                                      2023-07-03 18:42:00.439Z

                                      Hello @raphaelsepulveda ! Thanks for your help on all those topics, and sorry for chiming in that late on this one! I'm trying to use it as part of a bigger script but seems like I'm facing an issue: The main idea is, as part of a session prep script, to select all visible and active tracks (which would be my template tracks), and setup their track height to medium. (Later on, open all folder tracks, and move tracks inside them). In my template, I do have 3 levels of routing folder tracks.
                                      Let's say,
                                      ALL VOCALS
                                      - LEAD
                                      - ADD VOCALS
                                      -- BVS
                                      -- HARMOS
                                      -- ADLIBS

                                      Using your script for the selection part, looks like level three folders (BVS, HARMOS and ADLIBS in my example) aren't selected....
                                      Here is the overall script: would you have any idea on what's going on?
                                      Thanks in advance!!

                                      //SELECT AND SETUP VISIBLE AND ACTIVE TRACKS HEIGHT
                                      
                                      function isTrackActive({ track }) {
                                      	if (track.muteButton.exists) {
                                      		return track.muteButton.value.value !== 'inactive';
                                      	}
                                      	return track.outputWindowButton.value.value !== 'inactive';
                                      }
                                      
                                      function getVisibleActiveTracks() {
                                      	const visibleTracks = sf.ui.proTools.invalidate().visibleTracks;
                                      	let visibleActiveTracks = { trackHeaders: [], trackListItems: [], names: [] };
                                      	visibleTracks.trackHeaders.forEach((trackHeader, i) => {
                                      		if (isTrackActive({ track: trackHeader })) {
                                      			visibleActiveTracks["trackHeaders"].push(trackHeader)
                                      			visibleActiveTracks["trackListItems"].push(visibleTracks.trackListItems[i])
                                      			visibleActiveTracks["names"].push(visibleTracks.names[i])
                                      		}
                                      	});
                                      
                                      	return visibleActiveTracks
                                      }
                                      
                                      function selectTrack(trackListItem) {
                                      	trackListItem.children.whoseRole.is("AXCell").allItems[1].buttons.first.elementClick();
                                      }
                                      
                                      function setVisibleTracksHeight(size) {
                                      
                                      	// Make sure track lis is visible
                                      	sf.ui.proTools.menuClick({ menuPath: ["View", "Other Displays", "Track List"], targetValue: "Enable" })
                                      	// Get all items from track list
                                      	const trackList = sf.ui.proTools.trackListItems
                                      
                                      	sf.ui.proTools.trackDeselectAll();
                                      	getVisibleActiveTracks().trackListItems.forEach(selectTrack);
                                      
                                      	// Get all selected tracks
                                      	const selectedTracks = sf.ui.proTools.selectedTrackNames
                                      
                                      	// Scroll first track to view
                                      	const indexOfFirstSelected = trackList.findIndex(x => x.normalizedTrackName == selectedTracks[0])
                                      	trackList[indexOfFirstSelected].children.whoseRole.is("AXCell").allItems[1].buttons.first.mouseClickElement({ isControl: true, isShift: true })
                                      
                                      	// Select original selection
                                      	sf.ui.proTools.trackSelectByName({ names: selectedTracks });
                                      
                                      	//Setup track height 
                                      	var f = sf.ui.proTools.selectedTrack.frame;
                                      	var popupMenu = sf.ui.proTools.selectedTrack.popupMenuOpenFromElement({
                                      		relativePosition: { x: f.w - 10, y: 5 },
                                      		isOption: true,
                                      		isShift: true,
                                      	}).popupMenu;
                                      	popupMenu.menuClickPopupMenu({
                                      		menuPath: [size]
                                      	});
                                      
                                      setVisibleTracksHeight("medium");
                                      
                                      1. Hey @julien_creus, besides a } being missing on line 58—which I'm sure was just a mistake while posting it on the forum—I don't see anything else that would prevent the script from selecting folders of all levels as long as they're visible. Are the folders containing the level three folders open? If you could post a short video of the script running, that'll help a lot!

                                        1. Jjulien creus @julien_creus
                                            2023-07-03 22:45:24.134Z

                                            Hey Raphael! Thanks for your answer! Sure the "{" was a copy/paste mistake =) Here's a quick video of the issue (sorry as it goes quite fast). I made the track height move to medium, and then back to small. Parent folders are also opened yes.
                                            As you can see, the script seems to toggle the open/close state of those 3rd level folder (you can see the "open folder" arrows changing while the script runs during my video on F111 & F112).
                                            https://we.tl/t-rUf5C5ZN8o

                                            1. @julien_creus, thanks for the video, I was able to replicate it!

                                              The issue is that your track list width on the left side is too narrow. This script interacts with that area so what you have to do is make it a bit wider until you can see more of the name of the folders that aren't getting selected. That should fix your problem!

                                              1. Jjulien creus @julien_creus
                                                  2023-07-04 09:06:36.629Z

                                                  Yesss! It did, thanks a lot for your help! I'll be looking for a way to adapt the track list width to its content then =) that's perfect! I guess it would be another topic, but If by chance you have any leads about that?

                                                  1. That you would have to do manually. I'd suggest just having a set width that covers all situations. It doesn't have to display the whole name of the tracks, this particular script needs just enough to perform an action on it. You can identify how much that is by experimenting with this script and adjusting the width a bit at a time until it starts working correctly.

                                                    Now that I think about it, once you find that width then you can save a Window Configuration and import it into your other sessions to recall that width exactly.