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

Adding multiple sends but getting 'Could not open popup menu error'

By Alistair McLean @Alistair_McLean
    2023-01-05 03:53:00.468Z

    Hi all,

    Very new to soundflow and just experimenting with combining a few existing scripts. I've been trying to write little script to open my three most used sends in Send slots 1/2/3 in Pro Tools, based off the Select Track Insert/Send macros with a few added scripts to allow it to work on multiple channels at once and fire from both the edit and mix window.

    It's working quite well, however I run into an error if the Edit window is zoomed out enough that not all 3 sends are visible. When this occurs I get a 'Could not open popup menu error', with the log telling me 'Could not open popup menu
    Popup menu was not found
    Popup window was not found after waiting 2000 ms'

    I'm assuming the workaround is to build in a 'Zoom In' function for the edit window, but if I was doing this to multiple tracks it may be a little crazy!

    Thanks

    Solved in post #7, click to view
    • 9 replies
    1. A
      Alistair McLean @Alistair_McLean
        2023-01-05 03:55:10.727Z

        Current script is here, please ignore the placeholders copied over from the other scripts I've pirated... still trying not to get lost in the scripts!

        sf.ui.proTools.invalidate();
        
        // Place the following two functions at the top of your script:
        
        // #1
        function mainWindowStatus() {
            if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) {
                sf.ui.proTools.menuClick({
                        menuPath: ["Window", "Edit"],
                    });
                return "Mix";
            } else {
                return "Edit";
            }
        }
        
        //#2
        function returnToStartingMainWIndow(mainWindow) {
            if (mainWindow =="Mix") {
                    sf.ui.proTools.menuClick({
                        menuPath: ["Window", "Mix"],
                    });
            }
        }
        
        
        /// Place this line at the top of your script
        let startingWindow = mainWindowStatus();
        
        function doForAllSelectedTracks(action) {
            var originallySelectedTrackNames = sf.ui.proTools.selectedTrackNames;
        
            try {
                sf.ui.proTools.selectedTrackHeaders.forEach(track => {
                    track.trackSelect();
                    action(track);
                });
            }
            finally {
                sf.ui.proTools.trackSelectByName({ names: originallySelectedTrackNames });
            }
        }
        
        /**@param {AxPtTrackHeader} track */
        function trackFunc(track) {
        
         
         sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
            insertOrSend: "Send",
            pluginNumber: 1,
            pluginPath: ["bus","StereoVerb (Stereo)"],
            selectForAllSelectedTracks: true,
        });
        
        sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
            insertOrSend: "Send",
            pluginNumber: 2,
            pluginPath: ["bus","LongVerb (Stereo)"],
            selectForAllSelectedTracks: true,
        });
        
        sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
            insertOrSend: "Send",
            pluginNumber: 3,
            pluginPath: ["bus","MonoVerb (Mono)"],
            selectForAllSelectedTracks: true,
        });
           
           
            log(track.normalizedTrackName);
        
        }
        
        doForAllSelectedTracks(trackFunc);
        
        
        
        // end your script with this line
        returnToStartingMainWIndow(startingWindow);```
        1. What the script needed was an extra command to scroll the selected track into view (line 36):

          sf.ui.proTools.invalidate();
          
          // Place the following two functions at the top of your script:
          
          // #1
          function mainWindowStatus() {
              if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) {
                  sf.ui.proTools.menuClick({
                          menuPath: ["Window", "Edit"],
                      });
                  return "Mix";
              } else {
                  return "Edit";
              }
          }
          
          //#2
          function returnToStartingMainWIndow(mainWindow) {
              if (mainWindow =="Mix") {
                      sf.ui.proTools.menuClick({
                          menuPath: ["Window", "Mix"],
                      });
              }
          }
          
          
          /// Place this line at the top of your script
          let startingWindow = mainWindowStatus();
          
          function doForAllSelectedTracks(action) {
              var originallySelectedTrackNames = sf.ui.proTools.selectedTrackNames;
          
              try {
                  sf.ui.proTools.selectedTrackHeaders.forEach(track => {
                      track.trackSelect();
                      track.trackScrollToView() // <====== This wil scroll each track into view
                      action(track);
                  });
              }
              finally {
                  sf.ui.proTools.trackSelectByName({ names: originallySelectedTrackNames });
              }
          }
          
          /**@param {AxPtTrackHeader} track */
          function trackFunc(track) {
          
           
           sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
              insertOrSend: "Send",
              pluginNumber: 1,
              pluginPath: ["bus","StereoVerb (Stereo)"],
              selectForAllSelectedTracks: true,
          });
          
          sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
              insertOrSend: "Send",
              pluginNumber: 2,
              pluginPath: ["bus","LongVerb (Stereo)"],
              selectForAllSelectedTracks: true,
          });
          
          sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
              insertOrSend: "Send",
              pluginNumber: 3,
              pluginPath: ["bus","MonoVerb (Mono)"],
              selectForAllSelectedTracks: true,
          });
             
             
              log(track.normalizedTrackName);
          
          }
          
          doForAllSelectedTracks(trackFunc);
          
          
          
          // end your script with this line
          returnToStartingMainWIndow(startingWindow);
          
          1. Once you've scrolled to the first selected track theres no need to use doForAllSelectedTracks because the trackInsertOrSendSelect has a selectForAllSelectedTracks parameters . The script will run much faster since it only has to instantiate each send once:
            (I've also changed the way it scrolls to the first selected track so that it's more robust - sometime if the first selected track is the top track in the edit window it won't scroll properly)

            sf.ui.proTools.invalidate();
            
            // Place the following two functions at the top of your script:
            
            // #1
            function mainWindowStatus() {
                if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) {
                    sf.ui.proTools.menuClick({
                        menuPath: ["Window", "Edit"],
                    });
                    return "Mix";
                } else {
                    return "Edit";
                }
            }
            
            //#2
            function returnToStartingMainWIndow(mainWindow) {
                if (mainWindow == "Mix") {
                    sf.ui.proTools.menuClick({
                        menuPath: ["Window", "Mix"],
                    });
                }
            }
            
            
            /// Place this line at the top of your script
            let startingWindow = mainWindowStatus();
            
            //Get selected Tracks
            const selectedTracks = sf.ui.proTools.selectedTrackNames
            
            //Scroll to first selected track
            sf.ui.proTools.trackSelectByName({
                names: [selectedTracks[0]]
            })
            sf.ui.proTools.selectedTrack.trackScrollToView();
            
            //Reselect Tracks
            sf.ui.proTools.trackSelectByName({names:selectedTracks})
            
            
            // Insert Sends
            sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
                insertOrSend: "Send",
                pluginNumber: 1,
                pluginPath: ["bus", "StereoVerb (Stereo)"],
                selectForAllSelectedTracks: true,
            });
            
            sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
                insertOrSend: "Send",
                pluginNumber: 2,
                pluginPath: ["bus", "LongVerb (Stereo)"],
                selectForAllSelectedTracks: true,
            });
            
            sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
                insertOrSend: "Send",
                pluginNumber: 3,
                pluginPath: ["bus", "MonoVerb (Mono)"],
                selectForAllSelectedTracks: true,
            });
            
            // end your script with this line
            returnToStartingMainWIndow(startingWindow);
            
            1. Finally you could create an object that contains the send numbers and bus paths and loop through that object and instantiate the sends:

              sf.ui.proTools.invalidate();
              
              // Place the following two functions at the top of your script:
              
              // #1
              function mainWindowStatus() {
                  if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) {
                      sf.ui.proTools.menuClick({
                          menuPath: ["Window", "Edit"],
                      });
                      return "Mix";
                  } else {
                      return "Edit";
                  }
              }
              
              //#2
              function returnToStartingMainWIndow(mainWindow) {
                  if (mainWindow == "Mix") {
                      sf.ui.proTools.menuClick({
                          menuPath: ["Window", "Mix"],
                      });
                  }
              }
              
              /// Place this line at the top of your script
              let startingWindow = mainWindowStatus();
              
              //Get selected Tracks
              const selectedTracks = sf.ui.proTools.selectedTrackNames
              
              //Scroll to first selected track
              sf.ui.proTools.trackSelectByName({
                  names: [selectedTracks[0]]
              })
              sf.ui.proTools.selectedTrack.trackScrollToView();
              
              //Reselect Tracks
              sf.ui.proTools.trackSelectByName({ names: selectedTracks })
              
              // Define sendsToInstanatiate object
              const sendsToInstanatiate = {
                  1: ["bus", "StereoVerb (Stereo)"],
                  2: ["bus", "LongVerb (Stereo)"],
                  3: ["bus", "MonoVerb (Mono)"]
              }
              
              // Insert sends
              for (const send in sendsToInstanatiate) {
                  sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
                      insertOrSend: "Send",
                      pluginNumber: +send,
                      pluginPath: sendsToInstanatiate[send],
                      selectForAllSelectedTracks: true,
                  });
              }
              
              // end your script with this line
              returnToStartingMainWIndow(startingWindow);
              
              1. AAlistair McLean @Alistair_McLean
                  2023-01-05 22:46:58.096Z

                  Thanks for such a quick and detailed reply Chris (and I think I pinched most of the existing code from things you had posted too!).

                  That is mostly working very well now, I'm still occasionally getting a 'could not make send slot visible' error which seems to be caused by small track heights in the edit window (and if the track heights are set very small I get a 'could not find selected track's insert/send selector button for the specified plugin').

                  The easy workaround is to set all track heights to jumbo or extreme and then set them back to their original size- is there a simple way to include that in the code?

                  Thanks for your help!

                  1. Chris Shaw @Chris_Shaw2023-01-05 23:43:49.998Z2023-01-06 00:35:10.820Z

                    Try this (a lot more code :)  )

                    /////////////////////////////////////////////
                    /// F U N C T I O N S  & C O N S T A N T S //
                    /////////////////////////////////////////////
                    
                    // Define track size lookup object {height in pixels : size name}
                    const trackSizes = {
                        16: 'micro',
                        23: 'mini',
                        43: 'small',
                        97: 'medium',
                        192: 'large',
                        300: 'jumbo',
                    };
                    
                    function setTrackSize(size) {
                    
                        const f = sf.ui.proTools.selectedTrack.frame;
                        let popupMenu = sf.ui.proTools.selectedTrack.popupMenuOpenFromElement({
                            relativePosition: { x: f.w - 10, y: 5 },
                            isOption: true,
                            isShift: true,
                        }).popupMenu;
                        popupMenu.menuClickPopupMenu({
                            menuPath: [size]
                        });
                    }
                    
                    // Place the following two functions at the top of your script:
                    // #1
                    function mainWindowStatus() {
                        if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) {
                            sf.ui.proTools.menuClick({
                                menuPath: ["Window", "Edit"],
                            });
                            return "Mix";
                        } else {
                            return "Edit";
                        }
                    }
                    
                    //#2
                    function returnToStartingMainWIndow(mainWindow) {
                        if (mainWindow == "Mix") {
                            sf.ui.proTools.menuClick({
                                menuPath: ["Window", "Mix"],
                            });
                        }
                    }
                    
                    
                    
                    ///////////////
                    /// M A I N ///
                    ///////////////
                    
                    sf.ui.proTools.invalidate();
                    
                    // Determine which window is focused (Mix / Edit)
                    let startingWindow = mainWindowStatus();
                    
                    //Get selected Tracks
                    const selectedTracks = sf.ui.proTools.selectedTrackNames
                    
                    //Scroll to first selected track
                    sf.ui.proTools.trackSelectByName({
                        names: [selectedTracks[0]]
                    })
                    sf.ui.proTools.selectedTrack.trackScrollToView();
                    
                    //determine size of first selected track
                    const selectedTrackHeight = sf.ui.proTools.selectedTrack.frame.h;
                    
                    // Get original track size and whether it is too small
                    const originalTrackSize = trackSizes[selectedTrackHeight] || 'extreme';
                    const isTrackTooSmall = selectedTrackHeight < 43
                    
                    //resize track if necessary
                    if (isTrackTooSmall) setTrackSize("medium");
                    
                    //Reselect Tracks
                    sf.ui.proTools.trackSelectByName({ names: selectedTracks })
                    
                    // Define sendsToInstanatiate object
                    const sendsToInstanatiate = {
                        1: ["bus", "StereoVerb (Stereo)"],
                        2: ["bus", "LongVerb (Stereo)"],
                        3: ["bus", "MonoVerb (Mono)"]
                    }
                    
                    // Instantiate sends
                    for (const send in sendsToInstanatiate) {
                        sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
                            insertOrSend: "Send",
                            pluginNumber: +send,
                            pluginPath: sendsToInstanatiate[send],
                            selectForAllSelectedTracks: true,
                        });
                    }
                    
                    // Reset height of first selected track if necessary
                    if (isTrackTooSmall) {
                        sf.ui.proTools.trackSelectByName({ names: [selectedTracks[0]] })
                        setTrackSize(originalTrackSize)
                    }
                    // Reselect selected tracks
                    sf.ui.proTools.trackSelectByName({ names: selectedTracks })
                    
                    // Refocus Edit or Mix window
                    returnToStartingMainWIndow(startingWindow);
                    
                    Reply1 LikeSolution
                    1. I've refactored the above script - much more concise.

          2. A
            In reply toAlistair_McLean:
            Alistair McLean @Alistair_McLean
              2023-01-06 01:06:19.063Z

              Amazing Chris, working perfectly on big and small sessions! Really appreciate it. How do I buy you a beer or coffee to say thank you!

              1. A
                In reply toAlistair_McLean:
                Alistair McLean @Alistair_McLean
                  2024-10-29 04:06:20.343Z

                  A bit of a zombie thread, but with a recent PT update this script is now broken for me.
                  When using it I get some variation of the following:

                  '29.10.2024 15:04:42.05 [Backend]: Logging error in action (01) TrackSelectInsertOrSendAction: Could not select plugin menu item: 'bus: Long Verb (Stereo)'
                  !! Command Error: Add Sends V3 [user:default:clcjtdkc0000ttm10ue3gnabr]:
                  Could not select plugin menu item: 'bus: Long Verb (Stereo)' (Add Sends V3: Line 93)
                  Could not open popup menu
                  Popup menu was not found
                  Popup window was not found after waiting 2000 ms'

                  This is not always consistent and sometimes will create a send in slot 1 but fail on slot 2, sometimes will fail straightaway, sometimes will create a send in slot 3 but no others! I presume there has been a change in the way PT identifies busses but I'm a bit lost!