No internet connection
  1. Home
  2. How to

Is there a way to tell how many clips exist in a pro tools selection?

By Dustin Harris @Dustin_Harris
    2020-12-09 17:16:52.867Z

    Hi! I'm refining a complicated script that works on a number of selected tracks via a clipDoForEachSelectedClip of the top track of the selection. I want to add a condition to the action function to return early if there is only one clip in the selection... is this possible?

    Thanks in advance! :)

    Solved in post #6, click to view
    • 16 replies

    There are 16 replies. Estimated reading time: 12 minutes

    1. I'm not sure how to count clips in a selection but this will count clips on a track (if you delete the line with the comment). As is, the script will stop counting if there is more than one clip.
      Hope this can get you started…

      sf.ui.proTools.transportEnsureCluster();
      function location() { return sf.ui.proTools.getCurrentTimecode().stringValue }
      sf.ui.proTools.mainWindow.groups.whoseTitle.is('Transport View Cluster').first.groups.whoseTitle.
          is('Normal Transport Buttons').first.buttons.whoseTitle.is('Return to Zero').first.elementClick();
      var lastLocation
      sf.keyboard.press({ keys: "ctrl+tab", });
      var clipCount = 0
      while (true) {
          sf.keyboard.press({ keys: "ctrl+tab", });
          if (lastLocation == location()) break
          if (sf.ui.proTools.selectionGetInfo().hasFullClip) {
              clipCount = clipCount + 1
               lastLocation = location()
              if (clipCount > 1) {log ("More Than One Full Clip Exists","");break;} //Delete this to count all clips in track
          }
      }
      log("ClipCount =  " + clipCount)
      
      1. Dustin Harris @Dustin_Harris
          2020-12-09 23:44:50.150Z

          Thanks Chris, but I’m counting vertically in my case. I have a clunky/slow work around, but it does a lot of work to accomplish it that needs to be undone. Am hoping there’s a cool selection property I’m unaware of. Maybe the number of selections in the clip list?

          1. That was my first thought (# of clips selected in clip list) but I don't know how to get that value.

            1. Dustin Harris @Dustin_Harris
                2020-12-09 23:56:16.624Z

                Hahaha me neither :)

              • In reply toDustin_Harris:

                Hey @Dustin_Harris ! This bit tells you how many clips are selected in the Clip List.

                let selectedClips = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first.children.whoseRole.is("AXRow").allItems.map(row => 
                    row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
                
                log(selectedClips.length);
                

                The thing is that the clip has to be fully selected in order for Pro Tools to consider it as selected.

                Hopefully this gets you closer to what you want to do!

                Reply5 LikesSolution
                1. Dustin Harris @Dustin_Harris
                    2020-12-10 01:18:51.365Z

                    Raphael this is superb and works perfectly for what I need! Thank you so much!

                    1. JJack Byrne @Jack_Byrne
                        2024-11-06 21:22:14.169Z

                        Hey Raphael,

                        Old thread, this seems to have stopped working. Fairly certain it's something with the latest version of PT, only thing that's changed. I'll check it in an old version when I can to see if it's just this session misbehaving as well, but I figured you might want a heads up. I'm on SF 5.8.3 if that affects things, not sure if that's the latest.

                        1. The clip list has been overhauled so this should do it.

                          let selectedClips = sf.ui.proTools.mainWindow.clipListView.children.whoseRole.is("AXRow").allItems.map(row => 
                              row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
                          
                          log(selectedClips.length);
                          
                          1. Essentially, instead of addressng the clip list with:

                            sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first
                            

                            You can now use this:

                            sf.ui.proTools.mainWindow.clipListView
                            
                            1. In reply toChris_Shaw:
                              JJack Byrne @Jack_Byrne
                                2024-11-22 12:05:38.550Z

                                Does this break compatibility with older versions? I tend to run a couple of PT versions at once, couple of edit workflows from older versions that I've not updated mainly

                                1. This should work with all versions.

                                  // Get PT version
                                  const ptVersion = sf.ui.proTools.appVersion.split('.')
                                      .map(Number)
                                      .slice(0, 2)
                                      .reduce((p, c, i) => p + Math.pow(100, 2 - i) * c, 0);
                                  
                                  // Get clip list element (depending on PT version)
                                  const clipList = ptVersion >= 241000 ?
                                      sf.ui.proTools.mainWindow.clipListView
                                      : sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first 
                                  
                                  // get selected clips in clip list
                                  let selectedClips = clipList.children.whoseRole.is("AXRow").allItems.map(row => 
                                      row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
                                  
                                  
                                  log (selectedClips.length)
                                  

                                  I'm assuming that the clip list element changed with PT 2024.10. If it changed with an earlier version just change the number in line 8. If, for example, it changed with PT2024.6 then the number on line 8 should be 240600

                                  1. I've realized that the script could give an incorrect count if any selected stereo clip in the clip list is expanded to show the individual channels:

                                    In this example there are two stereo clips on the selected track but with the stereo clip expanded the script will return a count 5. So be sure that no stereo clips are expanded before running this script. (unless @raphaelsepulveda has a clever way of ensuring that no stereo clips are expanded in the clip list :) )

                                    1. @Chris_Shaw, @Jack_Byrne I recently wrote this script that fetches clip info using the SDK: Get selected Clip Name #post-5

                                      Give it a shot. It doesn't rely on the Clip List panel, deals with multichannel clips, and should work with any version of PT 2023 and onwards.

                                      Just change the last line to this to get the number of selected clips:

                                      log(selectedClipNames.length);
                                      
                                      1. JJack Byrne @Jack_Byrne
                                          2024-11-23 11:07:52.454Z

                                          Thanks! My use case is typically just mono files (drum sample workflow) but it'll be handy to have a version that's a little more bomb proof

                                2. In reply toJack_Byrne:
                                  Dustin Harris @Dustin_Harris
                                    2024-11-07 07:38:56.090Z

                                    Hi Jack,
                                    I’m on mobile so my syntax might be a little off, there is also an SDK derived function that is quick:

                                    sf.app.proTools.getSelectedClipInfo().clips.length

                            2. B
                              In reply toDustin_Harris:
                              Ben Rauscher @Ben_Rauscher
                                2025-02-10 18:01:38.317Z

                                This is great @Chris_Shaw, thank you. I've been using this too:

                                clipListView.getElements("AXSelectedRows");
                                

                                Can either of these methods be used in a forEach to click through every selected clip in the Clip List window? I am trying to get this clip-color script working to increase speed without needing to continuously select "Clips in Tracks" from the color palette window. Currently, using an elementClick() will select or de-select all the rows together, not individually:

                                function Color_Clips_By_Channel_Name() {
                                    let clipListView = sf.ui.proTools.mainWindow.clipListView;
                                    //let selectedClipRowsOLD = clipListView.getElements("AXSelectedRows");
                                
                                    let selectedClipRows = clipListView.children.whoseRole.is("AXRow").allItems
                                        .map(row => 
                                            row.children[1].children.first.value.value)
                                                .filter(clip => clip.startsWith('Selected. '));
                                
                                    log (selectedClipRows);
                                
                                    selectedClipRows.forEach(row => {
                                        // Click the row in the clip list to select the clip in the timeline, or de-select at the end...
                                        //row.elementClick();
                                
                                        // Get metadata
                                        let clipDetailsElement = row.children.allItems[1].children.first;
                                
                                        if (!clipDetailsElement || !clipDetailsElement.title.value) {
                                            log(`Warning: Skipping clip due to missing or invalid details.`);
                                            return;
                                        }
                                
                                        let clipDetails = clipDetailsElement.title.value;
                                        let line2 = clipDetails.split("\n")[1];
                                
                                        if (!line2) {
                                            log(`Warning: Skipping clip with invalid format: ${clipDetails}`);
                                            return;
                                        }
                                
                                        let psplit = line2.split("(");
                                
                                        if (psplit.length < 2) {
                                            throw new Error("Invalid clip format: Missing parenthesis content.");
                                        }
                                
                                        //let clipName = line2.split("(")[0].trim().replace(/"/g, "");
                                        let parenthesisContent = psplit[1].split(")")[0];
                                        let detailsMatch = parenthesisContent.match(/S:\s*(\S+),\s*T:\s*(\S+),\s*(\S+)/);
                                
                                        //let sceneNumber = detailsMatch ? detailsMatch[1] : "Unknown";
                                        //let takeNumber = detailsMatch ? detailsMatch[2] : "Unknown";
                                        let channelName = detailsMatch ? detailsMatch[3] : "Unknown";
                                
                                        // Color the clip without re-selecting "Clips in Tracks"
                                        let selectedColor = colorIso; // Default
                                
                                        if (channelName.toLowerCase().includes("mix")) {
                                            selectedColor = colorMix;
                                        } else if (channelName.toLowerCase().includes("boom")) {
                                            selectedColor = colorBoom;
                                        } else if (channelName.toLowerCase().includes("plant")) {
                                            selectedColor = colorPlant;
                                        }
                                
                                        sf.waitFor({ callback: () => 
                                            sf.ui.proTools.colorPaletteWindow.tables.whoseTitle.is("Color Palette View").first
                                                .children.whoseRole.is("AXRow").allItems[selectedColor.row]
                                                .children.whoseRole.is("AXCell").allItems[selectedColor.cell].buttons.first
                                                .elementClick()
                                        });
                                
                                        // ...Command-click to de-select the processed clip and proceed to the next row
                                    });
                                }