No internet connection
  1. Home
  2. Macro and Script Help

Create New FX Aux Script Throws Errors if No Send on Slot 1

By Daniel Knobler @Daniel_Knobler
    2023-11-06 04:16:24.495Z

    Title

    Create New FX Aux Script Throws Errors if No Send on Slot 1

    What do you expect to happen when you run the script/macro?

    This wonderful script for creating FX auxes that I borrowd from Phil Weinrobe creates a send to a new aux, routes the new aux to the same destination as the original track, and prompts to add an insert on slot 2.

    Are you seeing an error?

    If there is no send in slot one, I get this error. If there's already a send in slot 1 the scripts works totally fine, creating a new send in slot 2.

    05.11.2023 22:13:06.71 [Backend]: JavaScript error with InnerException: null
    Logging error in action (01) RunCommandAction: TypeError: Cannot read property 'toLowerCase' of undefined
    (Phil New Send Thing line 228)
    Error in action (00) SearchCommandsAction: RunCommandAction
    !! Command Error: Search Commands [soundflow.searchCommands]:
    TypeError: Cannot read property 'toLowerCase' of undefined
    (Phil New Send Thing line 228)
    << Command: Search Commands [soundflow.searchCommands]

    What happens when you run this script?

    If the source track has no send on slot 1, the script throws an error. If there is a send on slot 1 in the source track, the script works totally fine creating a new send in slot 2. However, I'm using the script most often when there are no sends on the source track.

    How were you running this script?

    I used a keyboard shortcut within the target app

    How important is this issue to you?

    5

    Details

    {
        "inputExpected": "This wonderful script for creating FX auxes that I borrowd from Phil Weinrobe creates a send to a new aux, routes the new aux to the same destination as the original track, and prompts to add an insert on slot 2.",
        "inputIsError": true,
        "inputError": "If there is no send in slot one, I get this error. If there's already a send in slot 1 the scripts works totally fine, creating a new send in slot 2.\n\n05.11.2023 22:13:06.71  [Backend]: JavaScript error with InnerException: null\nLogging error in action (01) RunCommandAction: TypeError: Cannot read property 'toLowerCase' of undefined\n(Phil New Send Thing line 228) \nError in action (00) SearchCommandsAction: RunCommandAction\n!! Command Error: Search Commands [soundflow.searchCommands]:\n    TypeError: Cannot read property 'toLowerCase' of undefined\n(Phil New Send Thing line 228)\n<< Command: Search Commands [soundflow.searchCommands]",
        "inputWhatHappens": "If the source track has no send on slot 1, the script throws an error. If there is a send on slot 1 in the source track, the script works totally fine creating a new send in slot 2. However, I'm using the script most often when there are no sends on the source track.",
        "inputHowRun": {
            "key": "-Mpfwh4RkPLb2LPwjePT",
            "title": "I used a keyboard shortcut within the target app"
        },
        "inputImportance": 5,
        "inputTitle": "Create New FX Aux Script Throws Errors if No Send on Slot 1"
    }

    Source

    
    /**
    * @param {string} sendAssignment
    */
    function assignToNewTrack(sendAssignment) {
        const selectedTracks = sf.ui.proTools.selectedTrackNames
        sf.ui.proTools.trackGetByName({ name: selectedTracks[selectedTracks.length - 1] }).track.groups.whoseTitle.is(getGroup("Sends", sendAssignment)).first.buttons.whoseTitle.is(`Send Assignment ${sendAssignment}`).first.popupMenuSelect({
            isShift: true,
            isOption: true,
            menuPath: ["new track..."],
        });
    }
    
    function moveSendWinOutOfSlots() {
        sf.ui.proTools.invalidate()
    
        const sendWin = sf.ui.proTools.mainTrackOutputWindow.elementWaitFor().element
        const sendWinPos = sendWin.position.x
        const sendSlots = sf.ui.proTools.selectedTrack.groups.whoseTitle.is("Inserts A-E").first
        const sendSlotsPos = sendSlots.position.x
    
        if (sendWinPos - sendSlotsPos < 450 && sendSlotsPos - sendWinPos < 170) {
            sendWin.windowMove({
                position: {
                    y: sendWin.position.y,
                    x: sendSlotsPos + 450
                }
            })
        }
    }
    
    function getFirstFreeSend() {
        const selectedTracks = sf.ui.proTools.selectedTrackHeaders
        const sendLetters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
        let sendAssignmentList = []
        for (let i = 0; i < selectedTracks.length; i++) {
            let trackInfo = sf.ui.proTools.trackGetByName({ name: selectedTracks[i].normalizedTrackName })
                .track.sendButtons.filter(x => x.value.invalidate().value != "unassigned").map(x => x.title.invalidate().value.split(" ")[2])
            sendAssignmentList.push(...trackInfo)
        }
    
        const firstFreeSend = sendLetters.filter(letter => sendAssignmentList.indexOf(letter) === -1)[0]
    
        if (firstFreeSend) {
            return firstFreeSend
        } else {
            alert("Must have at least one free send, that is the same for all tracks.")
            throw 0
        };
    };
    
    
    /**
    * @param {'Insert'|'Send'} slotType
    * @param {array} [defaultUsedSlots] = [] - If parameter is not used, default is []
    */
    function getFirstFreeInsertOrSend(slotType, defaultUsedSlots) {
    
        let buttons
        slotType == "Insert" ? buttons = "insertButtons" : buttons = "sendButtons"
    
        const selectedTracks = sf.ui.proTools.selectedTrackHeaders
        const sendLetters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
        let sendAssignmentList = defaultUsedSlots || []
        try {
            for (let i = 0; i < selectedTracks.length; i++) {
                let trackInfo = sf.ui.proTools.trackGetByName({ name: selectedTracks[i].normalizedTrackName })
                    // .insertButtons or .sendButtons
                    .track[buttons].filter(x => x.value.invalidate().value != "unassigned").map(x => x.title.invalidate().value.split(" ")[2])
                sendAssignmentList.push(...trackInfo)
            }
        } catch (err) { }
        const firstFreeSend = sendLetters.filter(letter => sendAssignmentList.indexOf(letter) === -1)[0]
    
        if (firstFreeSend) {
            return firstFreeSend
        } else {
            if (slotType == "Insert") { alert(`Must have at least one free ${slotType} slot.`) }
            else if (slotType == "Send") { alert(`Must have at least one free ${slotType} slot, that is the same for selected tracks.`) }
            throw 0
        };
    };
    
    
    /**
    * @param {string} sendLetter
    * @param {'Inserts'|'Sends'} slotType
    */
    function getGroup(slotType, sendLetter) {
        let group
        sendLetter.toLowerCase().charCodeAt(0) - 97 <= 4 ? group = `${slotType} A-E` : group = `${slotType} F-J`
        return group
    }
    
    
    
    function newTrackSettings() {
        const newTrackWin = sf.ui.proTools.windows.whoseTitle.is("New Track").first.elementWaitFor().element
    
        const format = newTrackWin.popupButtons.whoseTitle.is("Stereo").first
        const type = newTrackWin.popupButtons.whoseTitle.is("Aux Input").first
        const timeBase = newTrackWin.popupButtons.whoseTitle.is("Samples").first
    
        if (format.value.invalidate().value != "Stereo") { format.popupMenuSelect({ menuPath: ["Stereo"] }); }
        if (type.value.invalidate().value != "Aux Input") { type.popupMenuSelect({ menuPath: ["Aux Input"] }); }
        if (timeBase.value.invalidate().value != "Samples") { timeBase.popupMenuSelect({ menuPath: ["Samples"] }); }
    
        newTrackWin.checkBoxes.whoseTitle.is("Create next to current track").first.checkboxSet({ targetValue: "Enable" });
    
        //  Wait to name track and press ok
        newTrackWin.elementWaitFor({ waitType: "Disappear", timeout: -1 })
        sf.ui.proTools.invalidate()
    }
    
    /**
     * @param {'Enable'|'Disable'} targetValue
     * @param {array} [viewsNames] = [] - If parameter is not used, default is set inside
     */
    function setWindowViews(targetValue, viewsNames) {
        let views = viewsNames || ["Inserts A-E", "Inserts F-J", "Sends A-E", "Sends F-J"]
    
        views.forEach(view => {
            sf.ui.proTools.menuClick({ menuPath: ["View", "Edit Window Views", view], targetValue: targetValue })
            // sf.ui.proTools.menuClick({ menuPath: ["View", "Mix Window Views", view], targetValue: targetValue })
        })
    }
    
    
    const getSelectedTrackOut = (trackName) => sf.ui.proTools.trackGetByName({ name: trackName }).track.outputPathButton.title.invalidate().value.split('\n')[1].trim();
    
    
    
    let insertSlot
    let firstFreeSend
    function actions() {
    
        const originalSelectedTracks = sf.ui.proTools.selectedTrackNames
    
        // Save first selected track output on variable
        const firstSelectedOut = getSelectedTrackOut(originalSelectedTracks[0])
    
        //  Get free sends
        firstFreeSend = getFirstFreeInsertOrSend("Send")
    
        // Assign new send to new track
        assignToNewTrack(firstFreeSend)
    
        // New track setting and wait for track name
        newTrackSettings()
    
        // If new send win is blocking the inserts or sends, move win away
        moveSendWinOutOfSlots()
    
        // Expand created send
        sf.ui.proTools.menuClick({ menuPath: ["View", "Expanded Sends", `Send ${firstFreeSend}`], targetValue: "Enable" })
    
        // Solo safe new Aux
        const selectedTracks = sf.ui.proTools.selectedTrackNames
        const auxTrack = sf.ui.proTools.trackGetByName({ name: selectedTracks[selectedTracks.length - 1] }).track
        auxTrack.trackSelect()
        auxTrack.trackScrollToView()
        auxTrack.buttons.whoseTitle.is("Solo").first.mouseClickElement({ isCommand: true })
    
        // set new aux output
        if (getSelectedTrackOut(auxTrack.normalizedTrackName) != firstSelectedOut) {
            auxTrack.trackOutputSelect({ outputSelector: items => items.filter(item => item.element.title.value.includes(firstSelectedOut))[0] })
        }
    
        // Get free insert slot after A
        insertSlot = getFirstFreeInsertOrSend("Insert", ["A"])
    
    
        // Open search...
        auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first
            .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`)
            .first.popupMenuSelect({
                menuPath: ["search..."],
            });
    
    
        // Wait to open new plug
        while (true) {
            const plugIsOpen = auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first
                .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`).first
                .value.invalidate().value != "unassigned"
    
            if (!plugIsOpen) {
                sf.wait({ intervalMs: 1000 })
            } else {
                break;
            }
        }
        sf.ui.proTools.trackSelectByName({ names: originalSelectedTracks })
    }
    
    
    
    
    function main() {
    
        sf.ui.proTools.appActivateMainWindow();
        sf.ui.proTools.invalidate();
    
        // const isActiveInsGroupFMix = sf.ui.proTools.getMenuItem("View", "Mix Window Views", "Inserts F-J").isMenuChecked
        const isActiveInsGroupFEdit = sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Inserts F-J").isMenuChecked
    
        // const isActiveSendGroupFMix = sf.ui.proTools.getMenuItem("View", "Mix Window Views", "Sends F-J").isMenuChecked
        const isActiveSendGroupFEdit = sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Sends F-J").isMenuChecked
    
    
        const isEditWin = sf.ui.proTools.focusedWindow.title.value.startsWith("Edit")
        if (!isEditWin) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"] }) }
    
        // Close expand created sends
        sf.ui.proTools.menuClick({ menuPath: ["View", "Expanded Sends", "None"], targetValue: "Enable" })
    
        setWindowViews("Enable")
    
        try {
            actions()
        } catch (err) { throw err }
        finally {
    
            //  Go to mix if needed
            if (!isEditWin) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Mix"] }) }
    
            // Close Inserts Views if not needed
            if (insertSlot.toLowerCase().charCodeAt(0) - 97 <= 4 && (/* !isActiveInsGroupFMix || */ !isActiveInsGroupFEdit)) {
                // if (!isActiveInsGroupFMix) { setWindowViews("Disable", ["Inserts F-J"]) }
                if (!isActiveInsGroupFEdit) { setWindowViews("Disable", ["Inserts F-J"]) }
            }
    
    
            // Close Sends F-J if not needed
            if (firstFreeSend.toLowerCase().charCodeAt(0) - 97 <= 4 && (/* !isActiveSendGroupFMix || */ !isActiveSendGroupFEdit)) {
                //  if (!isActiveSendGroupFMix) { setWindowViews("Disable", ["Sends F-J"]) }
                if (!isActiveSendGroupFEdit) { setWindowViews("Disable", ["Sends F-J"]) }
            }
    
        }
    }
    
    main()
    
    

    Links

    User UID: 04vQUq1KmYSCMZHeEkMslw0IpRu2

    Feedback Key: sffeedback:04vQUq1KmYSCMZHeEkMslw0IpRu2:-NiXq8AvFjK9miDqreFf

    Feedback ZIP: oQjqNyxNyjiJPBc3Azu5nuJYqPMByIHms3rW+q+wYDSi9USj1HLMtFwTpst3nId5Meh7HkPi/aAnMqOo0kQbBOJ+BJpn6hJbTG1ElgScK4pPlG4bv5GPk5Z811bV99vm0plGC7JAfhjyFTPy3u9aNi0qS1JeZNk8LuYXjIGX4Br0OdwbJZS8aIBpic6zBGdpLX423Xd2L2grWjHeRDAEH6xCft0zB3aLtzqkoHX1fGBZVW613M0LVTQq1eDZsUdAxSBmJKBJLSzJsmgNHs7yxDQzWD85PIwzTuZ5lihEeV85+sy6FagxjVgCFFSIGzHkxhbqeGdi7R5Ki9DHnDZ1orfehc8AgEY2DWkH08p4yyQ=

    • 0 replies