Hi guys. For my workflow I would need a script that does this.
1__Delete all clips from my session
2_ delete all unused playlists
3_ delete all automations
4 _ delete all memory locations.
I was able to create a script that does step 1.
Step 3 doesn't always work ...
Could I ask for your help?
- samuel henriques @samuel_henriques
samuel henriques @samuel_henriques
Hey @Davide_Docente,
try this:
function selectAllTracks() { const groupsList = sf.ui.proTools.mainWindow.tables.whoseTitle.is("Group List").first; const firstRow = groupsList.childrenByRole("AXRow"); const firstCell = firstRow.first.childrenByRole("AXCell").first.buttons.first; firstCell.elementClick(); } function goToStartOfSession() { sf.ui.proTools.transportEnsureCluster(); const trannsportCluster = sf.ui.proTools.mainWindow.transportViewCluster; const transportButtons = trannsportCluster.groups.whoseTitle.is("Normal Transport Buttons").first; transportButtons.buttons.whoseTitle.is("Return to Zero").first.elementClick(); } function deleteAllAutomation() { sf.ui.proTools.appActivateMainWindow(); selectAllTracks(); goToStartOfSession() sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "shift+tab", fast: true, repetitions: 5 }); sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Clear Special', 'All Automation'] }); } function setWindowView() { sf.ui.proTools.menuClick({ menuPath: ["View", "Other Displays", "Track List"], targetValue: "Enable" }); sf.ui.proTools.menuClick({ menuPath: ["View", "Other Displays", "Clip List"], targetValue: "Enable" }); sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Track List pop-up").first.popupMenuSelect({ menuPath: ["Show All Tracks"], }); function showItems() { function show(item) { sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({ menuPath: ["Show", item], targetValue: "Enable" }); } show("Audio") show("MIDI") show("Video") show("Groups") show("Auto-Created") } showItems() } function deleteAllMemoryLocations() { sf.ui.proTools.memoryLocationsWindow.popupButtons.whoseTitle.is("Memory Locations").first.popupMenuSelect({ menuPath: ['Delete All'] }); } /** * @param {string} trackType - All track types included on trackTypes array */ function deleteUnusedPlaylists(trackType) { // Check if there are any tracks of trackType const trackTypeExists = sf.ui.proTools.visibleTrackHeaders.some(x => x.title.invalidate().value.includes(trackType)) if (trackTypeExists) { // Get name of first track of trackType const firstTrackByTypeName = sf.ui.proTools.visibleTrackHeaders.filter(x => x.title.invalidate().value.includes(trackType))[0].normalizedTrackName // Find track by name const getFirstTrackByTypeName = sf.ui.proTools.trackGetByName({ name: firstTrackByTypeName }).track // Scrool track if needed getFirstTrackByTypeName.trackScrollToView() // Delete unused menu getFirstTrackByTypeName.popupButtons.whoseTitle.is("Playlist selector").first.popupMenuSelect({ menuPath: ["Delete Unused..."] }); // Delete unused window const deleteUnusedWin = sf.ui.proTools.windows.whoseTitle.is("Delete Unused Playlists").first if (deleteUnusedWin.exists) { const deleteUnusedWinTable = deleteUnusedWin.tables.first.children.whoseRole.is("AXRow") // Select all unused playlists deleteUnusedWinTable.map(x => x.children.first.children.whoseRole.is("AXStaticText").first.elementClick()) // Click delete Btn deleteUnusedWin.buttons.whoseTitle.is("Delete").first.elementClick(); }; }; }; function clearAllFromCLipList() { // Select all clips in clip list sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is("Clip List").first.popupMenuSelect({ menuPath: ["Select", "All"], targetValue: "Enable", useWildcards: false, }); // Clear menu from clip list sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is("Clip List").first.popupMenuSelect({ menuPath: ["Clear..."], }); // click Remove on confirmation dialog if (sf.ui.proTools.confirmationDialog.invalidate().buttons.whoseTitle.is('Remove').first.exists) { sf.keyboard.modifiers({ isOption: true }) sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('Remove').first.elementClick(); } } function main() { sf.ui.proTools.appActivateMainWindow(); // show Track list, Clip list and All tracks setWindowView() deleteAllAutomation(); // Clear all items from clip list clearAllFromCLipList() /// delete memory locations sf.ui.proTools.memoryLocationsEnsureWindow({ action: deleteAllMemoryLocations, restoreWindowOpenState: true }); // delete unused playlists, needs to be done on all track types const trackTypes = [ "Video Track", "MIDI Track", "Inst Track", "Audio Track" ] trackTypes.forEach(deleteUnusedPlaylists) } main()
samuel henriques @samuel_henriques
I forgot the delete markers bit and found something else to add. I'll add Raphael's code and try to fix it today.
- In reply toD_av_3⬆:Dav3 @D_av_3
I probably do something wrong ... but when I start this script nothing happens ...
samuel henriques @samuel_henriques
Just updated above, with Raphael' bit as well.
Can you check is there are any lines underlined with red? would mean something when wrong with copy/paste
anyway try again, added some stuff that might be important
let me know how it goes
- In reply toD_av_3⬆:Dav3 @D_av_3
You are right. I was probably wrong to copy and paste ... I apologize.
Everything works perfectly.
... thank you so muchsamuel henriques @samuel_henriques
Awesome. Let me know if you find anything to be improved.
- In reply toD_av_3⬆:Dav3 @D_av_3
if I can still take advantage of your super knowledge .... then.... I also ask you if something can also be done for point 2
samuel henriques @samuel_henriques
I'll see. I don't use playlists. Wouldn't clearing all clips from session delete them as well?
samuel henriques @samuel_henriques
I mean delete all from clip list.
Dav3 @D_av_3
Delete their content. and this works perfectly. However, the empty playlists remain.
samuel henriques @samuel_henriques
Got it. By the way, i'll add the clip list view all audio, video, groups and auto created just in case.
samuel henriques @samuel_henriques
UPDATED: show all types of items in clip list and clear unused playlists.
let me know how it goes.
samuel henriques @samuel_henriques
UPDATED: fixed error if track type or unused playlist doesn't exist
samuel henriques @samuel_henriques
This looks cool, but out of curiosity, is this better than import session data without anything ?
Dav3 @D_av_3
Your observation is correct ... I used to use templates ... but I always try to improve something .. and in this way everything that I change remains in the session
- In reply tosamuel_henriques⬆:
Dav3 @D_av_3
Hello guys. I just upgraded to protools 2021.6. On my mac there are now 2 versions installed (for safety I also have 2020.12). When I launch this script (thank you again for your support) protools 2021.6 gives me this error and I have to do a forced shutdown of the program.
Assertion in "/Users/autobild/gitlab ci/PRE/release/2021/r2/Pro Tools/NewFieLds/SMgr/Auto PlayList.cpp", line 2323
samuel henriques @samuel_henriques
Hey Davide,
I won't be able to check this out today.
Could you double check if you are using the latest SoundFlow? It is needed for pro tools 2021.6.
Go to your area on the site, and under downloads, you can see the latest version.Chris Shaw @Chris_Shaw2021-08-06 01:14:43.521Z
I ran this script and everything seems to work except deleting unused playlists.
- In reply tosamuel_henriques⬆:
samuel henriques @samuel_henriques
I couldn't reproduce any error, I'm on pt 2021.6 as well.
try replacing the
deleteUnusedPlaylists()
function, I cleaned it and made it more readable, and added anìnvalidade()
when it's reading the trackHeaders. It should' fix any error you have though, so comment thetry{
line and the} catch (e) { }
line, you will get errors on the track types that don't have playlists, witch is normal( that's what the try - catch is doing here) but if you get the same error you were getting , let me know what it is, so I can figure it out.function deleteUnusedPlaylists(trackType) { try { const firstTrackByTypeName = sf.ui.proTools.invalidate().visibleTrackHeaders.filter(x => x.title.value.includes(trackType))[0].normalizedTrackName const getFirstTrackByTypeName = sf.ui.proTools.trackGetByName({ name: firstTrackByTypeName }).track getFirstTrackByTypeName.trackScrollToView() sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is("Playlist selector").first.popupMenuSelect({ menuPath: ["Delete Unused..."], }); const deleteUnusedWin = sf.ui.proTools.windows.whoseTitle.is("Delete Unused Playlists").first.elementWaitFor({}, 'Delete unused playlists window did\'t open').element const deleteUnusedWinTable = deleteUnusedWin.tables.first.children.whoseRole.is("AXRow") deleteUnusedWinTable.map(x => x.children.first.children.whoseRole.is("AXStaticText").first.elementClick()) deleteUnusedWin.buttons.whoseTitle.is("Delete").first.elementClick(); } catch (e) { } }
samuel henriques @samuel_henriques
Here's a version of the same function but, instead of a general try-catch, I made it check for existent trackType, and proceed if any exists. And if there are no unused playlists for that track type, continue without error.
Let me know how it goes.
/** * @param {string} trackType - All track types included on trackTypes array */ function deleteUnusedPlaylists(trackType) { // Check if there are any tracks of trackType const trackTypeExists = sf.ui.proTools.visibleTrackHeaders.some(x => x.title.invalidate().value.includes(trackType)) if (trackTypeExists) { // Get name of first track of trackType const firstTrackByTypeName = sf.ui.proTools.visibleTrackHeaders.filter(x => x.title.invalidate().value.includes(trackType))[0].normalizedTrackName // Find track by name const getFirstTrackByTypeName = sf.ui.proTools.trackGetByName({ name: firstTrackByTypeName }).track // Scrool track if needed getFirstTrackByTypeName.trackScrollToView() // Delete unused menu getFirstTrackByTypeName.popupButtons.whoseTitle.is("Playlist selector").first.popupMenuSelect({ menuPath: ["Delete Unused..."] }); // Delete unused window const deleteUnusedWin = sf.ui.proTools.windows.whoseTitle.is("Delete Unused Playlists").first if (deleteUnusedWin.exists) { const deleteUnusedWinTable = deleteUnusedWin.tables.first.children.whoseRole.is("AXRow") // Select all unused playlists deleteUnusedWinTable.map(x => x.children.first.children.whoseRole.is("AXStaticText").first.elementClick()) // Click delete Btn deleteUnusedWin.buttons.whoseTitle.is("Delete").first.elementClick(); }; }; }; ``
Chris Shaw @Chris_Shaw2021-08-07 20:33:20.395Z
Works great.
The only change I'd make is to add"Inst Track" to
trackTypes in the main script:const trackTypes = [ "Video Track", "MIDI Track", "Audio Track", "Inst Track" ]
samuel henriques @samuel_henriques
Cool Chris, thank you.
I'm not sure now, but I think the reason I didn't leave the Inst track, was the midi playlists are the same on the midi and instrument tracks, so deleting one would be enough. Can't remember for sure though.Chris Shaw @Chris_Shaw2021-08-07 21:43:55.940Z
It depends whether or not the MIDI clips were created on an Instr track or a MIDI track.
Also I rarely Use MIDI tracks. I always use Inst tracks. Adding this track type doesn't make the script take any longer so , why not? :)samuel henriques @samuel_henriques
You are absolutely right. Just updated the original post with the new function and 'Inst Track'.