No internet connection
  1. Home
  2. How to

Rudimentary question about popupMenuFetchAllItems and how to utilize in plugin menu

By Tristan Hoogland @Tristan
    2022-11-15 02:52:45.506Z

    Hi,

    This is a rudimentary question - I see the use of popupMenuFetchAllItems() (and various extensions of it) quite a lot in the forum and scripts and I know I can see how it would be useful to me, but I am having trouble wrapping my head around it. I was wondering if someone could kindly provide some information on how to use it so I can get a better handle on it, but also help with it in this example.

    In my specific case today, I'm hoping to

    1. Get the full plug-in name of the current insert
    2. use popupMenuFetchAllItems to index all plugins
    3. Then amend the original plugin name (from #1) using regex or slicing etc
    4. Then search the index of the popupMenuFetchAllItems from earlier to load another plugin with the amended name.

    Basically similar to what Chris Shaw did with his copy plugin to audiosuite function, but kept within the live, active plug-in world (not audiosuite).

    Any help would be appreciated!

    • 10 replies

    There are 10 replies. Estimated reading time: 13 minutes

    1. Kitch Membery @Kitch2022-11-15 07:06:18.454Z

      Hi @Tristan_Hoogland,

      Legend, I believe I created a script for you in our the last thread we had going that did something very similar. Did that not work? Or are you just trying to get an understanding of how its done?

      If you are free on Wednesday 11am PT come join us at the SoundFlow Hangout, I can possibly give you a more detailed rundown on how to do this.

      I also plan on answering here, but it may take me a day or two to get to it. :-)

      1. In reply toTristan:
        Kitch Membery @Kitch2022-11-15 07:54:22.919Z

        You can get the full plug-in name of the current insert (the frontmost plugin) like this

        const fullPluginName = sf.ui.proTools.pluginWindow.title.invalidate().value;
        
        log(fullPluginName);
        

        To fetch all the plug-in menu items from the front most plugin you can use this.

        sf.ui.proTools.appActivateMainWindow();
        
        const pluginMenuItems = sf.ui.proTools.pluginWindow.invalidate().popupButtons.whoseTitle.startsWith("Plug-In Selector").first.popupMenuFetchAllItems({ dismissMenu: true }).menuItems;
        
        log(pluginMenuItems);
        

        This will create an array of Menu Items containing important information about the Menu Item including the Path and UI Element.

        For step three in your post... how do you want to alter the full plugin name?

        For the forth step, you'll need to use either the Filter or Find method. Here is an example of using the find method to match the menu item from the popupMenuFetchAllItems().menuItems.

        sf.ui.proTools.appActivateMainWindow();
        
        const pluginMenuItems = sf.ui.proTools.pluginWindow.invalidate().popupButtons.whoseTitle.startsWith("Plug-In Selector").first.popupMenuFetchAllItems({ dismissMenu: true }).menuItems;
        
        const targetPath = [
            "plug-in",
            "EQ",
            "EQ3 1-Band (mono)"
        ];
        
        const matchingMenuItem = pluginMenuItems.find(menuItem => JSON.stringify(menuItem.path) === JSON.stringify(targetPath));
        
        log(matchingMenuItem);
        
        log(matchingMenuItem.path);
        

        Some of this is quite complex but I'm happy to provide more info if you need it.

        Rock on, Champion!

        1. TTristan Hoogland @Tristan
            2022-11-15 17:14:05.490Z

            Thanks Kitch!

            Firstly thanks so much as always. Yep definitely saw it in function in the other script (thanks!), just eager to increase the understanding a bit more so I can better implement it elsewhere. This is a little easier to digest so that helps, and for the most part I understand the concept of storing it in an array, I'm just having trouble naturally grasping how to then search the array and thus select another plugin.

            An example would be looking to amend the plugin name(s) as follows:
            iZotope, Inc. -> RX-8 Mouth De-click
            to:
            iZotope -> RX-9 Mouth De-click

            iZotope, Inc. -> RX-8 De-ess
            to:
            iZotope -> RX-9 Mouth De-ess
            etc

            What's great about this example is that I need to overcome two challenges:

            • Determine if it's a multichannel plug-in or a multi-mono in stereo, or a single instance (mono)
            • Be able to amend the iZotope, Inc. to iZotope

            While I know I could just specify the iZotope, Inc. to iZotope path easily, I actually have a few other things i'm working on where I'd love if the original plugin could be stored as a variable so I can utilize it in other plugin manufacturers.

            Let me know what you think king kitch!

            1. Kitch Membery @Kitch2022-11-15 19:29:34.656Z

              I'm more of a jester than a King ;-)

              There is a bit to digest here and it would be great to discuss this stuff in the Weekly Hangout if you are free as I can preemptively guess what your next questions will be.

              But to do what you are after check out the following script.

              //This is the original path to the plugin.
              const menuPath = ["plugin", "iZotope, Inc.", "RX-8 Mouth De-click"];
              
              //From the first section of the menu path work out if the plugin is multichannel
              const isMultichannel = menuPath[0] === "plugin" || menuPath[0] === ("multichannel plug-in");
              
              //From the first section of the menu path work out if the plugin is multichannel
              const isMultiMono = menuPath[0] === ("multi-mono plug-in");
              
              //This accesses the second (or 1th since Javascript index numbering starts at 0) item in the array
              //converting "iZotope, Inc." to "iZotope"
              menuPath[1] = menuPath[1].replace(", Inc.", "");
              
              //This accesses the second (or 2th since Javascript index numbering starts at 0) item in the array
              //converting "RX-8 Mouth De-click" to "RX-9 Mouth De-click"
              menuPath[1] = menuPath[1].replace("8", "9");
              
              log("Multichannel plugin: "+ isMultichannel);
              
              log("Multi-Mono plugin: "+ isMultiMono);
              
              log(menuPath);
              
              1. TTristan Hoogland @Tristan
                  2022-11-15 23:07:24.166Z

                  Thanks Kitch! Still a king in my eyes.

                  Oh i totally forgot to say - yes i'll jump in on the hangout tomorrow! I'll have a look at this and show you what I've got so far tomorrow. Appreciate your sage wisdom as always

                  1. In reply toKitch:
                    TTristan Hoogland @Tristan
                      2022-11-18 01:12:55.772Z

                      Hey Kitch,

                      I'm having a bit of trouble getting the script to recognize when it's a multi-channel plugin. It works great in both "stereo" and "mono" track-width instances though. I can already tell it's something simple and assuming it has something to do with the constant not being determined if it's true or false, and just chooses the path that appears first (which multichannel appears first).

                      Here's the portion of the script in how I'm using it:

                      
                          const currentPluginName = pluginMenuItems.find(mi => mi.element.isMenuChecked).path;
                      
                          //From the first section of the menu path work out if the plugin is multichannel
                          const isMultichannel = currentPluginName[0] === "plugin" || currentPluginName[0] === ("multichannel plug-in");
                      
                          //From the first section of the menu path work out if the plugin is multichannel
                          const isMultiMono = currentPluginName[0] === ("multi-mono plug-in");
                      
                          const path1 = currentPluginName[0]
                      
                          //category path
                          const path2 = currentPluginName[1]
                      
                          //actual plugin
                          const uadName = currentPluginName[2]
                      
                          //stereo or mono instance
                          const stripStereoMono = uadName.split(" (");
                      
                          //result should be "stereo)" or "mono)"
                          const stereoMono = " (" + stripStereoMono[1];
                      
                          //strip "UAD" "UA" Tags
                          const uadxName = uadName.replace(/(UAD UA\s)|(UAD\s)/g, "UADx ").split(" (").slice(0, -1).join("") + " Compressor" + stereoMono;
                      
                          sf.ui.proTools.appActivateMainWindow();
                      

                      Thanks!

                      1. Kitch Membery @Kitch2022-11-18 01:55:17.001Z

                        Ahh, yeah I see. I like what you did there!

                        I mentioned in the hangout, a way to do this with a lookup table (but for this example, I decided it was better to create an array of objects and filter them with the find method. That way you can get the plugin names, preset button positions, and paste button positions as you've specified.

                        Here is how you'd do it.

                        const uadXpluginLookupArray = [
                            {
                                uadPluginName: "UAD UA 1176LN Rev E",
                                uadPresetsButtonPosition: { x: 20, y: 300 },
                                uadXPluginName: "UADx UA 1176LN Rev E Compressor",
                                uadXPasteButtonPosition: { x: 20, y: 300 },
                            },
                            {
                                uadPluginName: "UAD UA 1176LN Rev A",
                                uadPresetsButtonPosition: { x: 10, y: 200 },
                                uadXPluginName: "UADx UA 1176LN Rev A Compressor",
                                uadXPasteButtonPosition: { x: 10, y: 200 },
                            },
                        ];
                        
                        //If this is the original path to the plugin.
                        const menuPath = ["plugin", "UAD", "UAD UA 1176LN Rev E (Stereo)"];
                        
                        //Get the width to add to the end of the plugin name.
                        const pluginWidth = menuPath[2].match(/\(([^)]+)\)/)[0];
                        
                        //Find the matching object in the 
                        const matchingPluginObject = uadXpluginLookupArray.find(plugin => {
                            return plugin.uadPluginName === menuPath[2].split(" (")[0];
                        });
                        
                        //Create the UADx pluing name
                        const targetPluginName = `${matchingPluginObject.uadXPluginName} ${pluginWidth}`;
                        
                        //This is the path to the UADx plugin
                        const uadXPluginPath = [
                            menuPath[0],
                            menuPath[1],
                            targetPluginName
                        ];
                        
                        log(uadXPluginPath); // Logs the Plugin Path
                        
                        log(matchingPluginObject.uadPluginName); //Logs the UAD plugin name
                        
                        log(matchingPluginObject.uadPresetsButtonPosition); //Logs the UAD plugin preset button position
                        
                        log(matchingPluginObject.uadXPluginName); //Logs the UADx plugin name
                        
                        log(matchingPluginObject.uadXPasteButtonPosition); //Logs the UADx plugin preset button position
                        

                        It may need a bit more of an explanation but I'm about to head into a Zoom meeting so if you have any questions let me know.

                        Rock on!

                        1. TTristan Hoogland @Tristan
                            2022-11-18 02:01:47.636Z

                            You went beyond here, mate! Thank you as always.

                            Perfect timing, too as I've just gone through the painful mouse-click coordinates for all the plugins. I'll implement everything here, have a play with it all and get back to you with where I'm at!

                            1. In reply toKitch:
                              TTristan Hoogland @Tristan
                                2022-11-18 04:07:20.683Z

                                Hey Kitch, one thing the array doesn’t take into account is the initial “copy settings” in the UAD plug is actually in a drop down menu.

                                So the actions need to be (in the example of 1176)
                                1 - Firstly, can we use the plug-in screen as a reference for the cursor? (That’s how I’m currently doing it)
                                2 - mouse position to x91, y357
                                3 - mouse click (drop down menu appears)
                                4 - move mouse down 51 on y axis to hover “copy settings”
                                5 - click copy settings.

                                Fortunately the move down distance is the same for all instances of the UAD plug

                                The paste coordinates are in the one place though - so nothing to worry about there!

                                1. Kitch Membery @Kitch2022-11-18 18:06:32.222Z

                                  Yeah that's all doable... I'll take a look at it when I get a chance.