No internet connection
  1. Home
  2. How to

Automating clips using an "AUTOMATOR" track with "get & set - selected tracks"

By TK_Delay @TK_Delay
    2024-10-03 22:32:03.887Z

    Hello to the collective knowledge.
    I'm trying to write a toggle script where I cut a clip from a track, insert it into an "AUTOMATOR" track and set automation modalities (Toggle Action 1).
    Then I want to write the automation in Toggle 2 and insert the clip into the original track.
    Toggle 1 works perfectly. But in Toggle 2 it doesn't work to put the clip back onto its original track.

    Any idea for a solution?

    // Define the plugin and track names from the event properties.
    const { pluginName, trackName } = event.props;
    
    /// Store the originally selected track names into a variable before any actions change the selection
    const originalSelectedTracks = sf.ui.proTools.selectedTrackNames
    
    // Check if the global state is undefined, which means this is the first toggle. Set it to 1 (initial state).
    if (globalState.INSAutoA === undefined) {
        globalState.INSAutoA = 1;
    }
    
    /////////////////////////////////////////// TOGGLE ACTION 1 ////////////////////////////////////////////////////////////
    else if (globalState.INSAutoA === 1) 
    
    {
        // Activate the main window of Pro Tools to ensure focus.
        sf.ui.proTools.appActivateMainWindow();
        sf.ui.proTools.mainWindow.invalidate();
    
        // Enable automation preview mode (this allows automation changes to be previewed without being written).
        sf.ui.proTools.automationPreview();
    
        // Cut the selected clip from the current track. 
        // It's important that this happens before switching tracks so the clip can be pasted later.
        sf.keyboard.press({
            keys: "cmd+x",
        });
    
        // Make the PFX Cutter Tracks visible by opening the track search function.
        sf.keyboard.press({
            keys: "cmd+alt+f",
        });
    
        // Type in the search text to find the "AUTOMATOR" track.
        sf.keyboard.type({
            text: "AUTOMATOR",
        });
    
        // Press Enter to select the track.
        sf.keyboard.press({
            keys: "numpad enter",
        });
    
        // Select the "AUTOMATOR" track to make it the active track.
        sf.ui.proTools.trackGetByName({ name: "AUTOMATOR", makeVisible: true }).track.trackSelect();
    
        // Paste the previously cut clip into the "AUTOMATOR" track and confirm the action with the "e" key.
        sf.keyboard.press({
            keys: "cmd+v, e",
        });
    
        /** 
         * Function to open a plugin on the given track.
         * @param {{ trackName?: string, pluginName: string }} args 
         */
        function openPlugin({ trackName, pluginName: targetPluginName }) {
            let insertIndex;  // Will hold the index of the plugin on the track.
    
            // Ensure the Pro Tools window is updated to reflect changes.
            sf.ui.proTools.mainWindow.invalidate();
    
            // Get the track by name or fall back to the currently selected track if no name is provided.
            const track = trackName
                ? sf.ui.proTools.trackGetByName({ name: trackName }).track
                : sf.ui.proTools.selectedTrack;
    
            // Manually fetch the insert buttons (avoiding issues with hidden tabs) for inserts A-E and F-J.
            const insertButtons = function () {
                const insertButtonsAE = track.groups.whoseTitle.is("Inserts A-E").first.children.whoseTitle.startsWith("Insert Assignment").map(ib => ib);
                const insertButtonsFJ = track.groups.whoseTitle.is("Inserts F-J").first.children.whoseTitle.startsWith("Insert Assignment").map(ib => ib);
                return [...insertButtonsAE, ...insertButtonsFJ];
            }();
    
            // Find the plugin by its name in the inserts of the track.
            const pluginNames = insertButtons.map(ib => ib.value.value);
            pluginNames.find((pluginName, i) => {
                if (pluginName.includes(targetPluginName)) {
                    insertIndex = i;  // Save the index of the plugin.
                    return true;
                }
            });
    
            // If the plugin is not found in any inserts, throw an error.
            if (insertIndex === undefined) {
                throw `No insert with the name "${targetPluginName}" found on track "${track.normalizedTrackName}".`;
            }
    
            // Check if the plugin window is already open.
            const pluginWindow = sf.ui.proTools.windows.whoseTitle.startsWith(`Plug-in: ${targetPluginName}`).first;
    
            if (pluginWindow.exists) {
                // If the window is already open, toggle the bypass and bring the window to the front.
                if (pluginWindow.buttons.whoseTitle.is("Effect Bypass").first.exists) {
                    pluginWindow.buttons.whoseTitle.is("Effect Bypass").first.elementClick();
                }
    
                // Bring the plugin window to the front.
                pluginWindow.elementRaise();
    
            } else {
                // If the plugin window is not already open, click the insert button to open it.
                track.insertButtons[insertIndex].elementClick();
    
                // Wait for the plugin window to appear.
                const pluginWin = sf.ui.proTools.windows.whoseTitle.startsWith(`Plug-in: ${targetPluginName}`).waitFor().element;
    
                // Toggle the bypass of the plugin (enable/disable).
                pluginWin.buttons.whoseTitle.is("Effect Bypass").first.elementClick();
    
                // Click the target button to bring the plugin into focus (optional step depending on workflow).
                pluginWin.buttons.whoseTitle.is("Target button").first.elementClick();
            }
        }
    
        openPlugin({
            trackName: trackName, // Optional: provide track name.
            pluginName: pluginName // Use the defined plugin name.
        });
    
        // Show a notification to the user that automation is now in preview mode.
        sf.interaction.notify({
            title: "--== AUTOMATION PREVIEW ==--",
        });
    
        globalState.INSAutoA = 2; // Update global state to indicate the next action will be Toggle Action 2.
    }
    
    ///////////////////////////////////////////// END OF TOGGLE ACTION 1 //////////////////////////////////////
    
    ///////////////////////////////////////////// TOGGLE ACTION 2 ////////////////////////////////////////////////////////////
    else if (globalState.INSAutoA === 2) 
    
    {
        // Activate the main window to ensure focus is on Pro Tools.
        sf.ui.proTools.appActivateMainWindow();
        sf.ui.proTools.mainWindow.invalidate();
    
        // Check if a clip is selected by reading the selection length.
        var startTime = sf.ui.proTools.mainWindow.counterDisplay.textFields.whoseTitle.is("Edit Selection Length").first;
    
        // If no selection is made, log an error message and stop the script.
        if (startTime.invalidate().value.value == "00:00:00:00") {
            log("No clip selected", startTime.invalidate().value.value);
            throw (0);
        } else {
            // Write all changed automation data to the selected area.
            sf.ui.proTools.automationWriteAutoToSelectionAndClear({
                autoConfirmation: true,
            });
    
            // Close the plugin window if it is open.
            sf.ui.proTools.floatingWindows.whoseTitle.startsWith("Plug-in: " + pluginName).allItems.forEach(function (win) {
                try { win.windowClose(); } catch (err) { }
            });
    
            // Cut the clip from the "AUTOMATOR" track.
            sf.keyboard.press({
                keys: "e, cmd+a, cmd+x",
            });
    
            // Select the originally selected track(s) using the previously stored track names.
            sf.ui.proTools.trackSelectByName({ names: originalSelectedTracks });
            
            // Make the original track visible and select it.
            sf.ui.proTools.trackGetByName({ name: originalSelectedTracks, makeVisible: true }).track.trackSelect();
    
            // Paste the clip back into the original track.
            sf.keyboard.press({
                keys: "cmd+v",
            });
    
            // Show a notification that automation is back to normal (no preview mode).
            sf.interaction.notify({
                title: "--== AUTOMATION NORMAL ==--",
            });
            
            log(originalSelectedTracks);
    
            globalState.INSAutoA = 1; // Reset global state to 1, ready for the next cycle.
        }
    
    }
    
    ////////////////////////////////////////////////// END OF TOGGLE ACTION 2 ////////////////////////////////////////////////////
    
    
    Solved in post #3, click to view
    • 2 replies
    1. T
      TK_Delay @TK_Delay
        2024-10-03 23:11:18.733Z

        This slightly shorter script works so far.
        But only if I insert the clip twice in line 38.
        Strange...

        sf.ui.proTools.appActivate();
        
        /// Get Selected track names to variable
        const originalSelectedTracks = sf.ui.proTools.selectedTrackNames
        
        sf.keyboard.press({
            keys: "cmd+x",
        });
        
        // Make the PFX Cutter Tracks visible by opening the track search function.
        sf.keyboard.press({
            keys: "cmd+alt+f",
        });
        
        // Type in the search text to find the "AUTOMATOR" track.
        sf.keyboard.type({
            text: "AUTOMATOR",
        });
        
        // Press Enter to select the track.
        sf.keyboard.press({
            keys: "numpad enter",
        });
        
        
        sf.ui.proTools.trackGetByName({ name: "AUTOMATOR", makeVisible: true }).track.trackSelect();
        
        sf.keyboard.press({
            keys: "cmd+v, cmd+c",
        });
        
        // Select track by name using variable selectedTracks
        sf.ui.proTools.trackSelectByName({ names: originalSelectedTracks })
        
        sf.ui.proTools.selectedTrack.trackScrollToView();
        
        sf.keyboard.press({
            keys: "cmd+v, cmd+v",
        });
        
        
        
        1. T
          In reply toTK_Delay:
          TK_Delay @TK_Delay
            2024-10-04 13:29:59.703Z

            Solution:

            /////////////////////////////////////// INSERT Automation via AUTOMATOR-Track TOGGLE /////////////////////////////////////////////////////////////////
            
            /** 
             * Toggle Action 1:     Save the currently selected track
             *                      Activate PREVIEW
             *                      Check if a clip is selected
             *                      Cut the selected clip(s) and paste them onto the "AUTOMATOR" track
             *                      Open Insert on the track and wait for the plugin window to appear
             *                      Toggle the Insert bypass (On/Off)
             *                      Display notification "--== AUTOMATION PREVIEW ==--"
             *
             * Toggle Action 2:     If no selection is made, abort the script.
             *                      Write all changed automation data into the selection area and deactivate PREVIEW
             *                      Close the plugin window
             *                      Cut the selected clip(s) and paste them back onto the original track
             *                      Display notification "--== AUTOMATION NORMAL ==--"
             */
            
            // Define the plugin and track names from the event properties.
            const { pluginName, trackName } = event.props;
            
            // Check if the global state is undefined, which means this is the first toggle. Set it to 1 (initial state).
            if (globalState.INSAutoA === undefined) {
                globalState.INSAutoA = 1;
            }
            
            /////////////////////////////////////////// TOGGLE ACTION 1 ////////////////////////////////////////////////////////////
            else if (globalState.INSAutoA === 1) {
            
                // Check if a clip is selected by reading the selection length.
                var startTime = sf.ui.proTools.mainWindow.counterDisplay.textFields.whoseTitle.is("Edit Selection Length").first;
            
                // If no selection is made, log an error message and stop the script.
                if (startTime.invalidate().value.value == "00:00:00:00") {
                    log("No clip selected", startTime.invalidate().value.value);
                    throw (0);
                } else {
            
                    // Save the originally selected tracks.
                    const selectedTrackName = sf.ui.proTools.selectedTrackNames[0];
                    globalState.selectedTracks = selectedTrackName;
            
                    // Activate the main Pro Tools window to ensure correct focus.
                    sf.ui.proTools.appActivateMainWindow();
                    sf.ui.proTools.mainWindow.invalidate();
            
                    // Activate automation preview mode.
                    sf.ui.proTools.automationPreview();
            
                    // Cut the selected clip.
                    sf.keyboard.press({
                        keys: "cmd+x",
                    });
            
                    // Open the track search function.
                    sf.keyboard.press({
                        keys: "cmd+alt+f",
                    });
            
                    // Type "AUTOMATOR" to find the track.
                    sf.keyboard.type({
                        text: "AUTOMATOR",
                    });
            
                    // Select the track by pressing Enter.
                    sf.keyboard.press({
                        keys: "numpad enter",
                    });
            
                    // Select the "AUTOMATOR" track to make it active.
                    sf.ui.proTools.trackGetByName({ name: "AUTOMATOR", makeVisible: true }).track.trackSelect();
            
                    // Paste the previously cut clip onto the "AUTOMATOR" track and confirm with "e".
                    sf.keyboard.press({
                        keys: "cmd+v, e",
                    });
            
                    /** 
                     * Function to open a plugin on the specified track.
                     * @param {{ trackName?: string, pluginName: string }} args 
                     */
                    function openPlugin({ trackName, pluginName: targetPluginName }) {
                        let insertIndex;  // Store the index of the plugin on the track.
            
                        // Refresh the Pro Tools window to reflect changes.
                        sf.ui.proTools.mainWindow.invalidate();
            
                        // Get the track either by name or use the currently selected track.
                        const track = trackName
                            ? sf.ui.proTools.trackGetByName({ name: trackName }).track
                            : sf.ui.proTools.selectedTrack;
            
                        // Manually retrieve Insert buttons for A-E and F-J to avoid tabs.
                        const insertButtons = function () {
                            const insertButtonsAE = track.groups.whoseTitle.is("Inserts A-E").first.children.whoseTitle.startsWith("Insert Assignment").map(ib => ib);
                            const insertButtonsFJ = track.groups.whoseTitle.is("Inserts F-J").first.children.whoseTitle.startsWith("Insert Assignment").map(ib => ib);
                            return [...insertButtonsAE, ...insertButtonsFJ];
                        }();
            
                        // Search for the plugin in the track's Insert.
                        const pluginNames = insertButtons.map(ib => ib.value.value);
                        pluginNames.find((pluginName, i) => {
                            if (pluginName.includes(targetPluginName)) {
                                insertIndex = i;  // Store the plugin's index.
                                return true;
                            }
                        });
            
                        // If the plugin is not found, throw an error.
                        if (insertIndex === undefined) {
                            throw `No Insert found with the name "${targetPluginName}" on track "${track.normalizedTrackName}".`;
                        }
            
                        // Check if the plugin window is already open.
                        const pluginWindow = sf.ui.proTools.windows.whoseTitle.startsWith(`Plug-in: ${targetPluginName}`).first;
            
                        if (pluginWindow.exists) {
                            // If the window is already open, toggle the bypass and bring the window to the foreground.
                            if (pluginWindow.buttons.whoseTitle.is("Effect Bypass").first.exists) {
                                pluginWindow.buttons.whoseTitle.is("Effect Bypass").first.elementClick();
                            }
            
                            // Bring the plugin window to the foreground.
                            pluginWindow.elementRaise();
            
                        } else {
                            // If the plugin window is not open, click the Insert button to open it.
                            track.insertButtons[insertIndex].elementClick();
            
                            // Wait for the plugin window to appear.
                            const pluginWin = sf.ui.proTools.windows.whoseTitle.startsWith(`Plug-in: ${targetPluginName}`).waitFor().element;
            
                            // Toggle the plugin's bypass (enable/disable).
                            pluginWin.buttons.whoseTitle.is("Effect Bypass").first.elementClick();
            
                            // Click the Target button to focus the plugin (optional).
                            pluginWin.buttons.whoseTitle.is("Target button").first.elementClick();
                        }
                    }
            
                    // Open the FabFilter Pro-Q 3 plugin on the "AUTOMATOR" track.
                    openPlugin({
                        pluginName: pluginName
                    });
            
                    // Show a notification that automation is now in preview mode.
                    sf.interaction.notify({
                        title: "--== AUTOMATION PREVIEW ==--",
                    });
            
                    globalState.INSAutoA = 2;
                }
            
            }
            
            ///////////////////////////////////////////// END OF TOGGLE ACTION 1 //////////////////////////////////////
            
            
            ///////////////////////////////////////////// TOGGLE ACTION 2 ////////////////////////////////////////////////////////////
            else if (globalState.INSAutoA === 2) {
            
                // Activate the main window to ensure focus is on Pro Tools.
                sf.ui.proTools.appActivateMainWindow();
                sf.ui.proTools.mainWindow.invalidate();
            
                // Check if a clip is selected by reading the selection length.
                var startTime = sf.ui.proTools.mainWindow.counterDisplay.textFields.whoseTitle.is("Edit Selection Length").first;
            
                // If no selection is made, log an error message and stop the script.
                if (startTime.invalidate().value.value == "00:00:00:00") {
                    log("No clip selected", startTime.invalidate().value.value);
                    throw (0);
            
                } else {
            
                    // Write all changed automation data to the selected area.
                    sf.ui.proTools.automationWriteAutoToSelectionAndClear({
                        autoConfirmation: true,
                    });
            
                    // Close the plugin window if it is open.
                    sf.ui.proTools.floatingWindows.whoseTitle.startsWith("Plug-in: " + pluginName).allItems.forEach(function (win) {
                        try { win.windowClose(); } catch (err) { }
                    });
            
                    // Cut the clip from the "AUTOMATOR" track.
                    sf.keyboard.press({
                        keys: "e, cmd+a, cmd+x",
                    });
            
                    /// SET Selected Tracks
            
                    /** @param {{trackName:string}} obj */
                    function scrollToTrack({ trackName }) {
                        sf.ui.proTools.appActivateMainWindow();
            
                        var originalClipboardText = sf.clipboard.getText().text || '';
            
                        sf.ui.proTools.menuClick({
                            menuPath: ["Track", "Scroll to Track..."],
                        });
            
                        sf.ui.proTools.confirmationDialog.elementWaitFor();
            
                        sf.clipboard.setText({
                            text: trackName,
                        });
            
                        sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Paste'] });
            
                        sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is("OK").first.elementClick();
            
                        sf.clipboard.setText({
                            text: originalClipboardText,
                        });
                    }
            
                    scrollToTrack({
                        trackName: globalState.selectedTracks
                    });
            
                    // Paste the clip back into the original track.
                    sf.keyboard.press({
                        keys: "cmd+v",
                    });
            
                    // Show a notification that automation is back to normal (no preview mode).
                    sf.interaction.notify({
                        title: "--== AUTOMATION NORMAL ==--",
                    });
            
                    globalState.INSAutoA = 1; // Reset global state to 1, ready for the next cycle.
                }
            }
            
            ////////////////////////////////////////////////// END OF TOGGLE ACTION 2 ////////////////////////////////////////////////////
            
            
            ReplySolution