Made on a 'hold my beer' challenge for my music editor who might make the jump to Soundflow. Calling all music editors to give it a run and see if it breaks. One button to Spot all your stems ;)
/// Make sure You're in Time Grabber Function \\\
function toggleTimeGrabTool() {
const grabberTool = sf.ui.proTools.mainWindow.groups.whoseTitle.is('Cursor Tool Cluster').first.buttons.whoseTitle.startsWith('Grabber tool').first;
grabberTool.elementClick(); // if there's smart tool selected then it turns it off
grabberTool.popupMenuSelect({
isRightClick: true,
menuPath: ['Time']
});
}
/// Single File Spot to Original \\\
function spotToOriginal() {
/// Define the Spotting Window
const spotWin = sf.ui.proTools.clipSpotDialog
/// Toggle Time Tool
toggleTimeGrabTool();
/// Open Spot Dialog
sf.ui.proTools.clipOpenSpotDialog();
/// Wait for Spot Dialog to Open
spotWin.elementWaitFor();
///Click Original Timestamp Button
spotWin.mouseClickElement({ relativePosition: { "x": 271, "y": 247 },});
///Click OK
spotWin.buttons.whoseTitle.is("OK").first.elementClick();
}
function main() {
/// Saftey Invalidate
sf.ui.proTools.appActivateMainWindow();
sf.ui.proTools.invalidate();
/// Get selected tracks
const originalTracks = sf.ui.proTools.selectedTrackNames;
//Do for each track.
sf.ui.proTools.selectedTracks.trackHeaders.slice().map(track => {
//Select track
track.trackSelect();
//Scroll track into View
track.trackScrollToView();
//Do for each clip on Track
sf.ui.proTools.clipDoForEachSelectedClip({
action: () => {
spotToOriginal();
},
onError: "Continue",
});
});
//Restore previously selected tracks
sf.ui.proTools.trackSelectByName({ names: originalTracks });
};
main();
- Kitch Membery @Kitch2023-07-28 00:07:27.460Z
Awesome, Owen!
What's this line clicking?
spotWin.mouseClickElement({ relativePosition: { "x": 271, "y": 247 }, });
Original Time Stamp?
- OOwen Granich-Young @Owen_Granich_Young
The original timestamp button inside the Spotting pane it didn't seem to trigger on ui when I rolled over it. I"ll update the script with comments now.
Kitch Membery @Kitch2023-07-28 00:16:07.739Z
A few tweaks but top work, Owen!
function selectTimeGrabTool() { const grabberTool = sf.ui.proTools.mainWindow.cursorToolCluster.grabberTool; grabberTool.elementClick(); // if there's smart tool selected then it turns it off grabberTool.popupMenuSelect({ isRightClick: true, menuPath: ['Time'], }); } function spotToOriginal() { const spotWin = sf.ui.proTools.clipSpotDialog; selectTimeGrabTool(); sf.ui.proTools.clipOpenSpotDialog(); spotWin.elementWaitFor(); // Click "Original Time Stamp" spotWin.mouseClickElement({ relativePosition: { "x": 271, "y": 247 }, }); spotWin.buttons.whoseTitle.is("OK").first.elementClick(); spotWin.elementWaitFor({ waitType: "Disappear" }); } function main() { // Activate Pro Tools Main Window sf.ui.proTools.appActivateMainWindow(); // Invalidate Pro Tools main Window sf.ui.proTools.mainWindow.invalidate(); // Get selected tracks const originalTracks = sf.ui.proTools.selectedTrackNames; // Do for each track. sf.ui.proTools.selectedTracks.trackHeaders.slice().map(track => { // Select track track.trackSelect(); // Scroll track into View track.trackScrollToView(); // Do for each clip on Track sf.ui.proTools.clipDoForEachSelectedClip({ action: spotToOriginal, onError: "Continue", }); }); // Restore previously selected tracks sf.ui.proTools.trackSelectByName({ names: originalTracks }); } main();
- VVanessa Garde @Vanessa_Garde
@Kitch , would it be possible to update this script, as it sometimes fails on certain tracks?
Thanks a lot!
Kitch Membery @Kitch2023-10-04 19:09:02.594Z
Work in Progress. But this should work.
function selectTimeGrabTool() { const grabberTool = sf.ui.proTools.mainWindow.cursorToolCluster.grabberTool; grabberTool.elementClick(); // if there's smart tool selected then it turns it off grabberTool.popupMenuSelect({ isRightClick: true, menuPath: ['Time'], }); } function spotToOriginal() { //Get Current Selection const oldSelection = sf.ui.proTools.selectionGetInSamples(); const spotWin = sf.ui.proTools.clipSpotDialog; //selectTimeGrabTool(); //sf.ui.proTools.clipOpenSpotDialog(); const menu = sf.ui.proTools.clipOpenContextMenu().popupMenu; menu.menuClickPopupMenu({ menuPath: ['Spot...'], }); spotWin.elementWaitFor(); // Click "Original Time Stamp" spotWin.mouseClickElement({ relativePosition: { "x": 271, "y": 247 }, }); spotWin.buttons.whoseTitle.is("OK").first.elementClick(); spotWin.elementWaitFor({ waitType: "Disappear" }); //Restore Current Selection sf.ui.proTools.selectionSetInSamples({ selectionStart: oldSelection.selectionStart, selectionEnd: oldSelection.selectionEnd, }); } function main() { // Activate Pro Tools Main Window sf.ui.proTools.appActivateMainWindow(); // Invalidate Pro Tools main Window sf.ui.proTools.mainWindow.invalidate(); // Get selected tracks const selectedTrackNames = sf.ui.proTools.selectedTrackNames; // Do for each track. selectedTrackNames.forEach(name => { // Select track const track = sf.ui.proTools.trackGetByName({ name }).track // Select Track track.trackSelect(); // Scroll track into View track.trackScrollToView(); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); // Do for each clip on Track sf.ui.proTools.clipDoForEachSelectedClip({ action: spotToOriginal, onError: "Continue", }, `There was an error spotting track ${name}`); }); // Restore previously selected tracks sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }); sf.ui.proTools.toolsSelect({ tool: "Smart", }); sf.ui.proTools.editModeSet({ mode: "Slip", }); } main();
- VVanessa Garde @Vanessa_Garde
Thanks for the work on this, @Kitch & @Owen_Granich_Young !!
Just tried the newer version, and I had to do it twice, since some clips were spotted to the wrong timestamp (just to go to 00:00:00:00). Repeating the process took them to the right place... I screencasted, for reference:
Any idea why this might be happening?
Thanks again!!!
Kitch Membery @Kitch2023-10-05 10:27:57.884Z
Hi @Vanessa_Garde,
Looking into this further, there are more issues stopping this above implementation from working.
It looks like the method for spotting does not always display the correct Original Time Stamp, it instead reports it as zero.
const menu = sf.ui.proTools.clipOpenContextMenu().popupMenu; menu.menuClickPopupMenu({ menuPath: ['Spot...'], });
When reverting to using the
sf.ui.proTools.clipOpenSpotDialog()
method, it's important that the clips are zoomed in. So for this, I'm using a zoom memory button to make sure the clips are zoomed in enough.I've also changed some other things so let me know if you have questions about anything else.
Try this out and let me know how it goes for you.
function selectTimeGrabTool() { const grabberTool = sf.ui.proTools.mainWindow.cursorToolCluster.grabberTool; grabberTool.elementClick(); // If there's smart tool selected then it turns it off grabberTool.popupMenuSelect({ isRightClick: true, menuPath: ['Time'], }); } function spotToOriginal() { //Get Current Selection const oldSelection = sf.ui.proTools.selectionGetInSamples(); const clipSpotDialog = sf.ui.proTools.clipSpotDialog; sf.ui.proTools.clipOpenSpotDialog(); clipSpotDialog.elementWaitFor(); if (clipSpotDialog.popupButtons.first.value.value !== "Samples") { clipSpotDialog.popupButtons.first.popupMenuSelect({ menuPath: ["Samples"] }); } const textFields = clipSpotDialog.childrenByRole("AXStaticText").map(e => e.value.value); const originalTimeStamp = clipSpotDialog.childrenByRole("AXStaticText")[textFields.indexOf("Original Time Stamp:") + 1].value.value; sf.ui.proTools.clipSpotDialog.textFields.whoseTitle.is("NumericEntryText").first.elementSetTextFieldWithAreaValue({ useMouseKeyboard: true, value: originalTimeStamp, }); clipSpotDialog.buttons.whoseTitle.is("OK").first.elementClick(); clipSpotDialog.elementWaitFor({ waitForNoElement: true }); //Restore Current Selection sf.ui.proTools.selectionSetInSamples({ selectionStart: oldSelection.selectionStart, selectionEnd: oldSelection.selectionEnd, }); } function main() { // Activate Pro Tools Main Window sf.ui.proTools.appActivateMainWindow(); // Invalidate Pro Tools main Window sf.ui.proTools.mainWindow.invalidate(); selectTimeGrabTool(); sf.ui.proTools.mainWindow.zoomQuadrantCluster.buttons.whoseTitle.is("Zoom Memory 1").first.elementClick(); // Get selected tracks const selectedTrackNames = sf.ui.proTools.selectedTrackNames; // Do for each track. selectedTrackNames.forEach(name => { // Select track const track = sf.ui.proTools.trackGetByName({ name }).track; // Select Track track.trackSelect(); // Scroll track into View track.trackScrollToView(); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "left" }); // Do for each clip on Track sf.ui.proTools.clipDoForEachSelectedClip({ action: spotToOriginal, onError: "Continue", }, `There was an error spotting track ${name}`); }); // Restore previously selected tracks sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }); sf.ui.proTools.toolsSelect({ tool: "Smart", }); sf.ui.proTools.editModeSet({ mode: "Slip", }); } main();
- VVanessa Garde @Vanessa_Garde
Great!! Much better now...!! Thanks @Kitch !!!
I noticed something too:
- If no selection is made (on the timeline, with the cursor in the beginning of the session, for ex.), on the first track, the clip doesn't spot. The rest does tho.
- Including a selection, it does make it work on the first track, as well.
Thank you!
Kitch Membery @Kitch2023-10-05 17:22:22.412Z
Interesting... I assume this is a quirk in the way the
sf.ui.proTools.clipOpenSpotDialog();
works.Try inserting
sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] });
at line 52 to see if that fixes the issue.Rock on!
- VVanessa Garde @Vanessa_Garde
BRAVO!!! Thank you @Kitch !!!
- JJascha Viehl @Jascha_Viehl
@Owen_Granich_Young @Kitch_Membery @Vanessa_Garde
Thanks for posting, refining and debugging the script.
It helped me to align a lot of music cues so far.
And it will be a great resource in the future as the show I'm working on has about 120 cues of music, sometimes delivered in stems.With the last mentioned script here some clips still where spotted to the beginning of the session, because the script clicked "Ok" in the spotting dialog before all of the sample values where entered into the number field "Start".
I inserted a small pause and adapted the script so the Spot Dialog resets to Timecode after all clips are spotted.
function selectTimeGrabTool() { const grabberTool = sf.ui.proTools.mainWindow.cursorToolCluster.grabberTool; grabberTool.elementClick(); // If there's smart tool selected then it turns it off grabberTool.popupMenuSelect({ isRightClick: true, menuPath: ['Time'], }); } function spotToOriginal() { //Get Current Selection const oldSelection = sf.ui.proTools.selectionGetInSamples(); const clipSpotDialog = sf.ui.proTools.clipSpotDialog; sf.ui.proTools.clipOpenSpotDialog(); clipSpotDialog.elementWaitFor(); if (clipSpotDialog.popupButtons.first.value.value !== "Samples") { clipSpotDialog.popupButtons.first.popupMenuSelect({ menuPath: ["Samples"] }); } const textFields = clipSpotDialog.childrenByRole("AXStaticText").map(e => e.value.value); const originalTimeStamp = clipSpotDialog.childrenByRole("AXStaticText")[textFields.indexOf("Original Time Stamp:") + 1].value.value; sf.ui.proTools.clipSpotDialog.textFields.whoseTitle.is("NumericEntryText").first.elementSetTextFieldWithAreaValue({ useMouseKeyboard: true, value: originalTimeStamp, }); // Wait to enable full entry of value (original TimeStamp) sf.wait({ intervalMs: 100, }); clipSpotDialog.buttons.whoseTitle.is("OK").first.elementClick(); clipSpotDialog.elementWaitFor({ waitForNoElement: true }); //Restore Current Selection sf.ui.proTools.selectionSetInSamples({ selectionStart: oldSelection.selectionStart, selectionEnd: oldSelection.selectionEnd, }); } function main() { // Activate Pro Tools Main Window sf.ui.proTools.appActivateMainWindow(); // Invalidate Pro Tools main Window sf.ui.proTools.mainWindow.invalidate(); // Select all in case nothing is selcted sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); selectTimeGrabTool(); sf.ui.proTools.mainWindow.zoomQuadrantCluster.buttons.whoseTitle.is("Zoom Memory 1").first.elementClick(); // Get selected tracks const selectedTrackNames = sf.ui.proTools.selectedTrackNames; // Do for each track. selectedTrackNames.forEach(name => { // Select track const track = sf.ui.proTools.trackGetByName({ name }).track; // Select Track track.trackSelect(); // Scroll track into View track.trackScrollToView(); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "left" }); // Do for each clip on Track sf.ui.proTools.clipDoForEachSelectedClip({ action: spotToOriginal, onError: "Continue", }, `There was an error spotting track ${name}`); }); // Reset Spot Dialog to Time Scale "Timecode" const clipSpotDialog = sf.ui.proTools.clipSpotDialog; sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.ui.proTools.clipOpenSpotDialog(); clipSpotDialog.elementWaitFor(); if (clipSpotDialog.popupButtons.first.value.value !== "Timecode") { clipSpotDialog.popupButtons.first.popupMenuSelect({ menuPath: ["Timecode"] }); } clipSpotDialog.buttons.whoseTitle.is("CANCEL").first.elementClick(); clipSpotDialog.elementWaitFor({ waitForNoElement: true }); // Restore previously selected tracks sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }); sf.ui.proTools.toolsSelect({ tool: "Smart", }); sf.ui.proTools.editModeSet({ mode: "Slip", }); } main();
- JIn reply toOwen_Granich_Young⬆:Judson Crane @Judson_Crane
Hi! excited to come across this as it is always a pain to spot clips when importing mixes to review before a dub. It failed at first on 5 of 6 clips I tried it on, but then I simply moved the clips to somewhere in the timeline besides the top, and it worked (perhaps this was mentioned and I missed it)! brilliant! much thanks!