How to use looseMatch in Popup Menu
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],});
}
Linked from:
- Nathan Salefski @nathansalefski
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; } }
- 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}`);
Nathan Salefski @nathansalefski
Currently tried and received this error:
"Couldn't get count of attribute 'AXChildren' of element with title '', role '': kAXErrorInvalidUIElement"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}`);
Nathan Salefski @nathansalefski
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
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" });
Nathan Salefski @nathansalefski
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(); }
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 afolderName
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.
Nathan Salefski @nathansalefski
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 secondfunction moveToFolder()
is within the largerfunction moveToParentFolder()
and is the code from post 9 you suggested I try. Thefunction moveToParentFolder()
only runs if there's a track named the same as the pathways parent folderKitch 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!
Nathan Salefski @nathansalefski
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
Ok great this works! Tired it in every way imaginable How to use looseMatch in Popup Menu #post-9
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 :-)
Nathan Salefski @nathansalefski
Thanks man
- In reply toKitch⬆:
Nathan Salefski @nathansalefski
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) });
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.
Nathan Salefski @nathansalefski
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
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.
- In reply toKitch⬆:
Nathan Salefski @nathansalefski
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();
Kitch Membery @Kitch2023-08-28 00:29:03.335Z
Great progress! So glad our chat helped :-)
- 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
toeditWindowMenuItem
as its value is a menu item, not a path. - Remove the
editWindowPosition
variable as it is redundant. TheeditWindowFrame
contains {x,y,h,w} values so there is no need to have theeditWindowPosition
variable to get the edit window's {x,y} values. - Restructured the
trackListResizePointX
andtrackListResizePointX
into an object namedtrackListResizePoint
with key-value pairs for x and y. - Make the
originalMousePosition
variable into aconst
rather than usinglet
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();
Nathan Salefski @nathansalefski
Awesome great point about the frame. Looks great except you missed changing
editWindowMenuPath
toeditWindowMenuItem
in Lines 15 and 18. Makes sense to changetrackListMenuPath
totrackListMenuItem
in Lines 32 and 35 as well
- Change the variable name for
- In reply tonathansalefski⬆:
Kitch Membery @Kitch2023-08-27 21:15:56.926Z
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.
Nathan Salefski @nathansalefski
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 pathKitch 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.Nathan Salefski @nathansalefski
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 themoveSelectedTracksToNewFolder();
functionality into theif (openWin.buttons.whoseTitle.is('Open').first.isEnabled)
statement. A new function,makeNewFolderTrack();
was added to theelse {}
part of theif (openWin.buttons.whoseTitle.is('Open').first.isEnabled)
statement. These changes ensure that both folder with and without audio can be treated the same by thebankToTrackNamed('Folder 1');
the proceedsfunction 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 theresizeTrackListView()
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();
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.
Nathan Salefski @nathansalefski
Absolutely I'll upload to dropbox shortly
- In reply toKitch⬆:
Nathan Salefski @nathansalefski
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
- In reply toKitch⬆:
Nathan Salefski @nathansalefski
- I've added a
- 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
propertyNathan Salefski @nathansalefski
Ah I see awesome thanks Kitch!