No internet connection
  1. Home
  2. How to

How to use looseMatch in Popup Menu

By Nathan Salefski @nathansalefski
    2023-08-25 15:21:48.884Z

    I'm trying to move a folder to another folder. The issue I'm running into is the '-''s added to the folder menu item name depending on how deep it is within another folder

    I tried using looseMatch but it doesn't seem to work in Popup Menus. Any ideas on how to work around this?

    //Move Tracks to New Folder
    sf.ui.proTools.selectedTrack.titleButton.popupMenuSelect({ 
        isRightClick: true, 
        relativePosition: { x: 5, y: 5 }, 
        looseMatch: true,
        menuPath: ['Move to...', parentName],});
    }
    
    • 32 replies

    There are 32 replies. Estimated reading time: 77 minutes

    1. Nathan Salefski @nathansalefski
        2023-08-25 18:17:55.236Z

        I tried this as well but it seemingly only works for names with a single '-' :

        try {
            sf.ui.proTools.selectedTrack.titleButton.popupMenuSelect({ 
            isRightClick: true, 
            relativePosition: { x: 5, y: 5 },
            menuSelector: items => items.filter(i => i.path.includes(parentName))[0]
            });
            } catch(err) { log('Could Not Move Folder to: ' + parentName); return; }
        
        }
        
        1. In reply tonathansalefski:
          Kitch Membery @Kitch2023-08-25 19:17:30.037Z

          This should do the trick.

          sf.ui.proTools.appActivateMainWindow();
          
          const folderName = "Folder 3"
          
          sf.ui.proTools.selectedTrack.titleButton.popupMenuSelect({
              isRightClick: true,
              relativePosition: { x: 5, y: 5 },
              menuSelector: items => items.filter(mi => mi.path[mi.path.length - 1].endsWith(folderName))[0]
          }, `Could Not Move Folder to: ${folderName}`);
          
          1. Nathan Salefski @nathansalefski
              2023-08-25 22:55:48.281Z

              Currently tried and received this error:
              "Couldn't get count of attribute 'AXChildren' of element with title '', role '': kAXErrorInvalidUIElement"

              1. Kitch Membery @Kitch2023-08-26 01:22:00.316Z

                The main window may need invalidating if your track names or position has changed.

                sf.ui.proTools.appActivateMainWindow();
                sf.ui.proTools.mainWindow.invalidate();
                
                const folderName = "Folder 3"
                
                sf.ui.proTools.selectedTrack.titleButton.popupMenuSelect({
                    isRightClick: true,
                    relativePosition: { x: 5, y: 5 },
                    menuSelector: items => items.filter(mi => mi.path[mi.path.length - 1].endsWith(folderName))[0]
                }, `Could Not Move Folder to: ${folderName}`);
                
                1. Nathan Salefski @nathansalefski
                    2023-08-26 15:06:56.113Z

                    Not quite working. This is a part of a much larger script. Everything is working but this does something strange and the error ends up opening the color palette? lol. It's also closing some folders for some reason. Here's a screen recording https://we.tl/t-i7vJIobLzt

                    1. Kitch Membery @Kitch2023-08-26 19:55:55.553Z

                      It could be exhibiting this behavior for a couple of reasons.

                      • If the click position is not within the frame of the button title. (I've implemented clicking the center of the title buttons frame)
                      • If the track needs to be scrolled into view. (I've implemented trackScrollToView)

                      I also noticed that if the selected track was already inside the target folder the titleButton popup menu would remain open because, despite the fact that the menu path exists, the last item in the menu path is greyed out (disabled).

                      Give this reusable function a try.

                      function moveToFolder({ folderName }) {
                          sf.ui.proTools.appActivateMainWindow();
                          sf.ui.proTools.mainWindow.invalidate();
                      
                          const selectedTrack = sf.ui.proTools.selectedTrack;
                      
                          // Scroll track into view in case it's off screen
                          selectedTrack.trackScrollToView();
                      
                          // Selected Tracks Title Button
                          const titleButton = selectedTrack.titleButton;
                      
                          const titleButtonFrame = titleButton.frame;
                      
                          titleButton.popupMenuSelect({
                              isRightClick: true,
                              relativePosition: {
                                  x: titleButtonFrame.w / 2, // Center of button's x axis
                                  y: titleButtonFrame.h / 2, // Center of button's y axis
                              },
                              menuSelector: items => items.filter((mi) => {
                                  return mi.path[mi.path.length - 1].endsWith(folderName);
                              })[0],
                          }, `Could Not Move Folder to: ${folderName}`);
                      
                          // Activate Pro Tools main window to close the popup menu, in cases where the selected track was already inside target folder. 
                          sf.ui.proTools.appActivateMainWindow();
                      }
                      
                      moveToFolder({ folderName: "Folder 2" });
                      
                      1. Nathan Salefski @nathansalefski
                          2023-08-26 22:03:41.000Z

                          No such luck quite yet. I'm going to include the entirety of the larger function here. Some of the functionality of what you suggested like selectedTrack.trackScrollToView(); is present just worded differently. Thanks for all your help Kitch! My goal is to maintain the same folder hierarchy as it is in finder upon import. Proving to be a bit tricky.

                          function importAudioForEach({ paths }) {
                              
                              //Define Import Audio Window
                              const openWin = sf.ui.proTools.windows.whoseTitle.is('Open').first;
                          
                              //Reference to Audio Import Options Window
                              const aIOWin = sf.ui.proTools.windows.whoseTitle.is("Audio Import Options").first
                          
                              paths.forEach(path => {
                          
                                  //File, Import, Audio
                                  sf.ui.proTools.menuClick({ menuPath: ["File", "Import", "Audio..."], });
                          
                                  //Wait for 'Open' Window
                                  openWin.elementWaitFor({ waitType: "Appear" });
                          
                                  //Open 'Go' Sheet
                                  sf.keyboard.type({ text: '/' });
                          
                                  //Wait for 'Go' Sheet Window to Appear
                                  openWin.sheets.first.elementWaitFor({ waitType: "Appear" });
                          
                                  //Set Destination
                                  openWin.sheets.first.textFields.first.elementSetTextAreaValue({ value: path });
                          
                                  //Press Return
                                  sf.keyboard.press({ keys: "return", });
                          
                                  //Wait for 'Go' Sheet Window to Disappear
                                  openWin.sheets.first.elementWaitFor({ waitType: "Disappear" });
                          
                                  //Select All
                                  sf.keyboard.press({ keys: "cmd+a", });
                          
                                  //Try "Copy" or "Convert"
                                  try {openWin.buttons.whoseTitle.is("Copy ->").first.elementClick();}
                          
                                  catch(err) { 
                                      
                                      sf.wait({intervalMs: 200});
                          
                                      if (openWin.buttons.whoseTitle.is("Convert ->").first.exists) { 
                                      
                                          try {openWin.buttons.whoseTitle.is("Convert ->").first.elementClick();} 
                                      
                                          catch(err) {log('Could Not Import Audio From: ' + path)};
                                          
                                      }
                                  }
                          
                                  //Click "Open"
                                  if (openWin.buttons.whoseTitle.is('Open').first.isEnabled) {
                                      
                                      try {openWin.buttons.whoseTitle.is('Open').first.elementClick();}
                          
                                      catch(err) {
                                          
                                          sf.wait({intervalMs: 200});
                          
                                          try {openWin.buttons.whoseTitle.is('Open').first.elementClick();}
                          
                                          catch(err) {log('Could Not Click Open')};
                                      }
                          
                                      //Wait for 'Open' Window
                                      openWin.elementWaitFor({ waitType: "Appear" });
                          
                                      //Click "Open"
                                      openWin.buttons.whoseTitle.is('Open').first.elementClick();
                          
                                      //Wait for 'Go' Sheet Window to Appear
                                      aIOWin.elementWaitFor({ waitType: "Appear" });
                          
                                      //Click "OK" to New Track
                                      aIOWin.buttons.whoseTitle.is("OK").first.elementClick();
                          
                                      //Wait
                                      sf.ui.proTools.waitForNoModals();
                          
                                  } else if (!openWin.buttons.whoseTitle.is('Open').first.isEnabled) {
                          
                                      //Click "Cancel"
                                      openWin.buttons.whoseTitle.is('Cancel').first.elementClick();
                          
                                      //Wait For Window to Disappear
                                      openWin.elementWaitFor({ waitType: "Disappear" });
                          
                                      log('No Audio In: ' + path)
                          
                                      return;
                          
                                  }
                          
                                  //Move Audio to Folder
                                  function moveToFolder() {
                          
                                      //Refresh Cache
                                      sf.ui.proTools.mainWindow.invalidate();
                          
                                      //Move Tracks to New Folder
                                      sf.ui.proTools.menuClick({ menuPath: ['Track', 'Move to New Folder...'],});
                          
                                      //Define Folder Window
                                      const folderWin = sf.ui.proTools.windows.whoseTitle.is("Move To New Folder").first
                          
                                      //Wait for Folder Window to Appear
                                      folderWin.elementWaitFor({waitType: "Appear"})
                          
                                      //Click Create
                                      folderWin.buttons.whoseTitle.is("Create").first.elementClick()
                          
                                      //Wait for Folder Window to Disappear
                                      folderWin.elementWaitFor({waitType: "Disappear"})
                          
                                      }
                          
                                  moveToFolder();
                          
                                  function renameFolder() {
                                          //Refresh After Making Folder
                                          sf.ui.proTools.mainWindow.invalidate();
                          
                                          //Define Folder Track
                                          const folderTrack = sf.ui.proTools.trackNames.filter(tn => tn.startsWith('Folder'))
                          
                                          //Select Folder Track
                                          sf.ui.proTools.trackSelectByName({ names: folderTrack, deselectOthers: true});
                          
                                          //Scroll to Track
                                          sf.ui.proTools.selectedTrack.trackScrollToView();
                          
                                          //Define Number of Backslashes in File Path to Keep Naming of Folders Consistent
                                          const backSlashes = Number(path.split('/').length) - 1
                          
                                          //Define Folder Name
                                          const folderName = path.split('/').slice(Number(backSlashes)).join('/')                
                          
                                          //Rename Folder Track to Corresponding Folder Name
                                          sf.ui.proTools.selectedTrack.trackRename({ renameFunction: oldName => folderName, });     
                          
                                      }
                                  
                                  renameFolder();
                          
                                  sf.ui.proTools.mainWindow.invalidate();
                          
                                  //TRYING TO KEEP FOLDER HIERARCHY THE SAME AS IN FINDER!!!
                                  const parentBackSlashes = Number(path.split('/').length) - 2
                          
                                  //Define Folder Name
                                  const parentName = path.split('/').slice(Number(parentBackSlashes), -1).join('/') 
                          
                                  const parentTrack = sf.ui.proTools.trackGetByName({ name: parentName }).track
                          
                                  if (parentTrack) {
                          
                                      //Move Audio to Folder
                                      function moveToParentFolder() {
                          
                                      //Define Number of Backslashes in File Path to Keep Naming of Folders Consistent
                                      const backSlashes = Number(path.split('/').length) - 1
                          
                                      //Define Folder Name
                                      let folderName = path.split('/').slice(Number(backSlashes)).join('/')
                          
                                      //Define Folder Track
                                      const folderTrack = sf.ui.proTools.trackNames.filter(tn => tn.startsWith(folderName))
                          
                                      try {
                                          //Select Folder Track
                                          sf.ui.proTools.trackSelectByName({ names: folderTrack, deselectOthers: true});
                          
                                          //Scroll to Track
                                          sf.ui.proTools.selectedTrack.trackScrollToView();
                          
                                          //Bank Track
                                          sf.ui.proTools.selectedTrack.titleButton.mouseClickElement({ isControl: true, isShift: true, relativePosition: { x: 5, y: 5 }});               
                                      }
                          
                                      catch(err) {log('Could Not Find Folder');}
                          
                                      sf.ui.proTools.mainWindow.invalidate();
                          
                                      //Move Tracks to New Folder
                                      try {
                          
                                          function moveToFolder({ folderName }) {
                                              
                                              sf.ui.proTools.appActivateMainWindow();
                                              sf.ui.proTools.mainWindow.invalidate();
                          
                                              const selectedTrack = sf.ui.proTools.selectedTrack;
                          
                                              // Scroll track into view in case it's off screen
                                              selectedTrack.trackScrollToView();
                          
                                              // Selected Tracks Title Button
                                              const titleButton = selectedTrack.titleButton;
                          
                                              const titleButtonFrame = titleButton.frame;
                          
                                              titleButton.popupMenuSelect({
                                                  isRightClick: true,
                                                  relativePosition: {
                                                      x: titleButtonFrame.w / 2, // Center of button's x axis
                                                      y: titleButtonFrame.h / 2, // Center of button's y axis
                                                  },
                                                  menuSelector: items => items.filter((mi) => {
                                                      return mi.path[mi.path.length - 1].endsWith(folderName);
                                                  })[0],
                                              }, `Could Not Move Folder to: ${parentName}`);
                          
                                              // Activate Pro Tools main window to close the popup menu, in cases where the selected track was already inside target folder. 
                                              sf.ui.proTools.appActivateMainWindow();
                                          }
                          
                                          moveToFolder({ folderName: parentName });
                          
                                      } catch(err) { log('Could Not Move Folder to: ' + parentName) }
                          
                                      }
                          
                                      moveToParentFolder();
                          
                                  }
                          
                                  //Deselect All Tracks
                                  sf.ui.proTools.trackDeselectAll();
                          
                              });
                          
                              //Refresh Cache
                              sf.ui.proTools.mainWindow.invalidate();
                          
                          }
                          
                          1. Kitch Membery @Kitch2023-08-26 22:39:04.949Z

                            Hi @nathansalefski,

                            Before we go hunting down the issue in the context of the full script, it's really important that we test the standalone function that is moving the selected track to a specified folder.

                            Your replies to this thread so far have been "Currently tried and received this error", "Not quite working", "No such luck quite yet", and I'm convinced you are attempting to run the code that I've provided weaved into your larger script.

                            I can already see from your full script that there are two functions named moveToFolder(). One that accepts a folderName as an argument (the script I shared in this thread), and one that does not. I can also see another function namedmoveToParentFolder() that performs a very similar action of moving track(s) to a folder. This means there are three potential places (two of which I had no prior knowledge of,) where the actions of moving track(s) to a specific folder could fail.

                            So let's first focus on testing the script that I've shared to see if you can make it fail.
                            To do this please copy the function from Post 9 into a new script. Then run the script in all the scenarios that you foresee the full script will need.
                            If it fails, we can address that issue specifically. If you can't make the standalone function fail then let's look at the full script in context to see if we can find a solution.

                            It's super important to test things this way, otherwise, it becomes really time-consuming.

                            Thanks in advance.

                            1. Nathan Salefski @nathansalefski
                                2023-08-26 22:45:20.004Z2023-08-26 23:03:49.497Z

                                Completely correct I’ve been implementing it into this large function when testing but this makes complete sense. I’ll try to make it fail and report back. I maybe naively figured it would be more thorough to test it in the full script rather than alone. More on the entire script, the first function moveToFolder() is moving all of the newly imported tracks to a folder. That is functioning perfectly. The second function moveToFolder() is within the larger function moveToParentFolder() and is the code from post 9 you suggested I try. The function moveToParentFolder() only runs if there's a track named the same as the pathways parent folder

                                1. Kitch Membery @Kitch2023-08-26 23:03:49.112Z

                                  Thanks for understanding @nathansalefski. As you can probably imagine, we deal with this scenario quite often when it comes to troubleshooting scripts here in the forum. Where we encounter the x/y problem. See the following link for more info about that https://xyproblem.info/ (which is similar to what we were encountering in this thread).

                                  Rock on!

                                  1. Nathan Salefski @nathansalefski
                                      2023-08-26 23:07:02.280Z

                                      Absolutely. I'm here to learn and the efficiency at which I do so is important. Makes total sense when it's put so plainly

                              • In reply toKitch:
                                Nathan Salefski @nathansalefski
                                  2023-08-26 22:57:10.458Z

                                  Ok great this works! Tired it in every way imaginable How to use looseMatch in Popup Menu #post-9

                                  1. Kitch Membery @Kitch2023-08-26 23:05:13.250Z

                                    Perfect. I'll take a look at the full script and see what's going on :-)

                                    1. Nathan Salefski @nathansalefski
                                        2023-08-26 23:07:16.625Z

                                        Thanks man

                                        1. In reply toKitch:
                                          Nathan Salefski @nathansalefski
                                            2023-08-27 03:41:24.079Z

                                            Hey @Kitch! Thanks again for the pointers. After our chat, here's the fleshed out refactor. I moved some things around to put things in a more logical order and optimize further. I'm still getting an error:

                                            "Could Not Select Track Named 'Folder 1' (Import Test: Line 123). Could not deselect tracks. Could not find select button of first selected item"

                                            It seems to be failing on folder number 4. This is the structure I've been using to test it just to ensure it will work with "any" number of folders.. Here's a DropBox link to the folder if you want to download it to test as well https://www.dropbox.com/scl/fo/w19uocurkljpiwy61n0m4/h?rlkey=79wym74telwtiw0455qdkv5gw&dl=0

                                            // Define Selcted Folder
                                            let selectedFolder = sf.ui.finder.selectedPaths[0]
                                            
                                            // Get Paths for ALL Directories in Selected Path
                                            function getDirectoryPaths(path) { return sf.file.directoryGetDirectories({ path, isRecursive: true, }).paths}
                                            
                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            function importAudio(path) {
                                                try {
                                                    // Click File, Import, Audio
                                                    sf.ui.proTools.menuClick({ menuPath: ["File", "Import", "Audio..."], });
                                            
                                                    // Define Import Audio Window
                                                    const openWin = sf.ui.proTools.windows.whoseTitle.is('Open').first;
                                            
                                                    // Wait for Import Audio Window
                                                    openWin.elementWaitFor({ waitType: "Appear" });
                                            
                                                    // Open 'Go' Sheet
                                                    sf.keyboard.type({ text: '/' });
                                            
                                                    // Wait for 'Go' Sheet Window to Appear
                                                    openWin.sheets.first.elementWaitFor({ waitType: "Appear" });
                                            
                                                    // Set Destination
                                                    openWin.sheets.first.textFields.first.elementSetTextAreaValue({ value: path });
                                            
                                                    // Press Return to Search
                                                    sf.keyboard.press({ keys: "return", });
                                            
                                                    // Wait for 'Go' Sheet Window to Disappear
                                                    openWin.sheets.first.elementWaitFor({ waitType: "Disappear" });
                                            
                                                    // Select All Audio Files
                                                    sf.keyboard.press({ keys: "cmd+a", });
                                            
                                                    // Click "Copy" or "Convert"
                                                    if (openWin.buttons.whoseTitle.is("Copy ->").first.exists) {
                                                        openWin.buttons.whoseTitle.is("Copy ->").first.elementClick({},
                                                        `Could Not Import Audio From: ${path}`
                                                        );
                                                    } else if (openWin.buttons.whoseTitle.is("Convert ->").first.exists) {
                                                        openWin.buttons.whoseTitle.is("Convert ->").first.elementClick({}, 
                                                        `Could Not Import Audio From: ${path}`
                                                        );
                                                    }
                                            
                                                    // Click "Open" if Button is Enabled, Click Open. Otherwise Assume Folder is Empty and Click Cancel
                                                    if (openWin.buttons.whoseTitle.is('Open').first.isEnabled) {
                                                        // Click "Open"
                                                        openWin.buttons.whoseTitle.is('Open').first.elementClick();
                                            
                                                        // Wait for 'Open' Window to Appear
                                                        openWin.elementWaitFor({ waitType: "Appear" });
                                            
                                                        // Click "Open"
                                                        openWin.buttons.whoseTitle.is('Open').first.elementClick();
                                            
                                                        // Define Audio Import Options Window
                                                        const audioImportOptionsWin = sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first;
                                            
                                                        // Wait for Audio Import Options Window to Appear
                                                        audioImportOptionsWin.elementWaitFor({ waitType: "Appear" });
                                            
                                                        // Click "OK"
                                                        audioImportOptionsWin.buttons.whoseTitle.is("OK").first.elementClick();
                                            
                                                        // Wait for Import to Complete
                                                        sf.ui.proTools.waitForNoModals();
                                                    } else {
                                                        // Click "Cancel"
                                                        openWin.buttons.whoseTitle.is('Cancel').first.elementClick();
                                            
                                                        // Wait For Window to Disappear
                                                        openWin.elementWaitFor({ waitType: "Disappear" });
                                            
                                                        log(`No Audio in ${path}`);
                                                    }
                                                } catch (err) {
                                                    throw err;
                                                }
                                            }
                                            
                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            function moveSelectedTracksToNewFolder() {
                                                try {
                                                    // Refresh Cache
                                                    sf.ui.proTools.mainWindow.invalidate();
                                            
                                                    // Click 'Move to New Folder...' from the 'Track Menu'
                                                    sf.ui.proTools.menuClick({ menuPath: ['Track', 'Move to New Folder...']}, 
                                                    `Could Not Click Menu Path: 'Track', 'Move to New Folder...'`
                                                    );
                                            
                                                    // Define Move To New Folder Window
                                                    const moveToNewFolderWin = sf.ui.proTools.windows.whoseTitle.is("Move To New Folder").first;
                                            
                                                    // Wait for Move To New Folder Window to Appear
                                                    moveToNewFolderWin.elementWaitFor({ waitType: "Appear" });
                                            
                                                    // Click Create
                                                    moveToNewFolderWin.buttons.whoseTitle.is("Create").first.elementClick({}, `Could Not Click Button Labeled 'Create'`);
                                            
                                                    // Wait for Move To New Folder Window to Disappear
                                                    moveToNewFolderWin.elementWaitFor({ waitType: "Disappear" });
                                                } catch (err) {
                                                    throw err;
                                                }
                                            }
                                            
                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            function bankToTrackNamed(trackName) { 
                                                // Refresh Cache
                                                sf.ui.proTools.mainWindow.invalidate();
                                            
                                                // Select Track By Name
                                                sf.ui.proTools.trackSelectByName({
                                                    names: [trackName],
                                                    deselectOthers: true
                                                }, `Could Not Select Track Named '${trackName}'`);
                                            
                                                // Scroll to Selected Track
                                                sf.ui.proTools.selectedTrack.trackScrollToView({}, 
                                                `Could Not Scroll Selected Track into View`
                                                );
                                            
                                                // Bank Track
                                                sf.ui.proTools.selectedTrack.titleButton.mouseClickElement({
                                                    isControl: true,
                                                    isShift: true,
                                                    relativePosition: { x: 5, y: 5 }
                                                }, `Could Not Click Title Button of Track Named '${trackName}'`);
                                            }
                                            
                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            function renameSelectedFolder(path) {
                                                try {
                                                    // Refresh Cache
                                                    sf.ui.proTools.mainWindow.invalidate();
                                            
                                                    // Define Number of Backslashes in File Path and Subtracting 1 to Keep Naming of Folders Consistent Regardless of File Path
                                                    const pathBackSlashes = Number(path.split('/').length) - 1;
                                            
                                                    // Define Folder Name
                                                    const pathFolderName = path.split('/').slice(Number(pathBackSlashes)).join('/');
                                            
                                                    // Rename Selected Folder Track to Corresponding Finder Folder Name
                                                    sf.ui.proTools.selectedTrack.trackRename({ renameFunction: oldName => pathFolderName,}, 
                                                    `Could Not Rename Selected Track to '${pathFolderName}'`
                                                    );
                                                } catch (err) {
                                                    throw err;
                                                }
                                            }
                                            
                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            function moveSelectedFolderToParentFolder({ folderName }) {
                                                try {
                                                    // Refresh Cache
                                                    sf.ui.proTools.mainWindow.invalidate();
                                            
                                                    // Define Selected Tracks Title Button
                                                    const titleButton = sf.ui.proTools.selectedTrack.titleButton;
                                            
                                                    const titleButtonFrame = titleButton.frame;
                                            
                                                    titleButton.popupMenuSelect({
                                                        isRightClick: true,
                                                        relativePosition: {
                                                            x: titleButtonFrame.w / 2, // Center of button's x axis
                                                            y: titleButtonFrame.h / 2, // Center of button's y axis
                                                        },
                                                        menuSelector: items => items.filter((mi) => {
                                                            return mi.path[mi.path.length - 1].endsWith(folderName);
                                                        })[0],
                                                    }, `Could Not Move Folder to: ${folderName}`);
                                            
                                                    // Activate Pro Tools main window to close the popup menu, in cases where the selected track was already inside target folder. 
                                                    //sf.ui.proTools.appActivateMainWindow();
                                                } catch (err) {
                                                    throw err;
                                                }
                                            }
                                            
                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                            
                                            function importAudioForEach({ paths }) {
                                            
                                                paths.forEach(path => {
                                            
                                                    importAudio(path);
                                            
                                                    moveSelectedTracksToNewFolder();
                                                    
                                                    bankToTrackNamed('Folder 1');
                                            
                                                    renameSelectedFolder(path);
                                            
                                                    // TRYING TO KEEP FOLDER HIERARCHY THE SAME AS IN FINDER!!!
                                                    const parentPathBackSlashes = Number(path.split('/').length) - 2
                                            
                                                    // Define Parent Folder Name
                                                    const parentFolderName = path.split('/').slice(Number(parentPathBackSlashes), -1).join('/')
                                            
                                                    // Define Parent Folder Track
                                                    const parentFolderTrack = sf.ui.proTools.trackGetByName({ name: parentFolderName }).track
                                            
                                                    //Using .exists Gives the Following Error: "TypeError: Cannot read property 'exists' of null (Import Test: Line 213)"
                                                    if (parentFolderTrack) {
                                                        moveSelectedFolderToParentFolder({ folderName: parentFolderName });
                                                    }
                                            
                                                    //Deselect All Tracks
                                                    sf.ui.proTools.trackDeselectAll();
                                                });
                                            }
                                            
                                            //Activate Pro Tools and Refresh Cache
                                            sf.ui.proTools.appActivate();
                                            sf.ui.proTools.mainWindow.invalidate();
                                            
                                            importAudioForEach({ paths: getDirectoryPaths(selectedFolder) });
                                            
                                            1. Kitch Membery @Kitch2023-08-27 20:09:10.036Z

                                              Hi Nathan,

                                              This looks like a possible bug with nested folders in Pro Tools it may take me a bit to track down what's going on but hopefully I'll have some time this week to investigate, or devise a workaround.

                                              1. Nathan Salefski @nathansalefski
                                                  2023-08-27 20:17:18.865Z

                                                  Thanks man! Take your time. I’ve got plenty of tidying up of the rest of the code to do! Hopefully this portion is much cleaner

                                                  1. Kitch Membery @Kitch2023-08-27 20:23:33.955Z

                                                    Ok, I think this is a Pro Tools side bug that is being caused by the width of the Tracks List being at its minimum size. If you resize the Track List's width (on the left side), the bug goes away.

                                                    I believe this bug has been logged internally.

                                                    1. In reply toKitch:
                                                      Nathan Salefski @nathansalefski
                                                        2023-08-28 00:26:24.808Z

                                                        YOU HAVE NO IDEA HOW MUCH OUR CONVERSATION HELPED! I had it working but only if the Edit Window was full size. I broke down the issue to the smallest possible problem, and now it works regardless of the Edit Window Size or Position.

                                                        // Mouse Drag Funtion
                                                        function mouseDrag(startPos, endPos) {
                                                            const timeToWaitBeforeReleasing = 250;
                                                        
                                                            sf.mouse.down({ position: startPos, });
                                                        
                                                            sf.mouse.drag({ position: endPos });
                                                        
                                                            sf.wait({ intervalMs: timeToWaitBeforeReleasing });
                                                        
                                                            sf.mouse.up({ position: endPos });
                                                        };
                                                        
                                                        ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                        
                                                        function resizeTrackListView() {
                                                            // Define Edit Window Menu Path
                                                            const editWindowMenuPath = sf.ui.proTools.getMenuItem('Window', 'Edit')
                                                        
                                                            // Show Edit Window if it isn't Shown
                                                            if (!(editWindowMenuPath.isMenuChecked)) {
                                                                // Show Track List from View Menu
                                                                sf.ui.proTools.menuClick({ menuPath: ['Window', 'Edit',] },
                                                                    `Could Not Show Edit Window`
                                                                );
                                                        
                                                                // Wait for Edit Window to be Shown
                                                                sf.wait({ intervalMs: 100 })
                                                        
                                                                // Refresh After Showing Edit Window
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            }
                                                        
                                                            // Define Track List View Menu Path
                                                            const trackListMenuPath = sf.ui.proTools.getMenuItem('View', 'Other Displays', 'Track List')
                                                        
                                                            // Show Track List if it isn't Shown
                                                            if (!(trackListMenuPath.isMenuChecked)) {
                                                                // Show Track List from View Menu
                                                                sf.ui.proTools.menuClick({ menuPath: ['View', 'Other Displays', 'Track List'], },
                                                                    `Could Not Show Track List`
                                                                );
                                                        
                                                                // Wait for Track List to be Shown
                                                                sf.wait({ intervalMs: 100 })
                                                        
                                                                // Refresh After Showing Track List
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            }
                                                        
                                                            // Define Edit Window
                                                            const editWindow = sf.ui.proTools.windows.whoseTitle.startsWith('Edit: ').first;
                                                        
                                                            // Define Pro Tools Edit Window Position
                                                            const editWindowPosition = editWindow.position;
                                                        
                                                            // Define Pro Tools Edit Window Frame
                                                            const editWindowFrame = editWindow.frame;
                                                        
                                                            // With Edit Window at Full Size:
                                                            // trackListFrame = x: 4, Minimum w: 85 
                                                            // Resize Point with Minimum w = x: 110 
                                                            // Offset = 21 (x + w = 89 ... 110 - 89 = 21)
                                                            const editWindowTrackListFrame = editWindow.tables.whoseTitle.is('Track List').first.frame;
                                                        
                                                            // Accounting for Resize Point Offset
                                                            const trackListResizePointX = editWindowPosition.x + editWindowTrackListFrame.w + 21;
                                                        
                                                            // Always in the Middle of the Window
                                                            const trackListResizePointY = editWindowPosition.y + (editWindowFrame.h / 2);
                                                        
                                                            // Define Drag Starting Point
                                                            const startDrag = { x: trackListResizePointX, y: trackListResizePointY }
                                                        
                                                            //Define Drag Ending Point
                                                            const endDrag = { x: trackListResizePointX + 150, y: trackListResizePointY }
                                                        
                                                            // Get Current Mouse Position
                                                            let originalMousePosition = sf.mouse.getPosition().position;
                                                        
                                                            // If Track List is too Small, Resize it
                                                            if (editWindowTrackListFrame.w >= 85 && editWindowTrackListFrame.w <= 250) {
                                                                // Drag Mouse
                                                                mouseDrag(startDrag, endDrag);
                                                            }
                                                        
                                                            // Restore Mouse's Original Position
                                                            sf.mouse.setPosition({ position: originalMousePosition },
                                                                `Could Not Restore Mouse's Original Position`
                                                            );
                                                        }
                                                        
                                                        
                                                        resizeTrackListView();
                                                        
                                                        1. Kitch Membery @Kitch2023-08-28 00:29:03.335Z

                                                          Great progress! So glad our chat helped :-)

                                                          1. In reply tonathansalefski:
                                                            Kitch Membery @Kitch2023-08-28 01:02:14.581Z

                                                            A few things to consider would be...

                                                            • Change the variable name for editWindowMenuPath to editWindowMenuItem as its value is a menu item, not a path.
                                                            • Remove the editWindowPosition variable as it is redundant. The editWindowFrame contains {x,y,h,w} values so there is no need to have the editWindowPosition variable to get the edit window's {x,y} values.
                                                            • Restructured the trackListResizePointX and trackListResizePointX into an object named trackListResizePoint with key-value pairs for x and y.
                                                            • Make the originalMousePosition variable into a const rather than using let as its value is not going to change throughout the duration of the script.

                                                            Here are the changes implemented. :-)

                                                            function mouseDrag(startPos, endPos) {
                                                                const timeToWaitBeforeReleasing = 250;
                                                            
                                                                sf.mouse.down({ position: startPos, });
                                                            
                                                                sf.mouse.drag({ position: endPos });
                                                            
                                                                sf.wait({ intervalMs: timeToWaitBeforeReleasing });
                                                            
                                                                sf.mouse.up({ position: endPos });
                                                            };
                                                            
                                                            function resizeTrackListView() {
                                                                // Define Edit Window Menu Path
                                                                const editWindowMenuPath = sf.ui.proTools.getMenuItem('Window', 'Edit');
                                                            
                                                                // Show Edit Window if it isn't Shown
                                                                if (!(editWindowMenuPath.isMenuChecked)) {
                                                                    // Show Track List from View Menu
                                                                    sf.ui.proTools.menuClick({ menuPath: ['Window', 'Edit',] },
                                                                        `Could Not Show Edit Window`
                                                                    );
                                                            
                                                                    // Wait for Edit Window to be Shown
                                                                    sf.wait({ intervalMs: 100 });
                                                            
                                                                    // Refresh After Showing Edit Window
                                                                    sf.ui.proTools.mainWindow.invalidate();
                                                                }
                                                            
                                                                // Define Track List View Menu Path
                                                                const trackListMenuPath = sf.ui.proTools.getMenuItem('View', 'Other Displays', 'Track List');
                                                            
                                                                // Show Track List if it isn't Shown
                                                                if (!(trackListMenuPath.isMenuChecked)) {
                                                                    // Show Track List from View Menu
                                                                    sf.ui.proTools.menuClick({ menuPath: ['View', 'Other Displays', 'Track List'], },
                                                                        `Could Not Show Track List`
                                                                    );
                                                            
                                                                    // Wait for Track List to be Shown
                                                                    sf.wait({ intervalMs: 100 });
                                                            
                                                                    // Refresh After Showing Track List
                                                                    sf.ui.proTools.mainWindow.invalidate();
                                                                }
                                                            
                                                                // Define Edit Window
                                                                const editWindow = sf.ui.proTools.windows.whoseTitle.startsWith('Edit: ').first;
                                                            
                                                                // Define Pro Tools Edit Window Frame
                                                                const editWindowFrame = editWindow.frame;
                                                            
                                                                // With Edit Window at Full Size:
                                                                // trackListFrame = x: 4, Minimum w: 85 
                                                                // Resize Point with Minimum w = x: 110 
                                                                // Offset = 21 (x + w = 89 ... 110 - 89 = 21)
                                                                const editWindowTrackListFrame = editWindow.tables.whoseTitle.is('Track List').first.frame;
                                                            
                                                                // Accounting for Resize Point Offset
                                                                // Always in the Middle of the Screen
                                                                const trackListResizePoint = {
                                                                    x: editWindowFrame.x + editWindowTrackListFrame.w + 21,
                                                                    y: editWindowFrame.y + (editWindowFrame.h / 2),
                                                                };
                                                            
                                                                // Define Drag Starting Point
                                                                const startDrag = trackListResizePoint;
                                                            
                                                                //Define Drag Ending Point
                                                                const endDrag = {
                                                                    x: trackListResizePoint.x + 150,
                                                                    y: trackListResizePoint.y
                                                                };
                                                            
                                                                // Get Current Mouse Position
                                                                const originalMousePosition = sf.mouse.getPosition().position;
                                                            
                                                                // If Track List is too Small, Resize it
                                                                if (editWindowTrackListFrame.w >= 85 && editWindowTrackListFrame.w <= 250) {
                                                                    // Drag Mouse
                                                                    mouseDrag(startDrag, endDrag);
                                                                }
                                                            
                                                                // Restore Mouse's Original Position
                                                                sf.mouse.setPosition({
                                                                    position: originalMousePosition
                                                                }, `Could Not Restore Mouse's Original Position`);
                                                            }
                                                            
                                                            resizeTrackListView();
                                                            
                                                            1. Nathan Salefski @nathansalefski
                                                                2023-08-28 01:19:55.116Z2023-08-28 01:26:46.904Z

                                                                Awesome great point about the frame. Looks great except you missed changing editWindowMenuPath to editWindowMenuItem in Lines 15 and 18. Makes sense to change trackListMenuPath to trackListMenuItem in Lines 32 and 35 as well

                                                          2. In reply tonathansalefski:
                                                            Kitch Membery @Kitch2023-08-27 21:15:56.926Z

                                                            @Nathan_Salefski,

                                                            Nice work on the refactor. Here's some further updates.

                                                            function getDirectoryPaths(path) {
                                                                // Get Paths for ALL Directories in Selected Path
                                                                let directoryPaths = sf.file.directoryGetDirectories({ path, isRecursive: true, }).paths;
                                                                
                                                                return directoryPaths;
                                                            }
                                                            
                                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                            
                                                            function importAudio(path) {
                                                                // Click File, Import, Audio Menu
                                                                sf.ui.proTools.menuClick({ menuPath: ["File", "Import", "Audio..."], });
                                                            
                                                                // Define Import Audio Window
                                                                const openWin = sf.ui.proTools.windows.whoseTitle.is('Open').first;
                                                            
                                                                // Wait for Import Audio Window
                                                                openWin.elementWaitFor();
                                                            
                                                                // Open 'Go' Sheet
                                                                sf.keyboard.type({ text: '/' });
                                                            
                                                                // Wait for 'Go' Sheet Window to Appear
                                                                openWin.sheets.first.elementWaitFor();
                                                            
                                                                // Set Destination
                                                                openWin.sheets.first.textFields.first.elementSetTextAreaValue({ value: path });
                                                            
                                                                // Press Return to Search
                                                                sf.keyboard.press({ keys: "return", });
                                                            
                                                                // Wait for 'Go' Sheet Window to Disappear
                                                                openWin.sheets.first.elementWaitFor({ waitType: "Disappear" });
                                                            
                                                                // Select All Audio Files
                                                                sf.keyboard.press({ keys: "cmd+a", });
                                                            
                                                                // Click "Copy" or "Convert"
                                                                if (openWin.buttons.whoseTitle.is("Copy ->").first.exists) {
                                                                    openWin.buttons.whoseTitle.is("Copy ->").first.elementClick({},
                                                                        `Could Not Import Audio From: ${path}`
                                                                    );
                                                                } else if (openWin.buttons.whoseTitle.is("Convert ->").first.exists) {
                                                                    openWin.buttons.whoseTitle.is("Convert ->").first.elementClick({},
                                                                        `Could Not Import Audio From: ${path}`
                                                                    );
                                                                }
                                                            
                                                                // Click "Open" if Button is Enabled, Click Open. Otherwise Assume Folder is Empty and Click Cancel
                                                                if (openWin.buttons.whoseTitle.is('Open').first.isEnabled) {
                                                                    // Click "Open"
                                                                    openWin.buttons.whoseTitle.is('Open').first.elementClick();
                                                            
                                                                    // Wait for 'Open' Window to Appear
                                                                    openWin.elementWaitFor();
                                                            
                                                                    // Click "Open"
                                                                    openWin.buttons.whoseTitle.is('Open').first.elementClick();
                                                            
                                                                    // Define Audio Import Options Window
                                                                    const audioImportOptionsWin = sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first;
                                                            
                                                                    // Wait for Audio Import Options Window to Appear
                                                                    audioImportOptionsWin.elementWaitFor();
                                                            
                                                                    // Click "OK"
                                                                    audioImportOptionsWin.buttons.whoseTitle.is("OK").first.elementClick();
                                                            
                                                                    // Wait for Import to Complete
                                                                    sf.ui.proTools.waitForNoModals();
                                                                } else {
                                                                    // Click "Cancel"
                                                                    openWin.buttons.whoseTitle.is('Cancel').first.elementClick();
                                                            
                                                                    // Wait For Window to Disappear
                                                                    openWin.elementWaitFor({ waitType: "Disappear" });
                                                            
                                                                    log(`No Audio in ${path}`);
                                                                }
                                                            }
                                                            
                                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                            
                                                            function moveSelectedTracksToNewFolder() {
                                                                // Refresh Cache
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            
                                                                // Click 'Move to New Folder...' from the 'Track Menu'
                                                                sf.ui.proTools.menuClick({ menuPath: ['Track', 'Move to New Folder...'] },
                                                                    `Could Not Click Menu Path: 'Track', 'Move to New Folder...'`
                                                                );
                                                            
                                                                // Define Move To New Folder Window
                                                                const moveToNewFolderWin = sf.ui.proTools.windows.whoseTitle.is("Move To New Folder").first;
                                                            
                                                                // Wait for Move To New Folder Window to Appear
                                                                moveToNewFolderWin.elementWaitFor();
                                                            
                                                                // Click Create
                                                                moveToNewFolderWin.buttons.whoseTitle.is("Create").first.elementClick({}, `Could Not Click Button Labeled 'Create'`);
                                                            
                                                                // Wait for Move To New Folder Window to Disappear
                                                                moveToNewFolderWin.elementWaitFor({ waitType: "Disappear" });
                                                            }
                                                            
                                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                            
                                                            function bankToTrackNamed(trackName) {
                                                                // Refresh Cache
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            
                                                                // Select Track By Name
                                                                sf.ui.proTools.trackSelectByName({
                                                                    names: [trackName],
                                                                    deselectOthers: true
                                                                }, `Could Not Select Track Named '${trackName}'`);
                                                            
                                                                // Scroll to Selected Track
                                                                sf.ui.proTools.selectedTrack.trackScrollToView({},
                                                                    `Could Not Scroll Selected Track into View`
                                                                );
                                                            
                                                                // Bank Track
                                                                sf.ui.proTools.selectedTrack.titleButton.mouseClickElement({
                                                                    isControl: true,
                                                                    isShift: true,
                                                                    relativePosition: { x: 5, y: 5 }
                                                                }, `Could Not Click Title Button of Track Named '${trackName}'`);
                                                            }
                                                            
                                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                            
                                                            function renameSelectedFolder(newName) {
                                                                // Refresh Cache
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            
                                                                // Rename Selected Folder Track to Corresponding Finder Folder Name
                                                                sf.ui.proTools.selectedTrack.trackRename({ newName: newName, },
                                                                    `Could Not Rename Selected Track to '${newName}'`
                                                                );
                                                            }
                                                            
                                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                            
                                                            function moveSelectedFolderToParentFolder(folderName) {
                                                                // Refresh Cache
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            
                                                                // Define Selected Tracks Title Button
                                                                const titleButton = sf.ui.proTools.selectedTrack.titleButton;
                                                            
                                                                const titleButtonFrame = titleButton.frame;
                                                            
                                                                titleButton.popupMenuSelect({
                                                                    isRightClick: true,
                                                                    relativePosition: {
                                                                        x: titleButtonFrame.w / 2, // Center of button's x axis
                                                                        y: titleButtonFrame.h / 2, // Center of button's y axis
                                                                    },
                                                                    menuSelector: items => items.filter((mi) => {
                                                                        return mi.path[mi.path.length - 1].endsWith(folderName);
                                                                    })[0],
                                                                }, `Could Not Move Folder to: ${folderName}`);
                                                            
                                                                // Activate Pro Tools main window to close the popup menu, in cases where the selected track was already inside target folder. 
                                                                //sf.ui.proTools.appActivateMainWindow();
                                                            }
                                                            
                                                            ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                            
                                                            function importAudioForEach({ paths }) {
                                                                paths.forEach(path => {
                                                                    let splitPathArray = path.split('/');
                                                                    // Get the Parent folder name (second last folder name from path)
                                                                    let parentFolderName = splitPathArray[splitPathArray.length - 2];
                                                                    // Get the Sub folder name (last folder name from path)
                                                                    let subFolderName = splitPathArray[splitPathArray.length - 1];
                                                            
                                                                    // Import Audio
                                                                    importAudio(path);
                                                            
                                                                    // Move Selected Tracks to new Folder
                                                                    moveSelectedTracksToNewFolder();
                                                            
                                                                    // Bank "Folder 1" track
                                                                    bankToTrackNamed('Folder 1');
                                                            
                                                                    // Rename the "Folder 1" track
                                                                    renameSelectedFolder(subFolderName);
                                                            
                                                                    // Get the Parent folder track
                                                                    const parentFolderTrack = sf.ui.proTools.trackGetByName({
                                                                        name: parentFolderName
                                                                    }).track;
                                                            
                                                                    // If parent track exists move selected tracks to the parent folder
                                                                    if (parentFolderTrack !== null && parentFolderTrack) {
                                                                        moveSelectedFolderToParentFolder(parentFolderName);
                                                                    }
                                                            
                                                                    //Deselect All Tracks
                                                                    sf.ui.proTools.trackDeselectAll();
                                                                });
                                                            }
                                                            
                                                            function main() {
                                                                // Get the selcted finder folder path
                                                                let selectedFinderFolderPath = sf.ui.finder.selectedPaths[0];
                                                            
                                                                //Activate Pro Tools and Refresh Cache
                                                                sf.ui.proTools.appActivateMainWindow();
                                                                sf.ui.proTools.mainWindow.invalidate();
                                                            
                                                                const directoryPaths = getDirectoryPaths(selectedFinderFolderPath);
                                                            
                                                                // Import Audio for each directory path
                                                                importAudioForEach({ paths: directoryPaths });
                                                            }
                                                            
                                                            main();
                                                            

                                                            Some of the changes were as follows.

                                                            • I've added a main function.
                                                            • Simplified the way you were fetching the parent folder and sub-folder names and passed them into the relevant functions.
                                                            • Removed the try-catch block as I found they were not really necessary for this script.
                                                            • Removed the default wait types from all the .elementWaitFor({ waitType: "Appear" }) so they are now .elementWaitFor()
                                                            • Renamed a few variables as they did not quite represent what the variables actually were.

                                                            Side note: I do foresee a possible issue occurring if there are no audio files in one of the finder subfolders, so you may need to account for that.

                                                            Rock on.

                                                            1. Nathan Salefski @nathansalefski
                                                                2023-08-27 21:21:32.987Z

                                                                Awesome thanks man! I tried to account for that. In line 49-78 if the "Open" button isn't enabled its presumable the sf.keyboard.press({ keys: "cmd+a", }); in line 36 to select all of the audio files didn't select anything because the folder is blank. In that case it will click cancel and log there isn't any audio in said path

                                                                1. Kitch Membery @Kitch2023-08-27 21:29:35.718Z

                                                                  For sure, however, you'll probably still need to add code to create a new Pro Tools folder using the subFolderName after canceling out of the import window, otherwise, any nested folders will not have a corresponding parent folder when it comes to nesting any subfolders.

                                                                  1. Nathan Salefski @nathansalefski
                                                                      2023-08-28 02:23:21.500Z2023-08-28 04:54:30.320Z

                                                                      I think we've done it. I changed a few things:

                                                                      • In order to handle Blank Folders as efficiently as possible, the function importAudio(path) {} was tweaked adding the moveSelectedTracksToNewFolder(); functionality into the if (openWin.buttons.whoseTitle.is('Open').first.isEnabled) statement. A new function, makeNewFolderTrack(); was added to the else {} part of the if (openWin.buttons.whoseTitle.is('Open').first.isEnabled) statement. These changes ensure that both folder with and without audio can be treated the same by the bankToTrackNamed('Folder 1'); the proceeds function importAudio(path) {}.
                                                                      • I added two functions to check the originally selected folder in Finder for Audio Files. If it detects them, it will run another new function: if (wav || mp3 !== null) { importAudioFrom(selectedFinderFolderPath) } to import that audio first before proceeding to all of the subfolders
                                                                      • Finally, I added a 'size' argument for the resizeTrackListView() function to be able to 'Increase' the size at the beginning of the script and 'Decrease' the size at the end.

                                                                      Would love for you to give it a spin and see how it's working!

                                                                      Thank you again!

                                                                      function getDirectoryPaths(path) {
                                                                          // Get Paths for ALL Directories in Selected Path
                                                                          let directoryPaths = sf.file.directoryGetDirectories({ path, isRecursive: true, }).paths;
                                                                      
                                                                          return directoryPaths;
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function checkForWAVE(path) {
                                                                          // Search for .wav File in Selected Path
                                                                          let wav = sf.file.directoryGetFiles({ searchPattern: "*" + '.wav', path: path }).paths[0];
                                                                      
                                                                          return wav;
                                                                      
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function checkForMP3(path) {
                                                                          // Search for .mp3 File in Selected Path
                                                                          let mp3 = sf.file.directoryGetFiles({ searchPattern: "*" + '.mp3', path: path }).paths[0];
                                                                      
                                                                          return mp3;
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      // Mouse Drag Funtion
                                                                      function mouseDrag(startPos, endPos) {
                                                                          const timeToWaitBeforeDropping = 250;
                                                                      
                                                                          sf.mouse.down({ position: startPos, });
                                                                      
                                                                          sf.mouse.drag({ position: endPos });
                                                                      
                                                                          sf.wait({ intervalMs: timeToWaitBeforeDropping });
                                                                      
                                                                          sf.mouse.up({ position: endPos });
                                                                      };
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function resizeTrackListView(size) {
                                                                          // Define Edit Window Menu Path
                                                                          const editWindowMenuItem = sf.ui.proTools.getMenuItem('Window', 'Edit');
                                                                      
                                                                          // Show Edit Window if it isn't Shown
                                                                          if (!(editWindowMenuItem.isMenuChecked)) {
                                                                              // Show Track List from View Menu
                                                                              sf.ui.proTools.menuClick({ menuPath: ['Window', 'Edit',] },
                                                                                  `Could Not Show Edit Window`
                                                                              );
                                                                      
                                                                              // Wait for Edit Window to be Shown
                                                                              sf.wait({ intervalMs: 100 });
                                                                      
                                                                              // Refresh After Showing Edit Window
                                                                              sf.ui.proTools.mainWindow.invalidate();
                                                                          }
                                                                      
                                                                          // Define Track List View Menu Path
                                                                          const trackListMenuItem = sf.ui.proTools.getMenuItem('View', 'Other Displays', 'Track List');
                                                                      
                                                                          // Show Track List if it isn't Shown
                                                                          if (!(trackListMenuItem.isMenuChecked)) {
                                                                              // Show Track List from View Menu
                                                                              sf.ui.proTools.menuClick({ menuPath: ['View', 'Other Displays', 'Track List'], },
                                                                                  `Could Not Show Track List`
                                                                              );
                                                                      
                                                                              // Wait for Track List to be Shown
                                                                              sf.wait({ intervalMs: 100 });
                                                                      
                                                                              // Refresh After Showing Track List
                                                                              sf.ui.proTools.mainWindow.invalidate();
                                                                          }
                                                                      
                                                                          // Define Edit Window
                                                                          const editWindow = sf.ui.proTools.windows.whoseTitle.startsWith('Edit: ').first;
                                                                      
                                                                          // Define Pro Tools Edit Window Frame
                                                                          const editWindowFrame = editWindow.frame;
                                                                      
                                                                          // With Edit Window at Full Size:
                                                                          // trackListFrame = x: 4, Minimum w: 85 
                                                                          // Resize Point with Minimum w = x: 110 
                                                                          // Offset = 21 (x + w = 89 ... 110 - 89 = 21)
                                                                          const editWindowTrackListFrame = editWindow.tables.whoseTitle.is('Track List').first.frame;
                                                                      
                                                                          // Accounting for Resize Point Offset
                                                                          // Always in the Middle of the Screen
                                                                          const trackListResizePoint = {
                                                                              x: editWindowFrame.x + editWindowTrackListFrame.w + 21,
                                                                              y: editWindowFrame.y + (editWindowFrame.h / 2),
                                                                          };
                                                                      
                                                                          // Define Drag Starting Point
                                                                          const startDrag = trackListResizePoint;
                                                                      
                                                                          let endDrag = {}
                                                                      
                                                                          if (size === 'Increase') {
                                                                              //Define Drag Ending Point
                                                                              endDrag = {
                                                                                  x: trackListResizePoint.x + 150,
                                                                                  y: trackListResizePoint.y
                                                                              };
                                                                      
                                                                              // If Track List is too Small, Resize it
                                                                              if (editWindowTrackListFrame.w >= 85 && editWindowTrackListFrame.w <= 250) {
                                                                                  // Drag Mouse
                                                                                  mouseDrag(startDrag, endDrag);
                                                                              }
                                                                          } else if (size === 'Decrease') {
                                                                              endDrag = {
                                                                                  x: trackListResizePoint.x - 150,
                                                                                  y: trackListResizePoint.y
                                                                              };
                                                                      
                                                                              mouseDrag(startDrag, endDrag);
                                                                          }
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function makeNewFolderTrack() {
                                                                      
                                                                          // Create a New Track
                                                                          sf.ui.proTools.menuClick({
                                                                              menuPath: ['Track', 'New...'],
                                                                          });
                                                                      
                                                                          // Define New Tracks Window
                                                                          const newTracksWin = sf.ui.proTools.windows.whoseTitle.is("New Tracks").first;
                                                                      
                                                                          // Wait for New Tracks Window
                                                                          newTracksWin.elementWaitFor();
                                                                      
                                                                          // Select Basic Folder
                                                                          newTracksWin.popupButtons.allItems[1].popupMenuSelect({
                                                                              menuPath: ["Basic Folder"],
                                                                          });
                                                                      
                                                                          // Click "Create"
                                                                          newTracksWin.buttons.whoseTitle.is("Create").first.elementClick();
                                                                      
                                                                          // Wait for New Tracks Window to Disappear
                                                                          newTracksWin.elementWaitFor({ waitType: "Disappear" });
                                                                      
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function moveSelectedTracksToNewFolder() {
                                                                          // Refresh Cache
                                                                          sf.ui.proTools.mainWindow.invalidate();
                                                                      
                                                                          // Click 'Move to New Folder...' from the 'Track Menu'
                                                                          sf.ui.proTools.menuClick({ menuPath: ['Track', 'Move to New Folder...'] },
                                                                              `Could Not Click Menu Path: 'Track', 'Move to New Folder...'`
                                                                          );
                                                                      
                                                                          // Define Move To New Folder Window
                                                                          const moveToNewFolderWin = sf.ui.proTools.windows.whoseTitle.is("Move To New Folder").first;
                                                                      
                                                                          // Wait for Move To New Folder Window to Appear
                                                                          moveToNewFolderWin.elementWaitFor();
                                                                      
                                                                          // Click Create
                                                                          moveToNewFolderWin.buttons.whoseTitle.is("Create").first.elementClick({}, `Could Not Click Button Labeled 'Create'`);
                                                                      
                                                                          // Wait for Move To New Folder Window to Disappear
                                                                          moveToNewFolderWin.elementWaitFor({ waitType: "Disappear" });
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function importAudio(path) {
                                                                          // Click File, Import, Audio Menu
                                                                          sf.ui.proTools.menuClick({ menuPath: ["File", "Import", "Audio..."], });
                                                                      
                                                                          // Define Import Audio Window
                                                                          const openWin = sf.ui.proTools.windows.whoseTitle.is('Open').first;
                                                                      
                                                                          // Wait for Import Audio Window
                                                                          openWin.elementWaitFor();
                                                                      
                                                                          // Open 'Go' Sheet
                                                                          sf.keyboard.type({ text: '/' });
                                                                      
                                                                          // Wait for 'Go' Sheet Window to Appear
                                                                          openWin.sheets.first.elementWaitFor();
                                                                      
                                                                          // Set Destination
                                                                          openWin.sheets.first.textFields.first.elementSetTextAreaValue({ value: path });
                                                                      
                                                                          // Press Return to Search
                                                                          sf.keyboard.press({ keys: "return", });
                                                                      
                                                                          // Wait for 'Go' Sheet Window to Disappear
                                                                          openWin.sheets.first.elementWaitFor({ waitType: "Disappear" });
                                                                      
                                                                          // Select All Audio Files
                                                                          sf.keyboard.press({ keys: "cmd+a", });
                                                                      
                                                                          // Trying to Deal with Folders Containing Audio Inside Blank Folders
                                                                          try {
                                                                              // Click "Copy" or "Convert"
                                                                              if (openWin.buttons.whoseTitle.is("Copy ->").first.exists && openWin.buttons.whoseTitle.is("Copy ->").first.isEnabled) {
                                                                                  openWin.buttons.whoseTitle.is("Copy ->").first.elementClick({},
                                                                                      `Could Not Click "Copy ->" in Import Audio Window`
                                                                                  );
                                                                              } else if (openWin.buttons.whoseTitle.is("Convert ->").first.exists && openWin.buttons.whoseTitle.is("Convert ->").first.isEnabled) {
                                                                                  openWin.buttons.whoseTitle.is("Convert ->").first.elementClick({},
                                                                                      `Could Not Click "Convert ->" in Import Audio Window`
                                                                                  );
                                                                              }
                                                                          } catch (err) {
                                                                              return
                                                                          }
                                                                      
                                                                          // Click "Open" if Button is Enabled and Move Audio to New Folder
                                                                          //Otherwise Assume Folder is Empty, Click Cancel and Make a New Folder
                                                                          if (openWin.buttons.whoseTitle.is('Open').first.isEnabled) {
                                                                              // Click "Open"
                                                                              openWin.buttons.whoseTitle.is('Open').first.elementClick();
                                                                      
                                                                              // Wait for 'Open' Window to Appear
                                                                              openWin.elementWaitFor();
                                                                      
                                                                              // Click "Open"
                                                                              openWin.buttons.whoseTitle.is('Open').first.elementClick();
                                                                      
                                                                              // Define Audio Import Options Window
                                                                              const audioImportOptionsWin = sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first;
                                                                      
                                                                              // Wait for Audio Import Options Window to Appear
                                                                              audioImportOptionsWin.elementWaitFor({}, `Audio Import Options Window did not Appear`);
                                                                      
                                                                              // Click "OK"
                                                                              audioImportOptionsWin.buttons.whoseTitle.is("OK").first.elementClick({}, `Could Not Click OK in Audio Import Options Window`);
                                                                      
                                                                              // Wait for Import to Complete
                                                                              sf.ui.proTools.waitForNoModals();
                                                                      
                                                                              // Move Selected Tracks to new Folder
                                                                              moveSelectedTracksToNewFolder();
                                                                          } else {
                                                                              // Click "Cancel"
                                                                              openWin.buttons.whoseTitle.is('Cancel').first.elementClick({}, `Could Not Click Cancel in Audio Import Options Window`);
                                                                      
                                                                              // Wait For Window to Disappear
                                                                              openWin.elementWaitFor({ waitType: "Disappear" });
                                                                      
                                                                              // Make a New Folder Track
                                                                              makeNewFolderTrack();
                                                                      
                                                                              log(`No Audio in ${path}`);
                                                                          }
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function bankToTrackNamed(trackName) {
                                                                          // Refresh Cache
                                                                          sf.ui.proTools.mainWindow.invalidate();
                                                                      
                                                                          // Select Track By Name
                                                                          sf.ui.proTools.trackSelectByName({
                                                                              names: [trackName],
                                                                              deselectOthers: true
                                                                          }, `Could Not Select Track Named '${trackName}'`);
                                                                      
                                                                          // Scroll to Selected Track
                                                                          sf.ui.proTools.selectedTrack.trackScrollToView({},
                                                                              `Could Not Scroll Selected Track into View`
                                                                          );
                                                                      
                                                                          // Bank Track
                                                                          sf.ui.proTools.selectedTrack.titleButton.mouseClickElement({
                                                                              isControl: true,
                                                                              isShift: true,
                                                                              relativePosition: { x: 5, y: 5 }
                                                                          }, `Could Not Click Title Button of Track Named '${trackName}'`);
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function renameSelectedFolder(newName) {
                                                                          // Refresh Cache
                                                                          sf.ui.proTools.mainWindow.invalidate();
                                                                      
                                                                          // Rename Selected Folder Track to Corresponding Finder Folder Name
                                                                          sf.ui.proTools.selectedTrack.trackRename({ newName: newName, },
                                                                              `Could Not Rename Selected Track to '${newName}'`
                                                                          );
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function moveSelectedFolderToParentFolder(folderName) {
                                                                          // Refresh Cache
                                                                          sf.ui.proTools.mainWindow.invalidate();
                                                                      
                                                                          // Define Selected Tracks Title Button
                                                                          const titleButton = sf.ui.proTools.selectedTrack.titleButton;
                                                                      
                                                                          const titleButtonFrame = titleButton.frame;
                                                                      
                                                                          titleButton.popupMenuSelect({
                                                                              isRightClick: true,
                                                                              relativePosition: {
                                                                                  x: titleButtonFrame.w / 2, // Center of button's x axis
                                                                                  y: titleButtonFrame.h / 2, // Center of button's y axis
                                                                              },
                                                                              menuSelector: items => items.filter((mi) => {
                                                                                  return mi.path[mi.path.length - 1].endsWith(folderName);
                                                                              })[0],
                                                                          }, `Could Not Move Folder to: ${folderName}`);
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function importAudioFrom(path) {
                                                                          let splitPathArray = path.split('/');
                                                                      
                                                                          // Get Main Folder Name
                                                                          let mainFolderName = splitPathArray[splitPathArray.length - 2];
                                                                      
                                                                          // Import Audio
                                                                          importAudio(path);
                                                                      
                                                                          // Bank "Folder 1" track
                                                                          bankToTrackNamed('Folder 1');
                                                                      
                                                                          // Rename the "Folder 1" track
                                                                          renameSelectedFolder(mainFolderName);
                                                                      
                                                                          //Deselect All Tracks
                                                                          sf.ui.proTools.trackDeselectAll();
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function importAudioForEach({ paths }) {
                                                                          paths.forEach(path => {
                                                                              let splitPathArray = path.split('/');
                                                                              // Get the Parent folder name (second last folder name from path)
                                                                              let parentFolderName = splitPathArray[splitPathArray.length - 2];
                                                                              // Get the Sub folder name (last folder name from path)
                                                                              let subFolderName = splitPathArray[splitPathArray.length - 1];
                                                                      
                                                                              // Import Audio
                                                                              importAudio(path);
                                                                      
                                                                              // Bank "Folder 1" track
                                                                              bankToTrackNamed('Folder 1');
                                                                      
                                                                              // Rename the "Folder 1" track
                                                                              renameSelectedFolder(subFolderName);
                                                                      
                                                                              // Get the Parent folder track
                                                                              const parentFolderTrack = sf.ui.proTools.trackGetByName({
                                                                                  name: parentFolderName
                                                                              }).track;
                                                                      
                                                                              // If parent track exists move selected tracks to the parent folder
                                                                              if (parentFolderTrack !== null && parentFolderTrack) {
                                                                                  moveSelectedFolderToParentFolder(parentFolderName);
                                                                              }
                                                                      
                                                                              //Deselect All Tracks
                                                                              sf.ui.proTools.trackDeselectAll();
                                                                          });
                                                                      }
                                                                      
                                                                      ////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                      
                                                                      function main() {
                                                                          // Get the selcted finder folder path
                                                                          let selectedFinderFolderPath = sf.ui.finder.selectedPaths[0];
                                                                      
                                                                          // Activate Pro Tools and Refresh Cache
                                                                          sf.ui.proTools.appActivateMainWindow({}, `Could Not Find Pro Tools Main Window`);
                                                                          sf.ui.proTools.mainWindow.invalidate();
                                                                      
                                                                          // Resize Track View
                                                                          resizeTrackListView('Increase');
                                                                      
                                                                          const directoryPaths = getDirectoryPaths(selectedFinderFolderPath);
                                                                      
                                                                          const wav = checkForWAVE(selectedFinderFolderPath);
                                                                      
                                                                          const mp3 = checkForMP3(selectedFinderFolderPath);
                                                                      
                                                                          // Import Audio From Selected Folder if it Exists
                                                                          if (wav || mp3 !== null) {
                                                                              importAudioFrom(selectedFinderFolderPath);
                                                                          }
                                                                      
                                                                          // Import Audio From Each Directory Path
                                                                          importAudioForEach({ paths: directoryPaths });
                                                                      
                                                                          // Resize Track View
                                                                          resizeTrackListView('Decrease');
                                                                      }
                                                                      
                                                                      main();
                                                                      
                                                                      1. Kitch Membery @Kitch2023-08-28 02:31:45.389Z

                                                                        Nice one Nathan. I'll check it out in the next couple of days. :-)

                                                                        If you have an updated folder structure that you are testing, with MP3's / missing files etc. that would be great.

                                                                        1. Nathan Salefski @nathansalefski
                                                                            2023-08-28 02:38:02.090Z

                                                                            Absolutely I'll upload to dropbox shortly

                                                                            1. In reply toKitch:
                                                                              Nathan Salefski @nathansalefski
                                                                                2023-08-28 03:50:59.603Z2023-08-28 04:03:18.821Z

                                                                                Quick update, to deal with folders containing audio that are inside of blank folders, I had to add the following:

                                                                                try {
                                                                                        // Click "Copy" or "Convert"
                                                                                        if (openWin.buttons.whoseTitle.is("Copy ->").first.exists && openWin.buttons.whoseTitle.is("Copy ->").first.isEnabled) {
                                                                                            openWin.buttons.whoseTitle.is("Copy ->").first.elementClick({},
                                                                                                `Could Not Click "Copy ->" in Import Audio Window`
                                                                                            );
                                                                                        } else if (openWin.buttons.whoseTitle.is("Convert ->").first.exists && openWin.buttons.whoseTitle.is("Convert ->").first.isEnabled) {
                                                                                            openWin.buttons.whoseTitle.is("Convert ->").first.elementClick({},
                                                                                                `Could Not Click "Convert ->" in Import Audio Window`
                                                                                            );
                                                                                        }
                                                                                    } catch (err) {
                                                                                        return
                                                                                }
                                                                                

                                                                                The above code is updated

                                                                                1. In reply toKitch:
                                                                                  Nathan Salefski @nathansalefski
                                                                                    2023-08-28 04:02:51.820Z
                                                      • In reply tonathansalefski:
                                                        Kitch Membery @Kitch2023-08-25 19:28:42.196Z

                                                        For future reference, looseMatch only works on the last element in the menu path and matches based on what the element "startsWith".

                                                        Recently Christian added documentation to macro methods/actions and properties that you can read by hovering over the method or property name, which comes in super handy.

                                                        This is what appears when hovering over the menuClick method.

                                                        And this is what appears when hovering over the looseMatch property

                                                        1. Nathan Salefski @nathansalefski
                                                            2023-08-25 22:49:01.989Z

                                                            Ah I see awesome thanks Kitch!