No internet connection
  1. Home
  2. How to

Loop Until Last Clip On Track is Detected

@Kitch How can I create a loop that places a marker at the beginning of each clip on a selected track and stops looping when the last clip on that track is detected. Better yet, I'd like to do this to only the timeline selection so if I had clips downstream that I didn't want included I could highlight an area on the track on which to perform the action, but still detecting the last clip in the selected area.

  • 10 replies

There are 10 replies. Estimated reading time: 11 minutes

  1. Kitch Membery @Kitch2020-10-27 00:28:29.771Z

    Thanks for posting this here Steve!

    Try this :-)

    function addMarker(oldSelectionEnd) {
        let clipStartTime = sf.ui.proTools.selectionGetInSamples().selectionStart;
    
        if (clipStartTime >= oldSelectionEnd) {
            throw "Done! :-)";
        } else {
            //Add Marker
            sf.keyboard.press({ keys: "numpad enter" });
    
            const win = sf.ui.proTools.windows.whoseTitle.is('New Memory Location').first;
    
            //Wait for New Memory Location Window
            win.elementWaitFor();
    
            //Click OK
            win.buttons.whoseTitle.is('OK').first.elementClick()
        }
    }
    
    sf.ui.proTools.appActivateMainWindow();
    
    const oldSelectionEnd = sf.ui.proTools.selectionGetInSamples().selectionEnd;
    
    sf.ui.proTools.clipDoForEachSelectedClip({ action: addMarker });
    
    1. You're a genius! Works perfectly. Two things, what if I wanted it to place one last marker at the end of the last clip? Also, I did get an error notification. When it reached the end of the last clip in the selection I get this:

      1. Here's the clips I was testing:

        1. In reply tosbiss:
          Kitch Membery @Kitch2020-10-27 18:47:10.066Z

          :-) Awesome...

          The error you are receiving is due to the fact that the end of your selection goes past the end of the last clip. If you only select from the start of a clip to the end of a clip the error will not be thrown.

          A hacky way of getting around the error would be to change the last line of code to;

          sf.ui.proTools.clipDoForEachSelectedClip({
              action: addMarker,
              onError: "Continue"
          });
          

          The better way would be to use a few if/else statement to determine if the user selection's end is actually at the end of the last selected clip. you can interigate the selection by using sf.ui.proTools.selectionGetInfo() and choose from the code hints;

          You could then use sf.ui.proTools.selectionGetInfo() in the same way to determine where to place the marker for the end of the last clip.

          If that's too much to take in let me know and when I get a chance I'll mock somthing up.
          Rock on, Steve!

          1. SSteve Bissinger @sbiss2020-10-28 20:26:56.339Z2020-10-28 20:37:00.918Z

            Thanks Kitch! I went for hacky, as is my way ;) It seems to work fine. Here's my final code including an opt-tab (to go to the end of the last clip) and add a marker for "END". I turned it into a template so I can mark "LOCATIONS", "SCENES", "CUTS", or sometimes I just use an "X".

            const {
                markerTitle,
            } = event.props
            
            function addMarker(oldSelectionEnd) {
                let clipStartTime = sf.ui.proTools.selectionGetInSamples().selectionStart;
            
                if (clipStartTime >= oldSelectionEnd) {
                    throw "Done! :-)";
                } else {
                    //Add Marker
                    sf.keyboard.press({ keys: "numpad enter" });
            
                    const win = sf.ui.proTools.windows.whoseTitle.is('New Memory Location').first;
            
                    //Wait for New Memory Location Window
                    win.elementWaitFor();
            
                    sf.keyboard.type({
                        text: markerTitle,
                    });
            
                    //Click OK
                    win.buttons.whoseTitle.is('OK').first.elementClick()
                }
            }
            
            sf.ui.proTools.appActivateMainWindow();
            
            const oldSelectionEnd = sf.ui.proTools.selectionGetInSamples().selectionEnd;
            
            sf.ui.proTools.clipDoForEachSelectedClip({
                action: addMarker,
                onError: "Continue"
            });
            
            //  ADD FINAL MARKER TO END OF LAST CLIP
            
            sf.keyboard.press({
                keys: "alt+tab",
            });
            
            sf.keyboard.press({ keys: "numpad enter" });
            
            const win = sf.ui.proTools.windows.whoseTitle.is('New Memory Location').first;
            
            //Wait for New Memory Location Window
            win.elementWaitFor();
            
            sf.keyboard.type({
                text: "END",
            });
            
            //Click OK
            win.buttons.whoseTitle.is('OK').first.elementClick()
            
            1. When I have some more time I'll try to implement your more sophisticated method of doing the same thing :)

              1. Kitch Membery @Kitch2020-10-28 20:45:23.966Z

                Noice!!!
                I may have a script somwhere that uses a for loop instead of the clipDoForEachSelectedClip to do somthing similar. If I find it I'll let you know :-)

                1. Kitch Membery @Kitch2020-11-02 03:01:30.444Z

                  Yo Steve!!

                  Here is the alternative, using a while loop instead of the doForEachSelectedClip();

                  It adds a "Selection Start" and "Selection End" and then Adds markers with incremented numbers in between.

                  function addMarker(markerName) {
                      //Add marker
                      sf.keyboard.press({ keys: "numpad enter" });
                  
                      const win = sf.ui.proTools.newMemoryLocationDialog;
                  
                      //Wait for New Memory Location window
                      win.elementWaitFor();
                  
                      //Add marker name
                      win.textFields.allItems[1].elementSetTextFieldWithAreaValue({ value: markerName });
                  
                      //Click OK
                      win.buttons.whoseTitle.is('OK').first.elementClick()
                  }
                  
                  function main() {
                      //Acitvate Pro Tools
                      sf.ui.proTools.appActivateMainWindow();
                  
                      //Invalidate Pro Tools Main Window
                      sf.ui.proTools.mainWindow.invalidate();
                  
                      //Get Selection
                      var originalSelection = sf.ui.proTools.selectionGet();
                  
                      //Down arrow to deselect
                      sf.keyboard.press({
                          keys: "down",
                      });
                  
                      //Add Selection Start Marker
                      addMarker('Selection Start');
                  
                      //Shift tab
                      sf.keyboard.press({
                          keys: "shift+tab",
                      });
                  
                      //Initialize clip count
                      var markerCount = 0;
                  
                      while (sf.ui.proTools.selectionGetInSamples().selectionEnd <= originalSelection.selectionEnd) {
                  
                          if (sf.ui.proTools.selectionGetInfo().hasFullClip) {
                  
                              if (markerCount > 0) {
                                  //Add Markers
                                  addMarker('Cut:' + markerCount);
                              }
                              //Increment Markers
                              markerCount++
                  
                              //Move to start of next clip
                              sf.keyboard.press({ keys: "tab", });
                          }
                          sf.keyboard.press({ keys: "shift+tab", });
                      }
                  
                      if (sf.ui.proTools.selectionGetInSamples().selectionEnd >= originalSelection.selectionEnd) {
                          //Move playhead to original selection end
                          sf.ui.proTools.selectionSet({
                              selectionEnd: originalSelection.selectionEnd,
                          });
                  
                          //Add Selection End marker
                          addMarker('Selection End');
                      }
                  
                      //Restore original selection
                      sf.ui.proTools.selectionSet({
                          selectionStart: originalSelection.selectionStart,
                          selectionLength: originalSelection.selectionLength,
                      });
                  
                      //Focus Selection
                      sf.keyboard.press({ keys: "alt + f", });
                  }
                  
                  //Change the Main Counter to Samples for the duration of the main function
                  sf.ui.proTools.mainCounterDoWithValue({
                      targetValue: 'Samples',
                      action: () => {
                          main();
                      }
                  });
                  
                  1. Hey Kitch,

                    Thanks! This has some cool features. I like that it incrementally numbers the memory location names. One thing I liked about the old script is that even if my selection started earlier than the clips, it put the first memory location at the beginning of the first clip. This new script puts it at the beginning of the selection. I have't been able to figure out how to fix that. I'm sure it's simple...

                    Also, for my workflow the memory location after "Start" is "Pop" (2 pop for film/tv), and the second to last location is "Tail Pop". I modified the script to add the "Pop" marker, and at the end of the script I added an Option-Tab to go back one clip to add the "Tail Pop" memory location. But this adds a memory location on top of an existing memory location. Is there a piece of code I can add to clear the memory location at the current selection point? That way I can clear the existing memory location and add the new "Tail Pop" memory location. Alternately is there a way to rename the memory location at the current selection point?

                    1. Kitch Membery @Kitch2020-11-02 20:24:35.228Z

                      Hi Steve, Will take a look at it when I get a chance :-)