No internet connection
  1. Home
  2. How to

Cache contents of a popup menu to speed up search times.

By Andrew Scheps @Andrew_Scheps
    2020-03-19 16:00:45.505Z

    As requested, a new thread to discuss caching the contents of a popup menu to speed up searching. Specifically (in my case) the inserts menu

    Solved in post #6, click to view
    • 10 replies
    1. Hi Andrew

      Please see this example. It caches the contents of the insert search menu.
      The first time you run it it will be slow (since you have a ton of plugins), the next time it should be instant.

      sf.ui.proTools.appActivateMainWindow();
      
      function getFirstFreeInsertIndex() {
          var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons;
          let insertArray = [2, 3, 4, 5, 6, 7, 8, 9, 1, 0];
          for (let i = 0; i < insertArray.length; i++)
              if (btns[insertArray[i]].value.invalidate().value === "unassigned") return (insertArray[i]);
      
          throw 0;
      }
      
      function addNewInsert() {
      
          var insertBtn = sf.ui.proTools.selectedTrack.insertSelectorButtons[getFirstFreeInsertIndex()];
      
          var menuItems = globalState.cachedInsertMenuItems;
          if (!menuItems) {
              menuItems = insertBtn.popupMenuFetchAllItems().menuItems;
              globalState.cachedInsertMenuItems = menuItems;
          }
      
          var selectedPath = sf.interaction.popupSearch({
              items: menuItems.map(mi => ({ name: mi.path.join(' -> '), path: mi.path })),
          }).item.path;
      
          insertBtn.popupMenuSelect({
              menuPath: selectedPath
          });
      }
      
      addNewInsert();
      
      1. Andrew Scheps @Andrew_Scheps
          2020-03-20 10:09:46.998Z

          This works great, thanks!

          1. Andrew Scheps @Andrew_Scheps
              2020-04-02 10:01:13.596Z

              Just found a problem with this. If I first run the script on a mono track none of the stereo versions of the plugins are cached and therefore the script fails when trying to use it on a stereo track...

              1. Yea I guess that's to be expected. The only way to fix this would be to know if you're on a mono or stereo track and keep two different caches.

                You could use this code to determine the number of Pan sliders (1 for mono, 2 for stereo) - and then use that information to build 2 different caches:

                var numberOfPanSliders = sf.ui.proTools.selectedTrack.groups.whoseTitle.is('Audio IO').first.sliders.whoseTitle.startsWith('Audio Pan indicator').count;
                

                Let me know if you need help implementing it :)

                1. Actually it was super quick for me to do, so here you go:

                  sf.ui.proTools.appActivateMainWindow();
                  
                  function getFirstFreeInsertIndex() {
                      var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons;
                      let insertArray = [2, 3, 4, 5, 6, 7, 8, 9, 1, 0];
                      for (let i = 0; i < insertArray.length; i++)
                          if (btns[insertArray[i]].value.invalidate().value === "unassigned") return (insertArray[i]);
                  
                      throw 0;
                  }
                  
                  function addNewInsert() {
                  
                      var numberOfPanSliders = sf.ui.proTools.selectedTrack.groups.whoseTitle.is('Audio IO').first.sliders.whoseTitle.startsWith('Audio Pan indicator').count;
                  
                      var insertBtn = sf.ui.proTools.selectedTrack.insertSelectorButtons[getFirstFreeInsertIndex()];
                  
                      var cacheKey = 'cachedInsertMenuItems_' + numberOfPanSliders;
                      var menuItems = globalState[cacheKey];
                      if (!menuItems) {
                          menuItems = insertBtn.popupMenuFetchAllItems().menuItems;
                          globalState[cacheKey] = menuItems;
                      }
                  
                      var selectedPath = sf.interaction.popupSearch({
                          items: menuItems.map(mi => ({ name: mi.path.join(' -> '), path: mi.path })),
                      }).item.path;
                  
                      insertBtn.popupMenuSelect({
                          menuPath: selectedPath
                      });
                  }
                  
                  addNewInsert();
                  
                  ReplySolution
                  1. Andrew Scheps @Andrew_Scheps
                      2020-04-02 13:47:47.807Z

                      Works great, this is really elegant. Thanks!

                      1. In reply tochrscheuer:
                        Andrew Scheps @Andrew_Scheps
                          2020-04-02 19:55:57.732Z

                          There's actually a problem with the addNewInsert function if there is a plugin already there that changes the channel width. For instance if you have a mono track with a mono->stereo plugin in slot 3, slot 1 and 2 actually need to try and instantiate mono, slot 3 needs to instantiate mono or mono->stereo and slots 4-10 need stereo plugins.

                          At the moment all slots bring up the search for stereo plugins, so you can't insert anything before slot 4 (in this example).

                          1. Haha yea I had actually thought about that as well when you initially suggested caching, but I decided the easier route of ignoring it instead of pointing it out, since I thought it was still valuable to have caching.
                            In this scenario I believe you wouldn't be able to use caching, unless you could read the channel-width-changing plugins and then decide accordingly if you want to search the mono or stereo plugin cache.
                            You may be able to read this from iterating through the existing assignments up until that point, to see if there are any "(mono->stereo)" stuff present, but I don't remember if that parenthesis is available to read in the assignment.

                            1. A final workaround might be that you always open the popup menu and just read menu items until you know if we're in stereo or mono, and then dismiss the popup menu and use the cache from then on.
                              But that's quite the challenge to build since SF's built in popup menu functions that are designed to make this easy, would likely all collect all items (and thus be slow).
                              But you could potentially roll your own - if you can't read the channel width changing plugin assignments directly.

                              1. Andrew Scheps @Andrew_Scheps
                                  2020-04-03 10:19:12.502Z

                                  If I were making a commercial product with these scripts I'd have to do that, but considering I don't often use plugins to change the width of a channel I'll just leave it as it is. Thanks for clarifying.