No internet connection
  1. Home
  2. How to

Add Comment to selected tracks (Pro Tools)

By Matt Cahill @Matt_Cahill
    2023-01-17 16:53:57.133Z

    Hi again,

    trying my best to work things out before coming to you guys, but the learning curve is slow! haha
    I want to make it so that I can select a group of audio tracks and with a macro, add "KICKS" etc. to the comment, I have worked out just the simple add comment to track macro but a little lost on how to execute the idea!

    cheers

    • 8 replies
    1. O

      I messed around this with this script : Copy track name and paste to PT scribble strip...

      Was able to modify it so it asks for comments then fills in the selected tracks. It will replace whatever is there...

      function setComments() {
          sf.ui.proTools.appActivateMainWindow()
          sf.ui.proTools.invalidate()
      
          var commentToFill = sf.interaction.displayDialog({
              title: "Comment",
              prompt: "Enter Comments",
              defaultAnswer: ""
          }).text
      
          //Get selected Tracks
          const selectedTracks = sf.ui.proTools.selectedTrackHeaders
      
          //Scrool to view first track
          selectedTracks[0].trackScrollToView()
      
          // Open rename window
          selectedTracks[0].popupButtons.first.mouseClickElement({ clickCount: 2 })
      
          // Wait for rename window
          sf.ui.proTools.windows.whoseTitle.is(selectedTracks[0].popupButtons.first.value.invalidate().value).first.elementWaitFor();
      
          //Get the elements of text fields and buttons 
          const [trackName, comments] = sf.ui.proTools.focusedWindow.invalidate().textFields.map(x => x)
          const [ok, cncl, pr, next] = sf.ui.proTools.focusedWindow.buttons.map(x => x)
      
      
          // Loop all tracks
          for (let i = 0; i < selectedTracks.length; i++) {
      
              let newCommments = commentToFill
      
              // Set track name in Comments
              {
                  comments.elementSetTextFieldWithAreaValue({
                      value: newCommments
                  });
                  sf.wait({ intervalMs: 5 })
              };
      
              // If its the last track press ok, else press next
              if (i === selectedTracks.length - 1) {
                  ok.elementClick()
              } else {
                  next.elementClick()
              };
      
          };
      };
      
      setComments();
      
      1. Hides pesky floating windows and then puts them back now :

        function setComments() {
            sf.ui.proTools.appActivateMainWindow()
            sf.ui.proTools.invalidate()
        
            var commentToFill = sf.interaction.displayDialog({
                title: "Comment",
                prompt: "Enter Comments",
                defaultAnswer: ""
            }).text
        
            //Get selected Tracks
            const selectedTracks = sf.ui.proTools.selectedTrackHeaders
        
            //Scrool to view first track
            selectedTracks[0].trackScrollToView()
        
            // Open rename window
            selectedTracks[0].popupButtons.first.mouseClickElement({ clickCount: 2 })
        
            // Wait for rename window
            sf.ui.proTools.windows.whoseTitle.is(selectedTracks[0].popupButtons.first.value.invalidate().value).first.elementWaitFor();
        
            //Get the elements of text fields and buttons 
            const [trackName, comments] = sf.ui.proTools.focusedWindow.invalidate().textFields.map(x => x)
            const [ok, cncl, pr, next] = sf.ui.proTools.focusedWindow.buttons.map(x => x)
        
        
            // Loop all tracks
            for (let i = 0; i < selectedTracks.length; i++) {
        
                let newCommments = commentToFill
        
                // Set track name in Comments
                {
                    comments.elementSetTextFieldWithAreaValue({
                        value: newCommments
                    });
                    sf.wait({ intervalMs: 5 })
                };
        
                // If its the last track press ok, else press next
                if (i === selectedTracks.length - 1) {
                    ok.elementClick()
                } else {
                    next.elementClick()
                };
        
            };
        };
        
        function setupAndRestore(callback) {
            sf.ui.proTools.appActivateMainWindow();
        
            const videoWinowMenuItem = sf.ui.proTools.getMenuItem('Window', 'Video');
        
            const initialViews = {
                isVideoWinOpen: videoWinowMenuItem.getString('AXMenuItemMarkChar') === ('-') || videoWinowMenuItem.isMenuChecked,
                isFloatingWindowsEnabled: sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isMenuChecked,
            }
        
            const { isVideoWinOpen, isFloatingWindowsEnabled } = initialViews;
        
            if (isVideoWinOpen) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Video'], }); }
            if (!isFloatingWindowsEnabled) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'], }); }
        
            try {
        
                callback();
        
            } finally {
        
                const modifiedViews = {
                    isVideoWinOpen: (videoWinowMenuItem.getString('AXMenuItemMarkChar') === ('-') || videoWinowMenuItem.isMenuChecked) !== initialViews.isVideoWinOpen,
                    isFloatingWindowsEnabled: sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isMenuChecked !== initialViews.isFloatingWindowsEnabled,
                }
        
                const { isVideoWinOpen, isFloatingWindowsEnabled } = modifiedViews;
        
                if (isVideoWinOpen) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Video'], }); }
                if (isFloatingWindowsEnabled) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'], }); }
            }
        }
        
        function main() {
            setupAndRestore(() => {
        
                setComments();
        
            });
        }
        
        main();
        
        1. MMatt Cahill @Matt_Cahill
            2023-01-18 10:59:30.436Z

            Owen you absolute beast, this is perfect! thank you!!

            1. Nah, I'm just standing on the shoulders of giants. This is all @samuel_henriques I just modified his work.

              1. MMatt Cahill @Matt_Cahill
                  2023-01-19 11:50:00.922Z

                  Well it is very good! I have run into a problem though, when I select a load of tracks that are separated by an AUX, it doesn't pick up the spacing properly and just applies it to the same amount of tracks, to if the AUXs were not there, here is a quick screen record, I hope it explains!

                  1. Makes perfect sense. I've re-done it to account for this. It's not as snappy as @samuel_henriques original code this way, but it does only do the actual tracks selected.

                    As to your below issue I'm pretty sure you have something triggering your main deck when protools becomes active. My bud had a similar thing and tracked it down. Often when you setup soundflow it will default to include an activate protools main deck on focus trigger. Hunt around in your default package you may be able to find it. Look for a 'Show Protools Deck' macro trigger. That's what it was for him.

                    function setupAndRestore(callback) {
                        sf.ui.proTools.appActivateMainWindow();
                    
                        const videoWinowMenuItem = sf.ui.proTools.getMenuItem('Window', 'Video');
                    
                        const initialViews = {
                            isVideoWinOpen: videoWinowMenuItem.getString('AXMenuItemMarkChar') === ('-') || videoWinowMenuItem.isMenuChecked,
                            isFloatingWindowsEnabled: sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isMenuChecked,
                        }
                    
                        const { isVideoWinOpen, isFloatingWindowsEnabled } = initialViews;
                    
                        if (isVideoWinOpen) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Video'], }); }
                        if (!isFloatingWindowsEnabled) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'], }); }
                    
                        try {
                    
                            callback();
                    
                        } finally {
                    
                            const modifiedViews = {
                                isVideoWinOpen: (videoWinowMenuItem.getString('AXMenuItemMarkChar') === ('-') || videoWinowMenuItem.isMenuChecked) !== initialViews.isVideoWinOpen,
                                isFloatingWindowsEnabled: sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isMenuChecked !== initialViews.isFloatingWindowsEnabled,
                            }
                    
                            const { isVideoWinOpen, isFloatingWindowsEnabled } = modifiedViews;
                    
                            if (isVideoWinOpen) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Video'], }); }
                            if (isFloatingWindowsEnabled) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'], }); }
                        }
                    }
                    
                    function doForAllSelectedTracks(action) {
                        var originallySelectedTrackNames = sf.ui.proTools.selectedTrackNames;
                    
                        try {
                            sf.ui.proTools.selectedTrackHeaders.forEach(track => {
                                track.trackSelect();
                                action(track);
                            });
                        }
                        finally {
                            sf.ui.proTools.trackSelectByName({ names: originallySelectedTrackNames });
                        }
                    }
                    
                    function setComments() {
                        sf.ui.proTools.appActivateMainWindow()
                        sf.ui.proTools.invalidate()
                    
                        var commentToFill = sf.interaction.displayDialog({
                            title: "Comment",
                            prompt: "Enter Comments",
                            defaultAnswer: ""
                        }).text
                    
                        //Get selected Tracks
                        const selectedTracks = sf.ui.proTools.selectedTrackHeaders
                    
                        //Scrool to view first track
                        selectedTracks[0].trackScrollToView()
                    
                        function trackFunc(track) {
                    
                            sf.ui.proTools.selectedTrack.titleButton.mouseClickElement({ clickCount: 2 });
                    
                            // Wait for rename window
                            sf.ui.proTools.windows.first.children.whoseRole.is("AXStaticText").whoseValue.is("Comments:").first.elementWaitFor();
                    
                    
                            //Get the elements of text fields and buttons 
                            const [trackName, comments] = sf.ui.proTools.focusedWindow.invalidate().textFields.map(x => x)
                            const [ok, cncl, pr, next] = sf.ui.proTools.focusedWindow.buttons.map(x => x)
                    
                            let newCommments = commentToFill
                    
                            // Set track name in Comments
                    
                            comments.elementSetTextFieldWithAreaValue({
                                value: newCommments
                            });
                            sf.wait({ intervalMs: 5 })
                            ok.elementClick()
                    
                        }
                    
                        doForAllSelectedTracks(trackFunc);
                    
                    }
                    
                    
                    setupAndRestore(() => {
                    
                        setComments();
                    
                    });
                    
                    1. Jordan Pascual @Jordan_Pascual
                        2024-05-22 01:25:27.236Z

                        Hey Owen, ya wonderful human. Unfortunately, this current code is throwing an error at line 69 (teehee), and I believe this is because ProTools switched the way Line 66 works... I've tried it with this on Line 66 instead...

                        sf.ui.proTools.selectedTrack.trackOpenRenameDialog();
                        

                        Is that the best way to do this as of PT 2023.3.1 ?

                    2. MMatt Cahill @Matt_Cahill
                        2023-01-19 11:53:12.768Z

                        Also, I am implementing this code as part of a larger deck, that has a main Home screen. This code is a tool on a sub deck called "Bounce" just off the home screen, the problem is, once I have entered the label and it's been pasted, every time it kicks back to the home screen (as opposed to remaining on the current deck) and I have to go back into the "Bounce" screen to do it again, any ideas?