No internet connection
  1. Home
  2. How to

Background Editing Script Help

By Owen Granich-Young @Owen_Granich_Young
    2022-12-01 22:37:41.421Z

    Hey @samuel_henriques I had an idea about the next step in automating background editing after this awesome script you wrote for Jake How to write an "exclude memory locations with this name" #post-5

    Wondering if this workflow is possible.

    Select all clips on Guide Track
    Get names of all clips in Guide - filter out duplicate names - (create an array?)
    Prompt user to choose a Name via sf.Prompt
    User chooses a clip name
    for each clip of that name - select clip - navigate to user defined track/tracks Paste to fill selection

    So you could load any specific location's BG build into your clipboard and then run the script to fill that location across the whole show.

    Thoughts?

    I don't even know if you can scrape clip names like memory locations, or how you would feels possible though, as long as you don't have a search enabled 😂

    Solved in post #5, click to view
    • 8 replies
    1. O

      Ok, so I did the easy legwork part. Can anybody help me with the hard Filtering part? I realized starting on the destination tracks was a better approach as then the user doesn't have to pre-define those.

      Or is the filtering not really possible with do for each selected clip? Does it have to instead have a 'read the title of the clip if correct title do action if not continue' ? That feels like it would be a slower process but maybe that's what it has to be as doForEachSelectedClip can't pre filter?

      //Activate Pro Tools main window;
      sf.ui.proTools.appActivateMainWindow();
      sf.ui.proTools.mainWindow.invalidate();
      
      //Original Track Names
      const originalTrackNames = sf.ui.proTools.selectedTrackNames;
      
      sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect();
      
      sf.ui.proTools.clipDoForEachSelectedClip({
          action: () => {
              sf.ui.proTools.trackSelectByName({ names: originalTrackNames });
      
              sf.ui.proTools.menuClick({
                  menuPath: ["Edit", "Paste Special", "Repeat to Fill Selection"],
              });
      
              sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect();
      
      
          },
          onError: "Continue",
      });
      
      1. OOwen Granich-Young @Owen_Granich_Young
          2022-12-02 19:26:36.290Z2022-12-02 19:35:37.076Z

          Ok, so I'm getting closer to scanning the clip names and selecting from them, (thanks to this post Get selected Clip Name @raphaelsepulveda ) The array it generates looks right and the select goes through, but for some reason my log comes up undefined, what simple thing am I missing?

          function getSelectedClipNamesFromClipList() {
              const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
          
              // Get all selected clips
              const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                  row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
          
              // Extract clip names
              const clipNames = selectedClips.map(c => c.split('"')[1]);
          
              return clipNames
          };
          
          const selectedClip = getSelectedClipNamesFromClipList();
          
          const chosenBackground = selectedClip[sf.interaction.popupSearch({
              title: `Select Background Name`,
              items: selectedClip.map(item => ({ name: item })),
              onCancel: 'Abort',
          }).item.name]
          
          log(chosenBackground)
          

          nvm...

          Found a better solution that also filters :

          function getSelectedClipNamesFromClipList() {
              const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
          
              // Get all selected clips
              const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                  row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
          
              // Extract clip names
              const clipNames = selectedClips.map(c => c.split('"')[1]);
          
              return clipNames
          };
          
          const selectedClip = getSelectedClipNamesFromClipList();
          
          //Filter out Memory location name duplicates
                  let uniqueBackgroundLocations = [...new Set(selectedClip)];
          
                  //Popup Search
                  let targetBackgroundLocation = sf.interaction.popupSearch({
                      items: uniqueBackgroundLocations.map(name => ({ name: name })),
                  }).item.name
          
          
          
          log(targetBackgroundLocation)
          
          
        • O

          Ok I feel like I'm so close to unlocking the last little piece with this post here Is there a way to search by region name and color all named "X" a specified color?

          However this does nothing now... can someone push me over the finish line?

          
          function getSelectedClipNamesFromClipList() {
              const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
          
              // Get all selected clips
              const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                  row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
          
              // Extract clip names
              const clipNames = selectedClips.map(c => c.split('"')[1]);
          
              return clipNames
          };
          
          function getClipName() {
              sf.ui.proTools.menuClick({ menuPath: ["Clip", "Rename..."] });
              const renameWin = sf.ui.proTools.windows.whoseTitle.is("Name").first.elementWaitFor({}, 'Rename Clip Window Not Found.').element;
              const clipName = renameWin.groups.first.textFields.first.value.invalidate().value;
              renameWin.buttons.whoseTitle.is("Cancel").first.elementClick();
              renameWin.elementWaitFor({ waitType: "Disappear" }, 'Rename Clip Window Failed to Close.');
              return clipName;
          };
          
          //Activate Pro Tools main window;
          sf.ui.proTools.appActivateMainWindow();
          sf.ui.proTools.mainWindow.invalidate();
          
          //Original Track Names
          const originalTrackNames = sf.ui.proTools.selectedTrackNames;
          
          sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect();
          
          const selectedClip = getSelectedClipNamesFromClipList();
          
          //Filter out Memory location name duplicates
          let uniqueBackgroundLocations = [...new Set(selectedClip)];
          
          //Popup Search
          let targetBackgroundLocation = sf.interaction.popupSearch({
              items: uniqueBackgroundLocations.map(name => ({ name: name })),
          }).item.name
          
          function pasteBackground(name) {
              if (name in targetBackgroundLocation) {
                  sf.ui.proTools.trackSelectByName({ names: originalTrackNames });
          
                  sf.ui.proTools.menuClick({
                      menuPath: ["Edit", "Paste Special", "Repeat to Fill Selection"],
                  });
          
                  sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect();
          
              } 
          };
          
          // Color each selected clip
          sf.ui.proTools.clipDoForEachSelectedClip({
              action: () => {
          
                  pasteBackground(getClipName())
          
              },
              onError: "Continue"
          })
          
          

          Is there an IS instead of an IN for the if statement? Have I just completely mis ordered?

          1. Got it.... Needed an extra invalidate. And to simply the get and if. Coooooool! I'm sure the code could use refactoring as I've just been cobbling it together, but pretty stoked! I'll also have to build in some error handling for 'crossfades for repeat to fill selection and so forth'

            function getSelectedClipNamesFromClipList() {
                const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
            
                // Get all selected clips
                const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                    row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
            
                // Extract clip names
                const clipNames = selectedClips.map(c => c.split('"')[1]);
            
                return clipNames
            };
            
            function getClipName() {
                sf.ui.proTools.menuClick({ menuPath: ["Clip", "Rename..."] });
                const renameWin = sf.ui.proTools.windows.whoseTitle.is("Name").first.elementWaitFor({}, 'Rename Clip Window Not Found.').element;
                const clipName = renameWin.groups.first.textFields.first.value.invalidate().value;
                renameWin.buttons.whoseTitle.is("Cancel").first.elementClick();
                renameWin.elementWaitFor({ waitType: "Disappear" }, 'Rename Clip Window Failed to Close.');
                return clipName;
            };
            
            function main(){
            
                //Activate Pro Tools main window;
                sf.ui.proTools.appActivateMainWindow();
                sf.ui.proTools.mainWindow.invalidate();
            
                //Original Track Names
                const originalTrackNames = sf.ui.proTools.selectedTrackNames;
            
                sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect();
            
                const selectedClip = getSelectedClipNamesFromClipList();
            
                //Filter out Memory location name duplicates
                let uniqueBackgroundLocations = [...new Set(selectedClip)];
            
                //Popup Search
                let targetBackgroundLocation = sf.interaction.popupSearch({
                    items: uniqueBackgroundLocations.map(name => ({ name: name })),
                }).item.name
            
                sf.ui.proTools.appActivateMainWindow();
                sf.ui.proTools.mainWindow.invalidate();
            
                sf.ui.proTools.clipDoForEachSelectedClip({
                    action: () => {
            
                        getClipName()
            
                        if (getClipName() == targetBackgroundLocation) {
                            sf.ui.proTools.trackSelectByName({ names: originalTrackNames });
            
                            sf.ui.proTools.menuClick({
                                menuPath: ["Edit", "Paste Special", "Repeat to Fill Selection"],
                            });
            
                            sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect()
            
                        }
            
                    },
                    onError: "Continue",
                });
            }
            
            main();
            
            ReplySolution
            1. samuel henriques @samuel_henriques
                2022-12-08 21:46:15.299Z

                Hey Owen, awesome work. Sorry I missed all your questions.
                How is it working now, do you need help on any more bits?

                1. This one is working! I've moved onto one that I'm trying to get to read the clip name then go and get the matching 'selection memory location' paste it and move onto the next clip. Basically 'build my backgrounds' script. It's a bit fragile though, and last time I gave it a run it just broke. Taking a break for a little while before I revisit it.

                  TBH my biggest problem with this one is it seems to be erroring out on @Jake_Carter much larger session, not 100% sure what kind of redundancy we can build into it to wait for it to actually process but I think the 'get clip names from Clip List' with his ENORMOUS clip list is really throwing it for a loop.

                  1. samuel henriques @samuel_henriques
                      2022-12-09 19:30:16.147Z

                      If you can predict what are the clip names, you can make a list and ask from that list which ones you want to paste, that would make it faster.

                      Another way is If you have a set of backgrounds in the session, you could start by doing a doForEachSelectedClip and take the background names and locations. Then choosing the "=SCENE=" track and location find the clip names that mach the backgrounds you just "scanned" and it would go to background, copy, go to where clip at =scene= was found and paste. This would automate it completely

                      Tweaked some bits, not major

                      function getSelectedClipNamesFromClipList() {
                          const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
                      
                          // Get all selected clips
                          const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                              row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
                      
                          // Extract clip names
                          const clipNames = selectedClips.map(c => c.split('"')[1]);
                      
                          return clipNames
                      };
                      
                      function getClipName() {
                          sf.ui.proTools.menuClick({ menuPath: ["Clip", "Rename..."] });
                          const renameWin = sf.ui.proTools.windows.whoseTitle.is("Name").first.elementWaitFor({}, 'Rename Clip Window Not Found.').element;
                          const clipName = renameWin.groups.first.textFields.first.value.invalidate().value;
                          renameWin.buttons.whoseTitle.is("Cancel").first.elementClick();
                          renameWin.elementWaitFor({ waitType: "Disappear" }, 'Rename Clip Window Failed to Close.');
                          return clipName;
                      };
                      
                      function main() {
                      
                          //Activate Pro Tools main window;
                          sf.ui.proTools.appActivateMainWindow();
                          sf.ui.proTools.mainWindow.invalidate();
                      
                          //Original Track Names
                          const originalTrackNames = sf.ui.proTools.selectedTrackNames;
                      
                          sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect();
                      
                          const selectedClip = getSelectedClipNamesFromClipList();
                      
                          //Filter out Memory location name duplicates
                          let uniqueBackgroundLocations = selectedClip.filter((n, i) => selectedClip.indexOf(n) === i)
                      
                          //Popup Search
                          let targetBackgroundLocation = sf.interaction.popupSearch({
                              items: uniqueBackgroundLocations.map(name => ({ name: name })),
                          }).item.name
                      
                      
                          sf.ui.proTools.clipDoForEachSelectedClip({
                              action: () => {
                      
                                  const clipName = getClipName()
                      
                                  if (clipName === targetBackgroundLocation) {
                                      sf.ui.proTools.trackSelectByName({ names: originalTrackNames });
                      
                                      sf.ui.proTools.menuClick({
                                          menuPath: ["Edit", "Paste Special", "Repeat to Fill Selection"],
                                      });
                      
                                      sf.ui.proTools.trackGetByName({ name: '=SCENE=', makeVisible: true }).track.trackSelect()
                      
                                  }
                      
                              },
                              onError: "Continue",
                          });
                      }
                      
                      main();