No internet connection
  1. Home
  2. How to

How do I copy and paste PT menu paths so that I don't have to type and miscapitalize

By John Morris @John_Morris
    2021-04-21 18:46:32.507Z

    I hate to type and I'm lazy. How do I copy and paste PT menu paths so that I don't have to type and miscapitalize the paths?

    • 13 replies

    There are 13 replies. Estimated reading time: 17 minutes

    1. samuel henriques @samuel_henriques
        2021-04-21 21:07:02.106Z2021-04-21 21:49:49.332Z

        Hello @John_Morris,

        This should help you with your problem :).

        To get all menu and submenu from popups:

        Open the log:

        and clear it, so it's easier to read the information:

        Using a macro, use the action "Fetch All Items from Popup Menu" and pick the popup you want. In this example, I'm using the "Clip List" popup.

        Create a new script and paste this script:

        function getPopupMenuItems(popup) {
            // Get the popup items 
            let popupMenuItems = popup.menuItems.map(x => x.path)
            //Activate Pro tools to dismiss the popup
            sf.ui.proTools.appActivateMainWindow()
        
            log(popupMenuItems)
        }
        
        //Activate Pro tools
        sf.ui.proTools.appActivateMainWindow()
        
        
        getPopupMenuItems(
            //==//  Paste code from element between the //==//. REMEMBER TO DELETE THE LAST ;
            
            //==//
        )
        

        now, go back to the macro and copy the action as Javascript:

        And paste it on the script I sent you between the //==//. MAKE SURE YOU DELETE THE LAST ;

        once you run the script, you will get all the menu and submenus:

        From there you can copy the text to paste somewhere else.

        1. samuel henriques @samuel_henriques
            2021-04-21 21:20:15.415Z

            To get a list from menus,:

            setup the log the same way.
            menus work a bit differently. The way this script work, you need to type the menu name to get its items. Sorry but one word only.

            sf.ui.proTools.appActivateMainWindow()
            
            let menuItems = sf.ui.proTools.getMenuItem("Edit").children.first.children.map(c => c.title.value)
            
            log(menuItems)
            

            When you run the script you'll get the first page.

            Then you can copy the submenu name you want, Lets use "Automation" and add it to the script like so:

            sf.ui.proTools.appActivateMainWindow()
            
            let menuItems = sf.ui.proTools.getMenuItem("Edit", "Automation").children.first.children.map(c => c.title.value)
            
            log(menuItems)
            

            and now you have all the items from the submenu:

            Hope this helps, let me know how it goes

            1. JJohn Morris @John_Morris7
                2021-04-21 21:39:56.892Z

                Thanks, Samuel!

                1. samuel henriques @samuel_henriques
                    2021-04-22 09:53:25.955Z2021-04-23 09:42:10.769Z

                    Hello everyone, here's a little tool to ease writing of menu paths:
                    This is for menus only, not popupMenus and should work on any app.

                    Use with a trigger while app is focussed.

                    Let me know how it works.

                    function prompt(item) {
                        let ptMenuAllPrompt = sf.interaction.popupSearch({
                            items: item.map(x => ({ name: x }))
                        }).item.name
                        return ptMenuAllPrompt
                    }
                    
                    
                    
                    /**
                     * @param {array} path
                     */
                    
                    function menuPathPrompt(path) {
                    
                        let pathPrompt = sf.interaction.displayDialog({
                            buttons: ["Cancel", "Copy Path to Action", "Copy Path to Clipboard"],
                            defaultButton: "Copy Path to Clipboard",
                            cancelButton: "Cancel",
                            title: "Menu Path Tool",
                            prompt: path.map(function (item) { return "\"" + item + "\"" }).join(', '),
                        }).button
                    
                        //  Copy to Clipboard
                        if (pathPrompt == "Copy Path to Clipboard") {
                    
                            sf.clipboard.setText({
                            text: path.map(function (item) { return "\"" + item + "\"" }).join(', '),
                            })
                        }
                    
                        // Copy to Macro Action
                        if (pathPrompt == "Copy Path to Action") {
                            // Activate SoundFlow
                            sf.ui.app("org.soundflow.sfsx.gui").appActivate()
                            // Coundn't avoid this wait
                            sf.wait({ intervalMs: 500 })
                    
                            path.forEach(p => {
                                sf.clipboard.setText({ text: p });
                    
                                sf.ui.frontmostApp.menuClick({ menuPath: ['Edit', 'Paste'] });
                    
                                sf.keyboard.press({ keys: 'return' });
                            });
                        }
                    }
                    
                    
                    const activeAppBundleID = sf.ui.frontmostApp.activeBundleID;
                    
                    // Array of Main Menu Items
                    const mainMenuItems = sf.ui.app(activeAppBundleID).children.whoseRole.is("AXMenuBar").first.children.whoseRole.is("AXMenuBarItem").map(x => x.title.value)
                    
                    // Choose Main Menu Item
                    const mainMenuItemsPrompt = prompt(mainMenuItems)
                    
                    // Array of Menu Items
                    const menuItems = sf.ui.app(activeAppBundleID).getMenuItem(mainMenuItemsPrompt).children.first.children.map(c => c.title.value).filter(x => x)
                    
                    // Choose Menu Item
                    const menuItemsPrompt = prompt(menuItems)
                    
                    // Array of Sub-Menu Items
                    const subMenuItems = sf.ui.app(activeAppBundleID).getMenuItem(mainMenuItemsPrompt, menuItemsPrompt).children.first.children.map(c => c.title.value).filter(x => x)
                    
                    // If no Sub-Menu Exists
                    if (subMenuItems.length == 0) {
                    
                        // Show Path
                        menuPathPrompt([mainMenuItemsPrompt, menuItemsPrompt])
                    
                    } else {
                    
                        // Choose Sub-Menu Item
                        let subMenuItemsPrompt = prompt(subMenuItems)
                    
                        // Array of Sub2-Menu Items
                        const subMenu2Items = sf.ui.app(activeAppBundleID).getMenuItem(mainMenuItemsPrompt, menuItemsPrompt, subMenuItemsPrompt).children.first.children.map(c => c.title.value).filter(x => x)
                    
                        // If no Sub2-Menu Exists
                        if (subMenu2Items.length == 0) {
                            // Show Path
                            menuPathPrompt([mainMenuItemsPrompt, menuItemsPrompt, subMenuItemsPrompt])
                        } else {
                    
                            // Choose Sub2-Menu Item
                            const subMenu2ItemsPrompt = prompt(subMenu2Items)
                            // Show Path
                            menuPathPrompt([mainMenuItemsPrompt, menuItemsPrompt, subMenuItemsPrompt, subMenu2ItemsPrompt])
                        }
                    }
                    
                    1. samuel henriques @samuel_henriques
                        2021-04-22 17:12:48.856Z2021-04-23 09:42:48.013Z

                        and here's a version for Popup menus.

                        Pick your element and paste de code on mu script between the //==//, REMEMBER TO DELETE THE LAST ;

                        /**
                         * @param {array} path
                         */
                        
                        function menuPathPrompt(path) {
                        
                            let pathPrompt = sf.interaction.displayDialog({
                                buttons: ["Cancel", "Copy Path to Action", "Copy Path to Clipboard"],
                                defaultButton: "Copy Path to Clipboard",
                                cancelButton: "Cancel",
                                title: "Popup Menu Path Tool",
                                prompt: path.map(function (item) { return "\"" + item + "\"" }).join(', '),
                            }).button
                        
                            //  Copy to Clipboard
                            if (pathPrompt == "Copy Path to Clipboard") {
                        
                                sf.clipboard.setText({
                                    text: path.map(function (item) { return "\"" + item + "\"" }).join(', '),
                                })
                            }
                        
                            // Copy to Macro Action
                            if (pathPrompt == "Copy Path to Action") {
                                // Activate SoundFlow
                                sf.ui.app("org.soundflow.sfsx.gui").appActivate()
                                // Coundn't avoid this wait
                                sf.wait({ intervalMs: 500 })
                        
                                path.forEach(p => {
                                    sf.clipboard.setText({ text: p });
                        
                                    sf.ui.frontmostApp.menuClick({ menuPath: ['Edit', 'Paste'] });
                        
                                    sf.keyboard.press({ keys: 'return' });
                                });
                            }
                        }
                        
                        function prompt(item) {
                            let ptMenuAllPrompt = sf.interaction.popupSearch({
                                items: item.map(x => ({ name: x }))
                            }).item.name
                            return ptMenuAllPrompt
                        }
                        
                        function onlyUnique(value, index, self) {
                            return self.indexOf(value) === index;
                        }
                        
                        
                        function getPopupMenuItems(popup) {
                            // Get the popup items 
                            const popupMenuItems = popup.menuItems.map(x => x.path)
                        
                            // Array of First Menu Items
                            let firstMenu = popupMenuItems.map(x => x[0]).filter(onlyUnique);
                        
                            // Choose Menu Item
                            const firstMenuPrompt = prompt(firstMenu)
                        
                            // Array of Second Menu Items
                            const secondMenu = popup.menuItems.filter(x => x.path[0] == firstMenuPrompt).map(x => x.path[1]).filter(onlyUnique);
                        
                            if (secondMenu.length == 0 || secondMenu[0] == null) {
                                // Show Path
                                menuPathPrompt([firstMenuPrompt])
                        
                            } else {
                        
                                // Choose Menu Item
                                const secondMenuPrompt = prompt(secondMenu)
                        
                                // Array of Third Menu Items
                                const thirdMenu = popup.menuItems.filter(x => x.path[0] == firstMenuPrompt).filter(x => x.path[1] == secondMenuPrompt).map(x => x.path[2]).filter(onlyUnique);
                        
                                if (thirdMenu.length == 0 || thirdMenu[0] == null) {
                                    // Show Path
                                    menuPathPrompt([firstMenuPrompt, secondMenuPrompt])
                                } else {
                                    // Choose Menu Item
                                    const thirdMenuPrompt = prompt(thirdMenu)
                        
                                    // Array of Fourth Menu Items
                                    const fourthMenu = popup.menuItems.filter(x => x.path[0] == firstMenuPrompt).filter(x => x.path[1] == secondMenuPrompt).filter(x => x.path[2] == thirdMenuPrompt).map(x => x.path[3]).filter(onlyUnique);
                        
                        
                                    if (fourthMenu.length == 0 || fourthMenu[0] == null) {
                                        // Show Path
                                        menuPathPrompt([firstMenuPrompt, secondMenuPrompt, thirdMenuPrompt])
                                    } else {
                                        // Choose Menu Item
                                        const fourthMenuPrompt = prompt(fourthMenu)
                                        // Show Path
                                        menuPathPrompt([firstMenuPrompt, secondMenuPrompt, thirdMenuPrompt, fourthMenuPrompt])
                                    }
                                }
                            }
                        }
                        
                        
                        getPopupMenuItems(
                            //==//  Paste code from "Fech All Items From Popup Menu" element between the //==//. REMEMBER TO DELETE THE LAST ;
                            //==//
                        
                        //Paste Action Code Here, REMEMBER TO DELETE THE LAST ;
                        
                            //==//
                            //==//
                        )
                        
                        
                        1. samuel henriques @samuel_henriques
                            2021-04-23 09:14:10.627Z2021-04-23 09:20:26.190Z

                            UPDATE: you can now paste the path to the macro action.
                            Both Popup Menu Script and Menu Script have this function.

                            Select the area you want the paste the path

                            Now activate the app you want to the the path from, in this case activate safari.

                            Then run the code with a trigger.

                            and choose "Copy Path to Action"

                            1. FFukurou Toshima @Fukurou_Toshima
                                2024-12-05 07:46:31.714Z

                                Hi samuel,

                                I wonder if I can copy ALL names of AAX plugins currently installed as it is displayed on the pop up menu on Pro Tools and make the lists of them not to miscapitalize.
                                Im setting up my presets for Teezio Plugin Loader but I have a plenty of plugins so it is not impractical to go back and forth between soundflow edit window and Pro Tools pop up menu.
                                It helps so much if there is the plugin name list as a kind of text file.
                                So if I use the script in this thread, which point do you think is right place to capture to obtain all names of the plugins?

                      • In reply toJohn_Morris:
                        Kitch Membery @Kitch2021-04-21 21:31:44.909Z

                        @samuel_henriques beat me to it but here is similar way,

                        sf.ui.proTools.appActivateMainWindow();
                        
                        const proToolsMenuNames = sf.ui.proTools.childrenByRole('AXMenuBar').map(x => x.children.map(m => ({
                            menu: m.title.invalidate().value,
                            menuItems: m.children.map(mi => mi.children.map(i=>i.title.invalidate().value).filter(i=>i))[0],
                        })));
                        
                        sf.file.writeJson({
                            path:'~/Desktop/Pro Tools Menu Items',
                            json:proToolsMenuNames
                        });
                        

                        Run this script and it will create a JSON file on your desktop named "Pro Tools Menu Items" that has all the menu items. Open it with the text edit application and copy and paste away :-)

                        1. JJohn Morris @John_Morris7
                            2021-04-21 21:40:57.540Z

                            Thanks Kitch! It's clear you are a lazy man too!

                            1. Kitch Membery @Kitch2021-04-21 21:54:34.812Z

                              Hahahaha :-)

                              And a bad speller!

                              Rock on!

                            2. In reply toKitch:
                              samuel henriques @samuel_henriques
                                2021-04-21 21:44:26.665Z

                                Nice one @Kitch, thank you!

                                1. Kitch Membery @Kitch2021-04-21 21:56:34.331Z

                                  @samuel_henriques & @John_Morris7,

                                  Come to think of it my method only gets one menu Item deep. I'll take a look at it over the next few days and see if I can make it dig deeper :-)

                              • J
                                In reply toJohn_Morris:
                                Jonathan Johnson @Jonathan_Johnson
                                  2025-03-08 19:19:48.196Z

                                  hey looking at this thread, i am opening the log file ( see top of the thread) , but after i clear it , the log starts logging info immediately to the point that the page is filed in about 2 sec,

                                  Im understanding the point here is to clear the log filets a move and copy, but the log file is auto updating very fast. seem off...