No internet connection
  1. Home
  2. How to

Elastic Audio and ARA Track Select Macro for Pro Tools 2025.10

By Emilio Diaz @Emilio_Diaz
    2025-11-26 15:48:17.884Z

    Hi, im trying to find a macro that can select the elastic audio and ARA mode on selected tracks. The previous macros have stoped working with this new update. Thanks in advance.

    • 20 replies

    There are 20 replies. Estimated reading time: 16 minutes

    1. Kitch Membery @Kitch2025-11-26 17:37:55.617Z2025-11-26 21:57:42.597Z

      Hi @Emilio_Diaz

      Try this script...

      sf.ui.useSfx();
      sf.ui.proTools.mainWindow.invalidate();
      
      /**
       * @param {object} obj
       * @param {string} obj.pluginName
       * @param {'Elastic Audio plugin'|'ARA plugin'} obj.pluginType
       */
      function selectElasticAudioOrAraPlugin({ pluginName, pluginType }) {
          const track = sf.ui.proTools.selectedTrack;
          const trackHeight = track.frame.h;
      
          if (trackHeight <= 43) {
              const trackOptionsPopupMenu = sf.ui.proTools.selectedTrack.getFirstWithTitle("Track options");
      
              const subMenu = "Elastic Audio/ARA"
              const subPath = pluginType;
      
              trackOptionsPopupMenu.popupMenuSelect({
                  menuPath: [subMenu, pluginType, pluginName],
                  isOption: true,
                  isShift: true,
              });
          } else {
              const elasticAudioOrAraPlugInSelectorBtn = track.popupButtons.whoseTitle.is("Elastic Audio or ARA Plugin selector").first;
      
              elasticAudioOrAraPlugInSelectorBtn.popupMenuSelect({
                  menuPath: [pluginType, pluginName],
                  isOption: true,
                  isShift: true,
              });
          }
      }
      

      Here are some example function calls.

      selectElasticAudioOrAraPlugin({
          pluginName: "Varispeed",
          pluginType: "Elastic Audio plugin",
      });
      
      selectElasticAudioOrAraPlugin({
          pluginName: "Melodyne",
          pluginType: "ARA plugin",
      });
      

      Let me know if that works for you or if you have any questions. :-)

      1. Ben Rubin @Ben_Rubin
          2025-11-26 21:26:40.175Z

          Trying this out and getting this error:

          The menu item was not found in the popup menu (ara: Line 25)

          doesnt seem like SF is not seeing the ARA selector button. No tool tip happens. When I pick it, it get: sf.ui.proTools.sfx.selectedTrack.popupButtons.allItems[4]
          i tried with no plugin selected and with a plugin selected and got the same result.

          1. Ben Rubin @Ben_Rubin
              2025-11-26 21:28:27.929Z

              also, a more general question for @Kitch

              still trying to get my head around when invalidate is required and wondering when it should be used at the beginning of a script. and wondering why it wouldnt be used at the end of a script also if something in the interface or tracks changes.

              also, when this script works it will be great and thinking there should be a repository for all of the scripts in the forum.

              1. Kitch Membery @Kitch2025-11-26 23:07:40.578Z

                Hi @Ben_Rubin

                Thanks for the suggestion re the repository. Please request this in the Ideas section of the forum so we can track it for consideration. :-)


                Regarding your invalidation question. I believe there was a thread from a while ago where I explained invalidation cases for you (I think it was quite some time ago, though)... however, it may be more beneficial for me to answer your questions about invalidation on a case-by-case basis. ie "Why was invalidate used here?"

                In this case, we're using sf.ui.proTools.mainWindow.invalidate(); at the top of the script.

                The .invalidate() method forces SoundFlow to refresh the entire UI subtree for the element to the left of the call, clearing not only the element itself but all of its children and their nested descendants. This ensures SoundFlow rebuilds a fresh, accurate view of the UI structure before your script interacts with it.

                The Pro Tools' main window contains many elements, including track headers. In this example, the first time an element is referenced in a new SoundFlow session usingsf.ui.proTools.mainWindow, SoundFlow caches the current information about the main window internally to avoid it having to collect all the data in the main window every time the mainWindow or a child element is referenced.

                There are many cases where SoundFlow takes care of the invalidation for you, but in cases where large amounts of information need to be collected (For example, the main window in a big Pro Tools session). It's not efficient to scrape the whole window every time.

                The cached information about Pro Tools's main window may sometimes be stale, due to things like tracks being deleted or the order of tracks being changed.

                I may be oversimplifying the subject, but let me know if you need further clarification on why I chose and found it necessary to invalidate Pro Tools' main window in this case.

                1. Kitch Membery @Kitch2025-11-26 23:24:26.045Z

                  Note: @Ben_Rubin, it took me quite some time to get a handle on when to use invalidation, so if in doubt, start a thread with a refined example code for any specific examples. :-)

                  1. Ben Rubin @Ben_Rubin
                      2025-11-27 02:00:54.214Z

                      Thanks as always, @kitch! I had this thread pinned in firefox, but i dont think it's the one you are referring to.
                      When to use invalidate()

                      I understand what you're saying above. So is it unnecessary to invalidate after making changes to the UI? Just before? Or only deeper in the script when something has been changed and the cache should be updated to reflect the change for any subsequent commands?

                      1. Kitch Membery @Kitch2025-11-27 02:36:28.528Z

                        Great questions...

                        "So is it unnecessary to invalidate after making changes to the UI" -> Yes, it's unnecessary to invalidate after making a change. The best practice is to invalidate only when fresh information is needed (So yes "Just before").

                        For example, if your script deletes a track programmatically, the next time you need to retrieve updated track information, you’ll need to invalidate the main window again before running the next command that relies on that fresh data. :-)

                2. In reply toBen_Rubin:
                  Kitch Membery @Kitch2025-11-26 21:42:11.114Z

                  My bad... Poor script from me. I'll update it shortly.

                  1. In reply toBen_Rubin:
                    Kitch Membery @Kitch2025-11-26 22:00:06.432Z

                    I've updated the script now. Let me know if that works for you now. :-)

                    1. Ben Rubin @Ben_Rubin
                        2025-11-27 02:24:03.171Z

                        thanks @kitch, now I am getting this error

                        Could not ensure Track List View is accessible (elastic test: Line 10)
                        Could not open Track List
                        ClickMenu Element UI required

                        yes, my track list is already open. Tried both micro and medium track sizes

                        1. Kitch Membery @Kitch2025-11-27 02:43:08.918Z

                          Hmmm, it's working for me, here...

                          Can you try creating a new script and running the script in this reply...

                          1. Ben Rubin @Ben_Rubin
                              2025-11-27 03:03:20.663Z2025-11-27 03:12:58.246Z

                              Now it seems to be working. Smoking fast actually. Lots of scripts were kicking that error. So i restarted SoundFlow and now it works.

                              Already had a version of this in template form, and this was easy to convert.

                              What this script is still missing is the option for "None." so i can delete a plugin. Cant figure out how to do that will all the sub-menus.

                              1. Ben Rubin @Ben_Rubin
                                  2025-12-05 19:01:49.171Z

                                  hey @kitch, just a quick ping about accessing "None" in this script. Any help is always appreciated.

                                  1. Kitch Membery @Kitch2025-12-05 19:14:34.442Z

                                    Here you go...

                                    sf.ui.useSfx();
                                    sf.ui.proTools.mainWindow.invalidate();
                                    
                                    /**
                                     * @param {object} obj
                                     * @param {string} obj.pluginName
                                     * @param {'Elastic Audio plugin'|'ARA plugin'} [obj.pluginType]
                                     */
                                    function selectElasticAudioOrAraPlugin({ pluginName, pluginType }) {
                                        const track = sf.ui.proTools.selectedTrack;
                                        const trackHeight = track.frame.h;
                                    
                                        if (trackHeight <= 43) {
                                            const trackOptionsPopupMenu = sf.ui.proTools.selectedTrack.getFirstWithTitle("Track options");
                                    
                                            const subMenu = "Elastic Audio/ARA"
                                    
                                            const menuPath = pluginName === "None"
                                                ? [subMenu, "None"]
                                                : [subMenu, pluginType, pluginName];
                                    
                                    
                                            trackOptionsPopupMenu.popupMenuSelect({
                                                menuPath,
                                                isOption: true,
                                                isShift: true,
                                            });
                                        } else {
                                            const elasticAudioOrAraPlugInSelectorBtn = track.popupButtons.whoseTitle.is("Elastic Audio or ARA Plugin selector").first;
                                    
                                            const menuPath = pluginName === "None"
                                                ? ["None"]
                                                : [pluginType, pluginName];
                                    
                                            elasticAudioOrAraPlugInSelectorBtn.popupMenuSelect({
                                                menuPath,
                                                isOption: true,
                                                isShift: true,
                                            });
                                        }
                                    }
                                    
                                    selectElasticAudioOrAraPlugin({
                                        pluginName: "None",
                                    });
                                    
                                    1. Ben Rubin @Ben_Rubin
                                        2025-12-05 19:28:39.749Z

                                        Brilliant, thanks. havent encountered that variable structure yet. always learning!

                                        1. Kitch Membery @Kitch2025-12-05 19:40:23.987Z

                                          Hi @Ben_Rubin

                                          Ahh yes... This is a ternary operator expression, which is a compact version of an if/else statement that returns one of two values depending on whether the condition is true or false.

                                                  const menuPath = pluginName === "None"
                                                      ? ["None"]
                                                      : [pluginType, pluginName];
                                          

                                          Breakdown:
                                          pluginName === "None" is the condition.
                                          • If the condition is true, the expression returns ["None"].
                                          • If the condition is false, it returns [pluginType, pluginName].
                                          • Whatever is returned gets assigned to menuPath.

                                          The longer version would look like this...

                                          let menuPath;
                                          if (pluginName === "None") {
                                              menuPath = ["None"];
                                          } else {
                                              menuPath = [pluginType, pluginName];
                                          }
                                          

                                          It is short, clean logic. It helps avoid repeating menuPath = in two branches. and is concise when you only need to choose between two values.

                                          I hope that helps.

                                          1. Ben Rubin @Ben_Rubin
                                              2025-12-05 21:13:49.054Z

                                              sure does. the explanation is much appreciated! Gonna start using it!

                            • In reply toKitch:
                              EEmilio Diaz @Emilio_Diaz
                                2025-11-27 01:05:36.949Z

                                Thanks Kitch, but I'm not getting anything to happen. No errors either.

                                1. Kitch Membery @Kitch2025-11-27 01:37:11.482Z

                                  Hi @Emilio_Diaz

                                  Are you on the latest version of Pro Tools? 2025.10? and SoundFlow 6.0.1+

                                  If so, it's important to note, with SoundFlow's new SFX integration that a script like this no longer needs to open the pop-up menu to click the menu path. So double-check that the Elastic audio or ARA plugin was not added to the track without you realizing.

                                  To test the script, please copy and paste the following code into a new script.

                                  sf.ui.useSfx();
                                  sf.ui.proTools.mainWindow.invalidate();
                                  
                                  /**
                                   * @param {object} obj
                                   * @param {string} obj.pluginName
                                   * @param {'Elastic Audio plugin'|'ARA plugin'} obj.pluginType
                                   */
                                  function selectElasticAudioOrAraPlugin({ pluginName, pluginType }) {
                                      const track = sf.ui.proTools.selectedTrack;
                                      const trackHeight = track.frame.h;
                                  
                                      if (trackHeight <= 43) {
                                          const trackOptionsPopupMenu = sf.ui.proTools.selectedTrack.getFirstWithTitle("Track options");
                                  
                                          const subMenu = "Elastic Audio/ARA"
                                          const subPath = pluginType;
                                  
                                          trackOptionsPopupMenu.popupMenuSelect({
                                              menuPath: [subMenu, pluginType, pluginName],
                                              isOption: true,
                                              isShift: true,
                                          });
                                      } else {
                                          const elasticAudioOrAraPlugInSelectorBtn = track.popupButtons.whoseTitle.is("Elastic Audio or ARA Plugin selector").first;
                                  
                                          elasticAudioOrAraPlugInSelectorBtn.popupMenuSelect({
                                              menuPath: [pluginType, pluginName],
                                              isOption: true,
                                              isShift: true,
                                          });
                                      }
                                  }
                                  
                                  selectElasticAudioOrAraPlugin({
                                      pluginName: "Varispeed",
                                      pluginType: "Elastic Audio plugin",
                                  });
                                  

                                  Then select an audio track in Pro Tools in the Edit window, and run the script. Varispeed should then be selected for the track.

                                  If the above steps don't work, it would be great if you could provide a screen recording to help troubleshoot further.

                                  Thanks in advance.

                                  1. EEmilio Diaz @Emilio_Diaz
                                      2025-11-27 17:32:51.875Z

                                      I got it to work. I wasn't sure how to use the function calls. Thanks.