No internet connection
  1. Home
  2. How to

Clip Gain by Clip Name

By samuel henriques @samuel_henriques
    2020-09-21 22:11:44.954Z

    Hello,
    I'm using this script that sets clip gain by the name of the clip.
    It looks like its working but:

    1 - First time I run it on the session it works great, but if I clear all clip gain and do it again (for the sake of testing), it'll do all the names but sets of
    1 dB or random, and fail to select all clips... random stuff. I need to close and open the session for the script to work again. This leads me to believe there's a coding error.

    2 - I would like to have an error correction in case the name of the clip doesn't exist on the session.

    Thank you so much.

    sf.ui.proTools.appActivateMainWindow();
    
    
    
    
    /////
     {
     var clipname = "Return Rob_05"
     var clipgain = 12
    
     clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    /////
    {
    var clipname = "SFX Unlock 1 REV"
    var clipgain = 16
    clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    ////
    {
    var clipname = "ANSWER REVEAL"
    var clipgain = 2
    clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    ////
    {
    var clipname = "Start Position_01"
    var clipgain = 12
    clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    ////
    {
    var clipname = "25 FREE Cinematic Transition Sound Effects"
    var clipgain = 15
    clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    ///
    {
    var clipname = "MS Battle of the Brains FX"
    var clipgain = 15
    clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    ////
    {
    var clipname = "SFX 30 sec Bell"
    var clipgain = 6
    clipselectandgain();
     sf.wait({
        intervalMs:1000,
    });
    }
    ////
    
    
    
    
    
    
    
    
    
    function clipselectandgain(){
    
    
    sf.keyboard.press({
        keys: "cmd+shift+f",
    });
    sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.elementWaitFor({
        waitType: "Appear",
    });
    sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.checkBoxes.whoseDescription.is('').first.checkboxSet({
        targetValue: "Enable",
    
    });
    
    
    sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({
        value: clipname,
    });
    
    sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.buttons.whoseTitle.is('OK').first.elementClick();
    
    //Go selectclipsoncliplist
    selectclipsoncliplist();
    
    
    
    
    //////GO CLIP GAIN
    sf.keyboard.press({
        keys: "ctrl+shift+up",
        repetitions: clipgain,
        fast: true,
    });
    sf.keyboard.press({
        keys: "cmd+shift+d",
    });
    
    
    }
    ///////////
    
    
    
    
    
    
    function selectclipsoncliplist(){
    
        
    // var view = sf.ui.proTools.mainWindow.clipListView;
    // view.childrenByRole("AXRow").first.children.allItems[1].children.first.elementClick();
    
    
    sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
        menuPath: ["Select","All"],
        targetValue: "Enable",
    });
    
    
    var view = sf.ui.proTools.mainWindow.clipListView;
    view.childrenByRole("AXRow").first.children.allItems[1].children.first.popupMenuSelect({
       isRightClick: true,
        menuPath: ['Object Select in Edit Window'],
    });
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    Solved in post #6, click to view
    • 45 replies

    There are 45 replies. Estimated reading time: 48 minutes

    1. samuel henriques @samuel_henriques
        2020-09-22 20:37:17.535Z

        I made a few changes, don't know why still get error if I clear clip gain and repeat the script, but if I just repeat it, it goes just fine.

        Managed to make it continue if the clip name doesn't exist and an alert in the end of the process.

        If anyone finds any coding mistakes, please share so I can make this better.

        Thank you so much!

        sf.ui.proTools.appActivateMainWindow();
        
        sf.ui.proTools.menuClick({
            menuPath: ["View","Other Displays","Clip List"],
            targetValue: "Enable",
        });
        
        
        
        ///// copy paste the next 5 lines to add more clips to be processed
        {
         var clipname = "CLIPNAME HERE"
         var clipgain = 1    ///// 1 for one dB up, if clip gain is set to increments on 1 dB
         clipselectandgain();
        }
        /////
        
        
        
        
        
        
        
        /////alert when process is finished
        var clearfindel = sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
            menuPath: ["Clear Find"],
        });
        if (!(clearfindel.exists && clearfindel.isEnabled)) {
           
        alert("DONE!")
        }
        
        
        
        
        function clipselectandgain(){
        
        
        sf.keyboard.press({
            keys: "cmd+shift+f",
        });
        sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.elementWaitFor({
            waitType: "Appear",
        });
        sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.checkBoxes.whoseDescription.is('').first.checkboxSet({
            targetValue: "Enable",
        });
        sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({
            value: clipname,
        });
        sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.buttons.whoseTitle.is('OK').first.elementClick();
        
        selectclipsoncliplist();
        
        //////GO CLIP GAIN
        sf.keyboard.press({
            keys: "ctrl+shift+up",
            repetitions: clipgain,
            fast: true,
        });
        sf.keyboard.press({
            keys: "cmd+shift+d",
        });
        }
        ///////////
        
        
        
        
        
        
        function selectclipsoncliplist(){
        
        sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
            menuPath: ["Select","All"],
            targetValue: "Enable",
        });
        
        var view = sf.ui.proTools.mainWindow.clipListView;
        view.childrenByRole("AXRow").first.children.allItems[1].children.first.popupMenuSelect({
           isRightClick: true,
            menuPath: ['Object Select in Edit Window'],
            onError: "Continue",
        });
             
        }
        
        
        
        
        
        
        
        1. Kitch Membery @Kitch2020-09-23 03:12:21.484Z

          Hi Sam,

          I did a bit of a rewrite to make the code a little clearer. I think it does what you want. Let me know if not.

          I added the error checking (if filtered clips do not exist) but made it log the error rather than alert it.

          I also made it so you can adjust the clip gain by a negative value as well as a positive value.

          function clipSelect(clipName) {
              const win = sf.ui.proTools.windows.whoseTitle.is('Find Clips').first;
          
              findClip();
          
              win.elementWaitFor({ waitType: "Appear", });
          
              win.checkBoxes.whoseTitle.is('By name').first.checkboxSet({ targetValue: "Enable" });
          
              win.textFields.first.elementSetTextFieldWithAreaValue({
                  value: clipName,
              });
          
              win.buttons.whoseTitle.is('OK').first.elementClick();
          
              win.elementWaitFor({ waitType: "Disappear", });
          
              selectClipsInClipList(clipName);
          }
          
          function adjustClipGain(gain) {
              if (gain !== 0) {
                  if (gain > 0) {
                      sf.keyboard.press({
                          keys: "ctrl+shift+up",
                          repetitions: gain,
                          fast: true,
                      });
                  } else {
                      sf.keyboard.press({
                          keys: "ctrl+shift+down",
                          repetitions: gain,
                          fast: true,
                      });
                  }
              }
          }
          
          function clearFindClip() {
              sf.keyboard.press({
                  keys: "cmd+shift+d",
              });
          }
          
          function findClip() {
              sf.keyboard.press({
                  keys: "cmd+shift+f",
              });
          }
          
          function selectClipsInClipList(clipName) {
              sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                  menuPath: ["Select", "All"],
                  targetValue: "Enable",
              });
          
              const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first;
          
              if (!row.children.allItems[1].children.first.exists) {
                  clearFindClip();
                  throw `No clip including the string ${clipName} exists.`;
              }
          
              row.children.allItems[1].children.first.popupMenuSelect({
                  isRightClick: true,
                  menuPath: ['Object Select in Edit Window'],
              });
          }
          
          function main() {
              const clipName = "ENTER CLIP NAME HERE"
              const clipGain = 1;    ///// 1 for one dB up, if clip gain is set to increments on 1 dB
          
              sf.ui.proTools.appActivateMainWindow();
          
              sf.ui.proTools.menuClick({
                  menuPath: ["View", "Other Displays", "Clip List"],
                  targetValue: "Enable",
              });
          
              clearFindClip();
          
              clipSelect(clipName);
          
              adjustClipGain(clipGain);
          
              clearFindClip();
          }
          
          main();
          

          Hope that helps!
          Rock on

          1. samuel henriques @samuel_henriques
              2020-09-23 07:49:28.377Z

              Hey Kitch,
              Thank you, it looks great and works.
              Now, I need an easy way to add more clip names and gain depending on the project. From what i read here, would I have to repeat the hole main() function with different names ?

              Also its nice to have a warning if the clip name doesn't exist but I would like it to continue. For example if I have 10 clip names to run on script, if the 5th doesn't exist, it could warn but keep going.

              Thank you, you rock!

              1. samuel henriques @samuel_henriques
                  2020-09-23 13:52:25.324Z

                  I made this to make it a list, is it stupid this way?
                  It's working but the last two are really slow getting gain up, weird.

                  function main() {
                  
                      
                      const clipName = (clipnamebulklist)
                      const clipGain = (clipgainbulklist);    
                  
                      
                  
                      sf.ui.proTools.appActivateMainWindow();
                  
                      sf.ui.proTools.menuClick({
                          menuPath: ["View", "Other Displays", "Clip List"],
                          targetValue: "Enable",
                      });
                  
                      clearFindClip();
                  
                      clipSelect(clipName);
                  
                      adjustClipGain(clipGain);
                  
                      clearFindClip();
                      
                  }
                  
                  
                  
                  
                   {
                   var clipnamebulklist = "Return Rob_05"
                   var clipgainbulklist = 12
                  main();
                  
                  }
                  /////
                  {
                  var clipnamebulklist = "SFX Unlock 1 REV"
                  var clipgainbulklist = 16
                  main();
                  
                  }
                  ////
                  {
                  var clipnamebulklist = "ANSWER REVEAL"
                  var clipgainbulklist = 2
                  main();
                  
                  }
                  ////
                  {
                  var clipnamebulklist = "Start Position_01"
                  var clipgainbulklist = 12
                  main();
                  
                  }
                  ////
                  {
                  var clipnamebulklist = "25 FREE Cinematic Transition Sound Effects"
                  var clipgainbulklist = 15
                  main();
                  
                  }
                  ///
                  {
                  var clipnamebulklist = "MS Battle of the Brains FX"
                  var clipgain = 15
                  main();
                  
                  }
                  ////
                  {
                  var clipnamebulklist = "SFX 30 sec Bell"
                  var clipgainbulklist = 6
                  main();
                  
                  }
                  ////
                  
                  
                  1. Kitch Membery @Kitch2020-09-23 23:21:33.356Z

                    Hey Sam :-)

                    That is not stupid at all. You have the right concept... I'm not sure why your script would slow down at the end though.

                    It may be better to do it by using a "forEach" array method on an array of objects (in this case "clipsArray".

                    Something like this should do the trick;

                    const clipsArray = [
                        { clip: 'Return Rob_05', gain: 12 },
                        { clip: 'SFX Unlock 1 REV', gain: 16 },
                        { clip: 'ANSWER REVEAL', gain: 2 },
                        { clip: 'Start Position_01', gain: 12 },
                        { clip: '25 FREE Cinematic Transition Sound Effects', gain: 15 },
                        { clip: 'MS Battle of the Brains FX', gain: 15 },
                        { clip: 'SFX 30 sec Bell', gain: 6 },
                    ];
                    
                    function clipSelect(clipName) {
                        const win = sf.ui.proTools.windows.whoseTitle.is('Find Clips').first;
                    
                        findClip();
                    
                        win.elementWaitFor({ waitType: "Appear", });
                    
                        win.checkBoxes.whoseTitle.is('By name').first.checkboxSet({ targetValue: "Enable" });
                    
                        win.textFields.first.elementSetTextFieldWithAreaValue({
                            value: clipName,
                        });
                    
                        win.buttons.whoseTitle.is('OK').first.elementClick();
                    
                        win.elementWaitFor({ waitType: "Disappear", });
                    
                        selectClipsInClipList(clipName);
                    }
                    
                    function adjustClipGain(gain) {
                        if (gain <= 0) {
                            gain = gain * -1;
                        }
                    
                        if (gain !== 0) {
                            if (gain > 0) {
                                sf.keyboard.press({
                                    keys: "ctrl+shift+up",
                                    repetitions: gain,
                                    fast: true,
                                });
                            } else {
                                sf.keyboard.press({
                                    keys: "ctrl+shift+down",
                                    repetitions: gain,
                                    fast: true,
                                });
                            }
                        }
                    }
                    
                    function clearFindClip() {
                        sf.keyboard.press({
                            keys: "cmd+shift+d",
                        });
                    }
                    
                    function findClip() {
                        sf.keyboard.press({
                            keys: "cmd+shift+f",
                        });
                    }
                    
                    function deselectClip() {
                        sf.keyboard.press({
                            keys: "down",
                        });
                    }
                    
                    function selectClipsInClipList(clipName) {
                        sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                            menuPath: ["Select", "All"],
                            targetValue: "Enable",
                        });
                    
                        const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first;
                    
                        if (!row.children.allItems[1].children.first.exists) {
                            clearFindClip();
                            log(`No clip including the string ${clipName} exists.`);
                        }
                    
                        row.children.allItems[1].children.first.popupMenuSelect({
                            isRightClick: true,
                            menuPath: ['Object Select in Edit Window'],
                            onError: "Continue",
                        });
                    }
                    
                    function doAdjustment(clipsArray) {
                        let { clip, gain } = clipsArray;
                    
                        clipSelect(clip);
                    
                        adjustClipGain(gain);
                    
                        clearFindClip();
                    
                        deselectClip();
                    }
                    
                    function main() {
                        sf.ui.proTools.appActivateMainWindow();
                    
                        sf.ui.proTools.menuClick({
                            menuPath: ["View", "Other Displays", "Clip List"],
                            targetValue: "Enable",
                        });
                    
                        deselectClip();
                    
                        clearFindClip();
                    
                        clipsArray.forEach(doAdjustment);
                    }
                    
                    main();
                    

                    I also noticed a couple of bugs (from my previous script) that I have addressed.

                    Rock on!

                    ReplySolution
                    1. samuel henriques @samuel_henriques
                        2020-09-24 07:54:07.374Z

                        Cool Kitch,
                        This looks like it. Should receive a new episode to really test this by the end of week.
                        Thank you so much!

                        1. Kitch Membery @Kitch2020-09-24 07:55:13.729Z

                          My pleasure mate. :-)

                          1. samuel henriques @samuel_henriques
                              2020-09-26 09:59:40.139Z
                              1. Kitch Membery @Kitch2020-09-26 16:19:11.520Z

                                Nice!!!! :-)

                                1. Nick Norton @notNickNorton
                                    2023-05-03 18:59:47.724Z

                                    Hey! I am trying to use this, and when I put a negative value in for my clip gain, it is increasing it by that value rather than decreasing. Any ideas?

                                    1. Kitch Membery @Kitch2023-05-03 20:09:13.676Z

                                      Ahh yes... It looks like my code has a bug.

                                      Replace the adjustClipGain function with the one below and that should do the trick

                                      function adjustClipGain(adjustmentValue) {
                                          log(adjustmentValue)
                                      
                                          let repetitions = adjustmentValue <= 0
                                              ? adjustmentValue * -1
                                              : adjustmentValue;
                                      
                                          if (adjustmentValue > 0) {
                                              sf.keyboard.press({
                                                  keys: "ctrl+shift+up",
                                                  repetitions,
                                                  fast: true,
                                              });
                                          } else if (adjustmentValue < 0) {
                                              sf.keyboard.press({
                                                  keys: "ctrl+shift+down",
                                                  repetitions,
                                                  fast: true,
                                              });
                                          }
                                      }
                                      
                                      1. LLuca Joass @Luca_Joass
                                          2023-07-18 23:33:40.831Z

                                          Firstly, thanks to everyone for the amazing work with this script. It's gonna be a huge time saver.
                                          On that note, for some reason, when I run the command, it only gets through the first two lines in my clips array, then stops. The log had this to say about it:

                                          19.07.2023 11:15:50.37 <info> [Backend]: Logging error in action (01) WaitForPopupMenuAction: Popup window was not found after waiting 2000 ms
                                          Logging error in action (01) OpenPopupMenuFromElementAction: Popup menu was not found
                                          Logging error in action (01) PopupMenuSelectAction: Could not open popup menu
                                          
                                          19.07.2023 11:15:50.38 <info> [Backend]: !! Command Error: TEST 3 [user:default:clk8rc9x20000k310k7e4fyqb]:
                                          Could not open popup menu (TEST 3: Line 91)
                                              Popup menu was not found
                                              Popup window was not found after waiting 2000 ms
                                          

                                          The notification window tells me it stops in line 2 of this bit:

                                          function selectClipsInClipList(clipName) {
                                              sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                                                  menuPath: ["Select", "All"],
                                                  targetValue: "Enable",
                                              });
                                          
                                              const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first;
                                          
                                              if (!row.children.allItems[1].children.first.exists) {
                                                  clearFindClip();
                                                  log(`No clip including the string ${clipName} exists.`);
                                              }
                                          
                                              row.children.allItems[1].children.first.popupMenuSelect({
                                                  isRightClick: true,
                                                  menuPath: ['Object Select in Edit Window'],
                                                  onError: "Continue",
                                              });
                                          }
                                          

                                          When the first 2 lines in the clips array are bypassed, it's happy to complete the third, but still stops after only doing 2, so I don't think it's a problem with my clip names.

                                          Forgive me, I have absolutely no JavaScript experience so this is a huge learning curve for me. Any suggestions would be greatly appreciated.

                                          Thanks,
                                          Luca

                                          1. samuel henriques @samuel_henriques
                                              2023-07-23 12:37:27.198Z

                                              Hello Lucas,
                                              This could indicate the popup button is not visible to SF.
                                              It it's hidden behind any window or plugin or something.

                                              1. LLuca Joass @Luca_Joass
                                                  2023-07-24 22:21:48.716Z

                                                  Thanks for the reply Samuel!

                                                  I just gave this a go but no luck. I tried hiding all floating windows, hiding all other windows, and pulling both my mix and edit windows to one screen but it's still having the same problem. It's just odd to me that it works on the first 2 but then stops.

                                                  I'm using MacOS Ventura 13.3.1 and ProTools 2022.12 if it's possible there's been a reshuffle of naming convention in recent updates.

                                                  Thanks for the help.

                                                  1. samuel henriques @samuel_henriques
                                                      2023-07-24 22:40:21.545Z

                                                      could you post your gain list, and could you make a screen recording of it failing? I might see some clue for the problem

                                                • In reply toKitch:
                                                  AAsi Tal @Asi_Tal
                                                    2024-08-15 15:55:48.590Z

                                                    Hey Kitch.. about clip gain. is there any way to analyze the clip gain, to adjust all clips to -6 db and then compensate the opposite with the track fader?
                                                    I'll try to be more clear.
                                                    Sometimes to get a project to mix and the clips are too low in gain (around -20db)
                                                    I'm looking to write a script / macro that could analyze the gain of a clip (lets say) -20db adjust it to -6db (so it turned up by 14db) and the take the track fader down with 14db ? that way I could preserve the current song balance.
                                                    for real, It would change my world.
                                                    @kitch

                                                    1. Kitch Membery @Kitch2024-08-15 18:26:24.484Z

                                                      Hi @Asi_Tal,

                                                      I'm unaware of a way to programmatically do this.

                                                      It may be best to start a new thread in the "How to" section of the forum, where the SoundFlow Community may be able to provide a solution. :-)

                                                      1. In reply toAsi_Tal:
                                                        Nick Norton @notNickNorton
                                                          2024-08-15 19:18:19.728Z

                                                          A bit of an aside, but I was unaware of the plugin Defaulter until recently, and it's amazing for getting clip gain to a solid starting level (particularly dialogue). A couple solid Soundflow scripts for it already too.

                                                          https://quietart.co.nz/defaulter/

                                                          1. Kitch Membery @Kitch2024-08-15 19:21:24.277Z

                                                            Nick, You read my mind! I was about to share that. :-)

                                  • L
                                    Luca Joass @Luca_Joass
                                      2023-07-24 23:13:38.956Z

                                      Here's the clip gain list...

                                      const clipsArray = [
                                          { clip: 'BB FLARE CLEAN SFX', gain: 4 },
                                          { clip: 'BB SPEC ROUND SFX', gain: 2 },
                                          { clip: 'SUBJECT ROUNDS SFX 2021', gain: 2 },
                                          { clip: 'BB COUNT DOWN SFX 2020', gain: 8 },
                                          { clip: 'Tk_Placeholder Sting', gain: 3 },
                                          { clip: 'LEADERBOARD SFX 2021', gain: 6 },
                                          { clip: 'BB SCOREBOARD NAME SFX 2020', gain: 6 },
                                          { clip: 'Tk_Signature Cue', gain: 6 },
                                          { clip: 'BB New Sting 1.8sec', gain: 9 },
                                          { clip: 'BB NEW SELECT SFX 2021', gain: 4 },
                                          { clip: 'END PART 1&3 STING', gain: 6 },
                                          { clip: 'TOP PART 2 STING', gain: 6 },
                                          { clip: 'TOP PART 3 STING', gain: 6 },
                                          { clip: 'VOTE LONGER', gain: 4 },
                                          { clip: 'OUT OF TIME FINAL', gain: 6 },
                                          { clip: 'BB RACE START SFX 2020', gain: -10 },
                                          { clip: 'BB Amygdala MAIN BOARD', gain: 2 },
                                          { clip: 'Tk_Race_ The Brain Buster', gain: 6 },
                                          { clip: 'Tk_Intro Player_Elimination', gain: 2 },
                                          { clip: 'Tk_Game Blueprinter 01', gain: 8 },
                                          { clip: 'Tk_Game Blueprinter_02', gain: 8 },
                                          { clip: 'Tk_Mikey theme', gain: 2 },
                                          { clip: 'Tk_Game Identifier', gain: 2 },
                                          { clip: 'Tk_Leaderboard Sting_01', gain: 4 },
                                          { clip: 'MegaMemory 2021v3', gain: 6 },
                                          { clip: 'Tk_Heartbeat', gain: 4 },
                                      ];
                                      

                                      And here's a link to a screen recording:
                                      https://we.tl/t-i1KBqtuggT

                                      Note at the start of the recording, I manually clear the previous find because that's what it gets to when it stops running the script.

                                      Let me know if this gives you a better sense of what's going on.

                                      Appreciate the help!

                                      (P.S. where it says line 91, it's referring to this one:)

                                         sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                                      
                                      1. samuel henriques @samuel_henriques
                                          2023-07-24 23:50:30.908Z

                                          Could you try to resize the edit window so the popup button won't be under the log when it opens?

                                          1. LLuca Joass @Luca_Joass
                                              2023-07-24 23:57:48.273Z

                                              Oh my goodness, that worked!

                                              Thank you so much. I should've noticed that.

                                              You're a legend Samuel

                                              1. samuel henriques @samuel_henriques
                                                  2023-07-25 00:11:54.260Z

                                                  Perfect. If you want to remove the logging, find a line starting with log(, on the script and add // before it. It will disable the line. Will look like //log( and change to green

                                            • Nick Norton @notNickNorton
                                                2024-12-06 18:11:46.213Z

                                                Hey @Kitch !

                                                Been a while. I started a show that could use this, and it's now returning an error regarding wait time, in this section of the code:

                                                function clipSelect(clipName) {
                                                    const win = sf.ui.proTools.windows.whoseTitle.is('Find Clips').first;
                                                
                                                    findClip();
                                                
                                                    win.elementWaitFor({ waitType: "Appear", });
                                                
                                                    win.checkBoxes.whoseTitle.is('By name').first.checkboxSet({ targetValue: "Enable" });
                                                
                                                    win.textFields.first.elementSetTextFieldWithAreaValue({
                                                        value: clipName,
                                                    });
                                                
                                                    win.buttons.whoseTitle.is('OK').first.elementClick();
                                                
                                                    win.elementWaitFor({ waitType: "Disappear", });
                                                
                                                    selectClipsInClipList(clipName);
                                                }
                                                

                                                The error message in the log is:

                                                Element was not found or removed after waiting 2000 ms (BMP 2024 Clip Gain by Clip Name : Line 50)
                                                

                                                Thoughts? I figured it might have something to do with the changes in the clip window in in PT...

                                                1. Kitch Membery @Kitch2024-12-06 19:02:19.474Z

                                                  Hi @notNickNorton,

                                                  Quite possibly.

                                                  Can you provide the whole script... It looks like there are some functions being called that are not present in what you've provided, and I'm unable to identify the code on line 50 that is throwing the error.

                                                  Also, could you refresh my memory, what is the workflow you're trying to achieve here?

                                                  Thanks in advance. :-)

                                                  1. Nick Norton @notNickNorton
                                                      2024-12-06 20:06:00.689Z

                                                      Yup, right here! The script is meant to take a list of clips and adjust their gain according to their filenames, since my picture editors always use the same FX (in the same way).

                                                      const clipsArray = [ 
                                                          { clip: ' Splash Or Dive Into Water', gain: -11.5 *2 },
                                                          { clip: ' Cymbal Riser ', gain: -12 *2 },
                                                          { clip: 'RisingCymbalRev1erse1', gain: -10 *2 },
                                                          { clip: 'WHOOSH HIT.Copy.01', gain: 4 *2 },
                                                          { clip: 'big hit.Copy.01', gain: -5 *2 },
                                                          { clip: 'IRL_Incursion_Stingend2', gain: -6 *2 },
                                                          { clip: '27 Wind Whoosh A', gain: -3.5 *2 },
                                                          { clip: '07 Unfamiliar Hit', gain: -9.5 *2 },
                                                          { clip: 'KAP BW BigBoomer1', gain: -3.5 *2 },
                                                          { clip: 'KAP GroundBang.new', gain: -3.5 *2 }  ,
                                                          { clip: 'SFX_RisingCymbal1.wav.', gain: -7 *2 }  ,
                                                          { clip: '35 Cymbal Washes II', gain: -13 *2 }  ,
                                                          { clip: 'KAP Cym Strike.wav', gain: -2.5 *2 }  , 
                                                          { clip: 'SFX_RisingCymbalReverse1.wav', gain: -15 *2 } ,   
                                                          { clip: '39 Intense Riser F', gain: -9 *2 } ,
                                                          { clip: 'trailer hits sound effects.new', gain: 3.5 *2 } ,    
                                                          { clip: 'SFX_Mammoth1.wav.new', gain: 2 *2 }  ,
                                                          { clip: 'SFX_Mammoth9.wav.new', gain: 2 *2 }  ,
                                                          { clip: '07 Soft Whoosh.wav.new', gain: 4 *2 }  ,
                                                          { clip: '06 Bassy Hit.wav.new', gain: 4 *2 }  ,
                                                          { clip: '06 Bassy Hit.wav.new', gain: 4 *2 } ,
                                                          { clip: 'KAP DD PowerHit', gain: -3.5 *2 }, 
                                                          { clip: 'WHOOSH JET HIT.new', gain: 13 *2 },
                                                          { clip: 'Sword Whoosh.aif.new.02', gain: 6 *2 },
                                                          { clip: '48 Tension Riser A.wa', gain: -6.5 *2 } ,
                                                          { clip: 'SWELL CYMBAL.new.07', gain: 5 *2 },
                                                          { clip: '14 Hard Whoosh A.wav.new.02', gain: 6 *2 },
                                                          { clip: 'Alarm_Buzzer_ODY-0299', gain: 3 *2 }
                                                      
                                                          
                                                          
                                                      ];
                                                      
                                                      
                                                      function clipSelect(clipName) {
                                                          const win = sf.ui.proTools.windows.whoseTitle.is('Find Clips').first;
                                                      
                                                          findClip();
                                                      
                                                          win.elementWaitFor({ waitType: "Appear", });
                                                      
                                                          win.checkBoxes.whoseTitle.is('By name').first.checkboxSet({ targetValue: "Enable" });
                                                      
                                                          win.textFields.first.elementSetTextFieldWithAreaValue({
                                                              value: clipName,
                                                          });
                                                      
                                                          win.buttons.whoseTitle.is('OK').first.elementClick();
                                                      
                                                          win.elementWaitFor({ waitType: "Disappear", });
                                                      
                                                          selectClipsInClipList(clipName);
                                                      }
                                                      
                                                      
                                                      function adjustClipGain(adjustmentValue) {
                                                          log(adjustmentValue)
                                                      
                                                          let repetitions = adjustmentValue <= 0
                                                              ? adjustmentValue * -1
                                                              : adjustmentValue;
                                                      
                                                          if (adjustmentValue > 0) {
                                                              sf.keyboard.press({
                                                                  keys: "ctrl+shift+up",
                                                                  repetitions,
                                                                  fast: true,
                                                              });
                                                          } else if (adjustmentValue < 0) {
                                                              sf.keyboard.press({
                                                                  keys: "ctrl+shift+down",
                                                                  repetitions,
                                                                  fast: true,
                                                              });
                                                          }
                                                      }
                                                      
                                                      function clearFindClip() {
                                                          sf.keyboard.press({
                                                              keys: "cmd+shift+d",
                                                          });
                                                      }
                                                      
                                                      function findClip() {
                                                          sf.keyboard.press({
                                                              keys: "cmd+shift+f",
                                                          });
                                                      }
                                                      
                                                      function deselectClip() {
                                                          sf.keyboard.press({
                                                              keys: "down",
                                                          });
                                                      }
                                                      
                                                      function selectClipsInClipList(clipName) {
                                                          sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                                                              menuPath: ["Select", "All"],
                                                              targetValue: "Enable",
                                                          });
                                                      
                                                          const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first;
                                                      
                                                          if (!row.children.allItems[1].children.first.exists) {
                                                              clearFindClip();
                                                              log(`No clip including the string ${clipName} exists.`);
                                                          }
                                                      
                                                          row.children.allItems[1].children.first.popupMenuSelect({
                                                              isRightClick: true,
                                                              menuPath: ['Object Select in Edit Window'],
                                                              onError: "Continue",
                                                          });
                                                      }
                                                      
                                                      function doAdjustment(clipsArray) {
                                                          let { clip, gain } = clipsArray;
                                                      
                                                          clipSelect(clip);
                                                      
                                                          adjustClipGain(gain);
                                                      
                                                          clearFindClip();
                                                      
                                                          deselectClip();
                                                      }
                                                      
                                                      function main() {
                                                          sf.ui.proTools.appActivateMainWindow();
                                                      
                                                          sf.ui.proTools.menuClick({
                                                              menuPath: ["View", "Other Displays", "Clip List"],
                                                              targetValue: "Enable",
                                                          });
                                                      
                                                          deselectClip();
                                                      
                                                          clearFindClip();
                                                      
                                                          clipsArray.forEach(doAdjustment);
                                                      }
                                                      
                                                      main();
                                                      
                                                      1. Kitch Membery @Kitch2024-12-06 22:11:36.987Z

                                                        Ok @notNickNorton,

                                                        Here is a suped-up version for the new clips list filter in Pro Tools 2024.10.

                                                        const clipsArray = [
                                                            { clipName: ' Splash Or Dive Into Water', gainAdjustment: -11.5 },
                                                            { clipName: ' Cymbal Riser ', gainAdjustment: -12 },
                                                            { clipName: 'RisingCymbalRev1erse1', gainAdjustment: -10 },
                                                            { clipName: 'WHOOSH HIT.Copy.01', gainAdjustment: 4 },
                                                            { clipName: 'big hit.Copy.01', gainAdjustment: -5 },
                                                            { clipName: 'IRL_Incursion_Stingend2', gainAdjustment: -6 },
                                                            { clipName: '27 Wind Whoosh A', gainAdjustment: -3.5 },
                                                            { clipName: '07 Unfamiliar Hit', gainAdjustment: -9.5 },
                                                            { clipName: 'KAP BW BigBoomer1', gainAdjustment: -3.5 },
                                                            { clipName: 'KAP GroundBang.new', gainAdjustment: -3.5 },
                                                            { clipName: 'SFX_RisingCymbal1.wav.', gainAdjustment: -7 },
                                                            { clipName: '35 Cymbal Washes II', gainAdjustment: -13 },
                                                            { clipName: 'KAP Cym Strike.wav', gainAdjustment: -2.5 },
                                                            { clipName: 'SFX_RisingCymbalReverse1.wav', gainAdjustment: -15 },
                                                            { clipName: '39 Intense Riser F', gainAdjustment: -9 },
                                                            { clipName: 'trailer hits sound effects.new', gainAdjustment: 3.5 },
                                                            { clipName: 'SFX_Mammoth1.wav.new', gainAdjustment: 2 },
                                                            { clipName: 'SFX_Mammoth9.wav.new', gainAdjustment: 2 },
                                                            { clipName: '07 Soft Whoosh.wav.new', gainAdjustment: 4 },
                                                            { clipName: '06 Bassy Hit.wav.new', gainAdjustment: 4 },
                                                            { clipName: '06 Bassy Hit.wav.new', gainAdjustment: 4 },
                                                            { clipName: 'KAP DD PowerHit', gainAdjustment: -3.5 },
                                                            { clipName: 'WHOOSH JET HIT.new', gainAdjustment: 13 },
                                                            { clipName: 'Sword Whoosh.aif.new.02', gainAdjustment: 6 },
                                                            { clipName: '48 Tension Riser A.wa', gainAdjustment: -6.5 },
                                                            { clipName: 'SWELL CYMBAL.new.07', gainAdjustment: 5 },
                                                            { clipName: '14 Hard Whoosh A.wav.new.02', gainAdjustment: 6 },
                                                            { clipName: 'Alarm_Buzzer_ODY-0299', gainAdjustment: 3 }
                                                        ];
                                                        
                                                        // This depends on the value set in "Pro Tools"=>"Settings"=>"Edit"=>"Clip Gain Nudge Value".
                                                        const clipGainMultiplier = 2;
                                                        
                                                        // Create a blank array of non existent clips.
                                                        const nonExistentClips = []
                                                        
                                                        function setClipListFilter(filterString) {
                                                            sf.ui.proTools.appActivateMainWindow();
                                                        
                                                            const clipListFilterTextField = sf.ui.proTools.mainWindow.textFields.find(
                                                                tf => tf.getString("AXRoleDescription") === "edit text"
                                                            );
                                                        
                                                            const clipsFilterPlate = sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Plate");
                                                            const clearClipsFilterButton = clipsFilterPlate.allItems.whoseValue.is("Clear Search Text").first;
                                                        
                                                            if (clearClipsFilterButton.exists) {
                                                                clearClipsFilterButton.elementClick();
                                                            }
                                                        
                                                            sf.ui.proTools.appActivate();
                                                        
                                                            clipListFilterTextField.elementSetTextFieldWithAreaValue({
                                                                value: filterString,
                                                                useMouseKeyboard: true
                                                            });
                                                        
                                                            sf.waitFor({
                                                                callback: () => clipListFilterTextField.value.invalidate().value === filterString,
                                                                timeout: 2000,
                                                            }, `Failed entering clip filter text: "${filterString}".`);
                                                        }
                                                        
                                                        function clearFindClip() {
                                                            const clipsFilterPlate = sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Plate");
                                                            const clearClipsFilterButton = clipsFilterPlate.allItems.whoseValue.is("Clear Search Text").first;
                                                        
                                                            if (clearClipsFilterButton.exists) {
                                                                clearClipsFilterButton.elementClick({}, `Failed clearing the Clips List filter text field.`);
                                                            }
                                                        }
                                                        
                                                        function adjustClipGain(adjustmentValue, multiplier) {
                                                            let repetitions = adjustmentValue <= 0
                                                                ? (adjustmentValue * multiplier) * -1
                                                                : (adjustmentValue * multiplier);
                                                        
                                                            if (adjustmentValue > 0) {
                                                                sf.keyboard.press({
                                                                    keys: "ctrl+shift+up",
                                                                    repetitions,
                                                                    fast: true,
                                                                });
                                                            } else if (adjustmentValue < 0) {
                                                                sf.keyboard.press({
                                                                    keys: "ctrl+shift+down",
                                                                    repetitions,
                                                                    fast: true,
                                                                });
                                                            }
                                                        }
                                                        
                                                        function deselectClip() {
                                                            let timelineSelectionStartTime = sf.app.proTools.getTimelineSelection().inTime;
                                                        
                                                            sf.app.proTools.setTimelineSelection({
                                                                inTime: timelineSelectionStartTime,
                                                                outTime: timelineSelectionStartTime
                                                            });
                                                        }
                                                        
                                                        function selectClipsInClipList(clipName) {
                                                            const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first;
                                                        
                                                            if (!row.children.allItems[1].children.first.exists) {
                                                                clearFindClip();
                                                        
                                                                nonExistentClips.push(clipName);
                                                        
                                                                return
                                                            }
                                                        
                                                            sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Show Options menu').first.popupMenuSelect({
                                                                menuPath: ["Select", "All"],
                                                                targetValue: "Enable",
                                                            });
                                                        
                                                            row.children.allItems[1].children.first.popupMenuSelect({
                                                                isRightClick: true,
                                                                menuPath: ['Object Select in Edit Window'],
                                                                onError: "Continue",
                                                            });
                                                        }
                                                        
                                                        function doAdjustment(clipsArray) {
                                                            let { clipName, gainAdjustment } = clipsArray;
                                                        
                                                            setClipListFilter(clipName)
                                                        
                                                            selectClipsInClipList(clipName);
                                                        
                                                            adjustClipGain(gainAdjustment, clipGainMultiplier);
                                                        
                                                            clearFindClip();
                                                        
                                                            deselectClip();
                                                        }
                                                        
                                                        function main() {
                                                            sf.ui.proTools.appActivateMainWindow();
                                                        
                                                            sf.ui.proTools.menuClick({
                                                                menuPath: ["View", "Other Displays", "Clip List"],
                                                                targetValue: "Enable",
                                                            });
                                                        
                                                            deselectClip();
                                                        
                                                            clearFindClip();
                                                        
                                                            clipsArray.forEach(doAdjustment);
                                                        
                                                            // Display a dialog with any clips that were not found in the session.
                                                            if (nonExistentClips.length > 0) {
                                                                sf.interaction.displayDialog({
                                                                    prompt: `No clip were found for the folowing clip names.\n\n${nonExistentClips.join("\n")}`,
                                                                });
                                                            }
                                                        }
                                                        
                                                        main();
                                                        

                                                        I've also made a bunch of changes to the script so that it no longer relies on keyboard simulation for various functions. (still needs them for clip gain though). Along with some other changes to improve the performance and stability.

                                                        I've removed the continuous logging that you had going on as it was causing issues with the clip filter plate, and have replaced it with a dialog at the end that shows the names of any clips that were not found.

                                                        I've given it minimal testing but let me know how it goes. :-)

                                                        1. Nick Norton @notNickNorton
                                                            2024-12-07 00:48:47.024Z

                                                            Wow, thank you! Works beautifully, except for one very important part: it doesn't seem to find any clips. Whatever I put in, even when I'm looking at it in the clips list, comes up empty. Perhaps it has to do with how it is searching strings? It would be best if it searched for strings within clip names, since the suffixes vary a lot.

                                                            1. Kitch Membery @Kitch2024-12-07 00:53:23.778Z

                                                              Hmmm... Can you make it filter, if you manually enter text into the search?

                                                              If not, you may need to check the filter to make sure you have everything you need showing.

                                                              1. Nick Norton @notNickNorton
                                                                  2024-12-09 05:27:57.742Z

                                                                  Just got a minute to test it, and yes, filtering seems to work right. The text pops into the clip filter field, and the clips appear in the list, but they don't get selected. I'm wondering if it needs some sort of wait before the select function...

                                                                  1. Kitch Membery @Kitch2024-12-09 19:05:07.133Z

                                                                    Thanks for clarifying @notNickNorton!

                                                                    Great that the filter is working... Looks like it may need Pro Tool's main window focused before selecting the clips.

                                                                    I'll take a look at it sometime today or tomorrow :-)

                                                                    1. In reply tonotNickNorton:
                                                                      Kitch Membery @Kitch2024-12-09 20:20:13.651Z

                                                                      Hi @notNickNorton

                                                                      Looking at the script again, I might need a screen recording from you, as I'm unable to make it fail on my system.

                                                                      1. Nick Norton @notNickNorton
                                                                          2024-12-20 16:49:41.210Z

                                                                          Alright, it's starting to look like something is off with SoundFlow overall on my end. It seems now that the script won't run at all. I tried putting it into a marco, and got this error:

                                                                          << Command: Bunim Murray sFX Automatic Clip Gain [user:ckzrx0vrg0001jm10vruv3r07:clku2h5k300023510929nxjtt]
                                                                          
                                                                          20.12.2024 08:46:50.92 <info> [EditorWindow:Renderer]: Active Focus Container:  commandsPage/MacroCommandDetails Line 33963 file:///Applications/SoundFlow.app/Contents/Helpers/SoundFlow.app/Contents/Resources/app.asar/dist/editor.js
                                                                          

                                                                          I just installed the newest version of SF and got the same thing. It seems noteworthy that a few days ago I was editing another macro and the changes didn't seem to be taking hold.

                                                                          Maybe this is for a new thread?

                                                                          1. Kitch Membery @Kitch2024-12-20 17:52:25.807Z

                                                                            Hi @notNickNorton,

                                                                            Can I get you to log a help/Issue request from the SoundFlow icon up by the clock for this?

                                                                            Be sure to provide as much information as possible.

                                                                            Thanks in advance.

                                                                            1. Nick Norton @notNickNorton
                                                                                2024-12-20 18:18:32.573Z

                                                                                On it, though I'm starting to think it might be a PT issue actually, as I'm having other troubles in the clips list. Will investigate and send an issue request if I still think it's SF!

                                                                                1. Kitch Membery @Kitch2024-12-20 18:20:49.825Z

                                                                                  Did you just recently update Pro Tools?

                                                                                  1. In reply tonotNickNorton:
                                                                                    Nick Norton @notNickNorton
                                                                                      2024-12-20 19:09:58.342Z

                                                                                      Before I do, is there a clip list setting or preference for something like "select clip in edit window" that I'm missing? That is what seems to be glitchy here.

                                                                                      1. Kitch Membery @Kitch2024-12-20 19:19:24.015Z

                                                                                        Hi @notNickNorton,

                                                                                        Did you just recently update Pro Tools?

                                                                                        In recent versions of Pro Tools, there was a change to the way the clip are filtered in the clips list. This may be what you're experiencing.

                                                                                        I covered a way to use the new filter field here...
                                                                                        Set &amp; Clear the "Clips List" filter text field in Pro Tools 2024.6+

                                                                                        1. Nick Norton @notNickNorton
                                                                                            2024-12-23 21:42:07.938Z

                                                                                            Alright, messing with it a bit and think that's indeed the issue—gonna keep playing with pasting that stuff in correctly. But I had an idea last night that might streamline this significantly:

                                                                                            Instead of running a huge library of clip names, what if it grabbed the name and gain of the currently highlighted clip and applied it to all with the same root name? Could even only apply it to clips further down the timeline, for making tweaks as you do your first pass.

                                                                                            1. Kitch Membery @Kitch2024-12-23 22:47:26.235Z

                                                                                              Yes, that could work for sure. Keep me updated on how you go with that approach! :-)

                                                                                              1. Nick Norton @notNickNorton
                                                                                                  2024-12-24 00:56:51.755Z2024-12-24 01:17:38.376Z

                                                                                                  Okay, I'm extremely close to having a working version of this that is way, way more effective than the original idea.

                                                                                                  One question I can't seem to find an answer for: is there a way to make this right click on "object select in edit window" on the clips list happen?

                                                                                                  That seems to be the only place this option exists in all of PT's menus. Been trying "mouse click relative to UI element" and having no luck.

                                                                                                  1. Kitch Membery @Kitch2024-12-24 18:51:53.348Z

                                                                                                    Hi Nick,

                                                                                                    You can do this with the popupMenuSelect method.

                                                                                                    const clipsList = sf.ui.proTools.mainWindow.clipListView;
                                                                                                    const rows = clipsList.children.whoseRole.is("AXColumn").whoseTitle.is("Name ").first.children.whoseRole.is("AXRow");
                                                                                                    const firstRow = rows.first;
                                                                                                    const cell = rows.first.children.whoseRole.is("AXCell");
                                                                                                    const cellText = cell.allItems[1].children.whoseRole.is("AXStaticText").first;
                                                                                                    
                                                                                                    cellText.popupMenuSelect({
                                                                                                        isRightClick: true,
                                                                                                        menuPath: ["Object Select in Edit Window"]
                                                                                                    });
                                                                                                    
                                                                                                    1. Nick Norton @notNickNorton
                                                                                                        2024-12-24 19:44:13.935Z

                                                                                                        IT WORKS!!!!

                                                                                                        I know key presses aren't the best way to do things, but it seems very stable so I'm happy!

                                                                                                        1. Kitch Membery @Kitch2024-12-24 20:23:42.435Z

                                                                                                          Hi @notNickNorton,

                                                                                                          Can you list what all these keyboard shortcuts are doing? I'll bet this could be done programmatically.

                                                                                                          1. Nick Norton @notNickNorton
                                                                                                              2024-12-26 22:43:09.101Z

                                                                                                              Sure. The first one, after rename, is setting the cursor to the beginning of the clip name and then selecting to the right and copying. It's going for the first three groups of characters, because a select all wasn't filtering correctly.

                                                                                                              Then it escapes that window and copies the clip gain. The next key press switches to the clip filter and pastes in the text, then after waiting for the search to be safe it escapes the filter field and selects all clips that have appeared.

                                                                                                              Then it's just the select and paste, which only pastes the clip gain.

                                                                                                              After using it for a couple of days, it's great, but it would be double great to only select objects ahead of the current timeline position instead of across the whole session, so it doesn't undo changes I've made earlier in the timeline if I accidentally run it twice. I added a clip color change at the very end to keep myself from doing that by.