Hello friends! Since the Pro Tools operations windows have now been consolidated into a single floating window, what is the best way to script them from SoundFlow? When the floating panels were separate, I was able to make scripts that could:
Change the Quantize resolution
Change the input resolution
Toggle triplet on/off
Activate/Deactivate Input Quantizing
Now I'm not sure how to make the single floating panel triangles open and close and then of course navigate the data fields, input data and press the apply button.
Thanks You!
John Costello
- Mitch Willard @Mitch_Willard
maybe the best way would be to open and close each item as you need it.
So for example to open/close Quantize, you could use:
///Open Quantize sf.ui.proTools.focusedWindow.buttons.whoseTitle.is("Collapser button: Collapsed - Quantize").first.elementClick();
and to Close:
///Close Quantize sf.ui.proTools.focusedWindow.buttons.whoseTitle.is("Collapser button: Expanded - Quantize").first.elementClick();
and is you wanted to toggle it open and close, you can use:
///Toggle sf.ui.proTools.focusedWindow.buttons.whoseTitle.endsWith("- Quantize").first.elementClick();
Cheers,
Mitch
Mitch Willard @Mitch_Willard
actually this will work even better for you to open each:
sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Quantize...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Change Velocity...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Change Duration...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Transpose...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Select/Split Notes...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Quantize...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Input Quantize...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Step Input...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Restore Performance...').elementClick(); sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Flatten Performance...').elementClick();
for filling out the data you want and applying, you can just use the
.elementClick()
John Costello @John_Costello
Your scripts work great controlling the operation elements. Thank you! I was able to make a successful script for
Toggle triplet on/off
Activate/Deactivate Input QuantizingI'm not the best coder but I was able to make a SoundFlow Macro where I could "Pick" the button and then convert that to a script and insert it between two toggle scripts to achieve my goal.
To change Quantise resolutions I'm running into a wall with the "Open and select item in Popup menu." The SoundFlow error is "Menu not found".
I've tried to change the UI element drop downs to other options but still not working.
Thank you so much for helping me!
JC3
Mitch Willard @Mitch_Willard
Here is a code that will allow you to set all your settings in the Quantize field.
Just fill in what you want to
'Enable'
or'Disable'
and add the value.//////Change statuses to 'Enable' or 'Disable' ///// set values to numeric values /// Note On const noteOnStatus = 'Enable' /// Note Off const noteOffStatus = 'Enable' ///Preserve note duration const preserveNoteDuration = 'Enable' ////what to quantize popup const whatToQuantizePopUp = 'Elastic Audio Events' ///Quantize Grid const quantizeGridValue = "1/8 note" ///Tuplet const tupletStatus = 'Disable' const tupletValue = 20 const tupletInTimeValue = 5 ///Swing const swingStatus = 'Disable' const swingValue = 100 ///Strength const strengthStatus = 'Disable' const strengthValue = 100 ///Offset const offsetStatus = 'Disable' const offsetValue = 0 ///Randomize const randomizeStatus = 'Disable' const randomizeValue = 1 ///Include within const includeWithinStatus = 'Disable' const includeWithinValue = 100 ///Include within const excludeWithinStatus = 'Disable' const excludeWithinValue = 10 function quantizeSettings() { function setNumericValue(field, dBValue) { //Set value of number field if (field.value.invalidate().value !== dBValue.toString()) { field.elementClick(); //Remove contents of Number field if it is not empty if (field.value.invalidate().value !== '') { sf.keyboard.press({ keys: 'delete' }); } //Type number into number field sf.keyboard.type({ text: dBValue.toString() }); sf.keyboard.press({ keys: 'return' }); }; }; const numericValues = sf.ui.proTools.windows.first.textFields; const checkBox = sf.ui.proTools.windows.first.checkBoxes; if (!sf.ui.proTools.windows.first.children.whoseRole.is("AXStaticText").whoseValue.is("Quantize").first.exists) { sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Quantize...').elementClick(); }; for (var i = 0; i < 16; i++) { if (sf.ui.proTools.windows.first.buttons.allItems[i].title.value.startsWith('Collapser button: Expanded')) { sf.ui.proTools.windows.first.buttons.allItems[i].elementClick(); }; }; let quantizeMenuOpen = (sf.ui.proTools.windows.first.buttons.first.title.value === "Collapser button: Expanded - Quantize") if (!quantizeMenuOpen) { sf.ui.proTools.windows.first.buttons.whoseTitle.is("Collapser button: Collapsed - Quantize").first.elementClick(); }; checkBox.whoseTitle.is("Note On").first.checkboxSet({ targetValue: noteOnStatus }); checkBox.whoseTitle.is("Note Off").first.checkboxSet({ targetValue: noteOffStatus }); checkBox.whoseTitle.is("Preserve note duration").first.checkboxSet({ targetValue: preserveNoteDuration }); if (sf.ui.proTools.windows.first.popupButtons.first.isEnabled) { sf.ui.proTools.windows.first.popupButtons.first.popupMenuSelect({ menuPath: [whatToQuantizePopUp], }); }; if (sf.ui.proTools.windows.first.popupButtons.allItems[1].value.value != quantizeGridValue) sf.ui.proTools.windows.first.popupButtons.allItems[1].popupMenuSelect({ menuPath: [quantizeGridValue] }); ///Tuplet checkBox.whoseTitle.is("Tuplet:").first.checkboxSet({ targetValue: tupletStatus }); if (checkBox.whoseTitle.is("Tuplet:").first.isCheckBoxChecked) { ///Tuplet Value setNumericValue(numericValues.allItems[0], tupletValue); ///inTime Value setNumericValue(numericValues.allItems[1], tupletInTimeValue); }; ///Swing checkBox.whoseTitle.is("Swing:").first.checkboxSet({ targetValue: swingStatus }); if (checkBox.whoseTitle.is("Swing:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[2], swingValue); ///Strength checkBox.whoseTitle.is("Strength:").first.checkboxSet({ targetValue: strengthStatus }); if (checkBox.whoseTitle.is("Strength:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[3], strengthValue); ///Offset checkBox.whoseTitle.is("Offset:").first.checkboxSet({ targetValue: offsetStatus }); if (checkBox.whoseTitle.is("Offset:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[4], offsetValue); ///Randomize checkBox.whoseTitle.is("Randomize:").first.checkboxSet({ targetValue: randomizeStatus }); if (checkBox.whoseTitle.is("Randomize:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[5], randomizeValue); ///Include Within checkBox.whoseTitle.is("Include within:").first.checkboxSet({ targetValue: includeWithinStatus }); if (checkBox.whoseTitle.is("Include within:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[6], includeWithinValue); ///Exclude Within checkBox.whoseTitle.is("Exclude within:").first.checkboxSet({ targetValue: excludeWithinStatus }); if (checkBox.whoseTitle.is("Exclude within:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[7], excludeWithinValue); ///Apply sf.ui.proTools.windows.first.buttons.whoseTitle.is("Apply").allItems[4].elementClick(); }; quantizeSettings();
John Costello @John_Costello
This is an absolutely amazing looking script! I've been testing it and I get "Could not open pop-up" SoundFlow error when I change quatizeGridValue . Could this be because of the note symbol before the grid value? Also When I change noteOnStatus to Disable there is no error but nothing changes. Thank you for helping me Mitch!
JC3
Mitch Willard @Mitch_Willard
Sorry it’s not working for you. It’s working for me in regards to the popup, I’ll take a look when I’m in front of the computer a bit later.
I’ll have a look at the noteOnStatus might be cause it’s not available? Is it greyed out?John Costello @John_Costello
I gave the track some midi data so it had something to work with but I'm still getting weird behavior from your beautiful script. When midi notes are selected the noteOnStatus is not greyed out. Experimenting so far is not yielding success for me.
I'm on BigSur 2PT 023.9.0
I'm thankful that it works for you. Thank you for putting your personal time into this script, maybe there is another way to crack this nut someday.
Possibly the SoundFlow gods could make us a definitive template for these processes at some point.
Cheers!
JC3
Mitch Willard @Mitch_Willard
Hey @John_Costello
give this a try, it should work now for the popup menu.
as for the noteOnStatus, it's working for me, but have added something to hopefully help it as it may have been skipping over it.
Thanks
Mitch
//////Change statuses to 'Enable' or 'Disable' ///// set values to numeric values /// Note On const noteOnStatus = 'Disable' /// Note Off const noteOffStatus = 'Disable' ///Preserve note duration const preserveNoteDuration = 'Enable' ////what to quantize popup const whatToQuantizePopUp = 'Elastic Audio Events' ///Quantize Grid const quantizeGridValue = "1/8 note" ///Tuplet const tupletStatus = 'Disable' const tupletValue = 20 const tupletInTimeValue = 5 ///Swing const swingStatus = 'Disable' const swingValue = 100 ///Strength const strengthStatus = 'Disable' const strengthValue = 100 ///Offset const offsetStatus = 'Disable' const offsetValue = 0 ///Randomize const randomizeStatus = 'Disable' const randomizeValue = 1 ///Include within const includeWithinStatus = 'Disable' const includeWithinValue = 100 ///Include within const excludeWithinStatus = 'Disable' const excludeWithinValue = 10 function quantizeSettings() { function setNumericValue(field, dBValue) { //Set value of number field if (field.value.invalidate().value !== dBValue.toString()) { field.elementClick(); //Remove contents of Number field if it is not empty if (field.value.invalidate().value !== '') { sf.keyboard.press({ keys: 'delete' }); } //Type number into number field sf.keyboard.type({ text: dBValue.toString() }); sf.keyboard.press({ keys: 'return' }); }; }; const numericValues = sf.ui.proTools.windows.first.textFields; const checkBox = sf.ui.proTools.windows.first.checkBoxes; if (!sf.ui.proTools.windows.first.children.whoseRole.is("AXStaticText").whoseValue.is("Quantize").first.exists) { sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Quantize...').elementClick(); }; sf.ui.proTools.windows.first.elementWaitFor({ waitType: 'Appear', timeout: 1000, pollingInterval: 50 }); for (var i = 0; i < 16; i++) { if (sf.ui.proTools.windows.first.buttons.allItems[i].title.value.startsWith('Collapser button: Expanded')) { sf.ui.proTools.windows.first.buttons.allItems[i].elementClick(); }; }; let quantizeMenuOpen = (sf.ui.proTools.windows.first.buttons.first.title.value === "Collapser button: Expanded - Quantize") if (!quantizeMenuOpen) { sf.ui.proTools.windows.first.buttons.whoseTitle.is("Collapser button: Collapsed - Quantize").first.elementClick(); }; checkBox.whoseTitle.is("Note On").first.checkboxSet({ targetValue: noteOnStatus }); checkBox.whoseTitle.is("Note Off").first.checkboxSet({ targetValue: noteOffStatus }); checkBox.whoseTitle.is("Preserve note duration").first.checkboxSet({ targetValue: preserveNoteDuration }); if (sf.ui.proTools.windows.first.popupButtons.first.isEnabled) { sf.ui.proTools.windows.first.popupButtons.first.popupMenuSelect({ menuPath: [whatToQuantizePopUp], }); }; if (sf.ui.proTools.windows.first.popupButtons.allItems[1].value.value != quantizeGridValue) sf.ui.proTools.windows.first.popupButtons.allItems[1].popupMenuSelect({ menuSelector: items => items.filter(i => i.path[0].includes(quantizeGridValue))[0] }); ///Tuplet checkBox.whoseTitle.is("Tuplet:").first.checkboxSet({ targetValue: tupletStatus }); if (checkBox.whoseTitle.is("Tuplet:").first.isCheckBoxChecked) { ///Tuplet Value setNumericValue(numericValues.allItems[0], tupletValue); ///inTime Value setNumericValue(numericValues.allItems[1], tupletInTimeValue); }; ///Swing checkBox.whoseTitle.is("Swing:").first.checkboxSet({ targetValue: swingStatus }); if (checkBox.whoseTitle.is("Swing:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[2], swingValue); ///Strength checkBox.whoseTitle.is("Strength:").first.checkboxSet({ targetValue: strengthStatus }); if (checkBox.whoseTitle.is("Strength:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[3], strengthValue); ///Offset checkBox.whoseTitle.is("Offset:").first.checkboxSet({ targetValue: offsetStatus }); if (checkBox.whoseTitle.is("Offset:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[4], offsetValue); ///Randomize checkBox.whoseTitle.is("Randomize:").first.checkboxSet({ targetValue: randomizeStatus }); if (checkBox.whoseTitle.is("Randomize:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[5], randomizeValue); ///Include Within checkBox.whoseTitle.is("Include within:").first.checkboxSet({ targetValue: includeWithinStatus }); if (checkBox.whoseTitle.is("Include within:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[6], includeWithinValue); ///Exclude Within checkBox.whoseTitle.is("Exclude within:").first.checkboxSet({ targetValue: excludeWithinStatus }); if (checkBox.whoseTitle.is("Exclude within:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[7], excludeWithinValue); sf.ui.proTools.windows.first.buttons.whoseTitle.is("Apply").allItems[4].elementClick(); }; quantizeSettings();
John Costello @John_Costello
Hiya @Mitch_Willard
Winner winner fried chicken dinner!!!!!! Super sexy script!!!! Works nice and keeps the floating window open, which is my preference! Thank you so much!
The final thing I'm trying to do is drive the input quantize window in the same manner. So I went to your super sexy script and changed all the "Quantize" references to say "Input Quantize" and that didn't work. Possibly because there is no "apply" button, only an enable check box.
I write full songs for film and tv. But like a crazy person, I record my midi parts into PT instead of a proper midi daw. This saves me time getting to the mix/master stage. I'm a players player so I rarely need to use the other functions.
You are the best Mitch! Thank you!
JC3
Mitch Willard @Mitch_Willard
hey @John_Costello
Excellent! glad it's working for you.
Give me a sec and I'll do the Input Quantize for you.
- In reply toJohn_Costello⬆:
Mitch Willard @Mitch_Willard
Here you go mate, for Input Quantize.
//////Change statuses to 'Enable' or 'Disable' ///// set values to numeric values /// Note On const noteOnStatus = 'Disable' /// Note Off const noteOffStatus = 'Disable' ///Preserve note duration const preserveNoteDuration = 'Enable' ////what to quantize popup const whatToQuantizePopUp = 'Elastic Audio Events' ///Quantize Grid const quantizeGridValue = "1/8 note" ///Tuplet const tupletStatus = 'Enable' const tupletValue = 20 const tupletInTimeValue = 5 ///Swing const swingStatus = 'Enable' const swingValue = 100 ///Strength const strengthStatus = 'Enable' const strengthValue = 100 ///Offset const offsetStatus = 'Enable' const offsetValue = 0 ///Randomize const randomizeStatus = 'Enable' const randomizeValue = 1 ///Include within const includeWithinStatus = 'Enable' const includeWithinValue = 100 ///Include within const excludeWithinStatus = 'Enable' const excludeWithinValue = 10 function quantizeSettings() { function setNumericValue(field, dBValue) { //Set value of number field if (field.value.invalidate().value !== dBValue.toString()) { field.elementClick(); //Remove contents of Number field if it is not empty if (field.value.invalidate().value !== '') { sf.keyboard.press({ keys: 'delete' }); } //Type number into number field sf.keyboard.type({ text: dBValue.toString() }); sf.keyboard.press({ keys: 'return' }); }; }; const numericValues = sf.ui.proTools.windows.first.textFields; const checkBox = sf.ui.proTools.windows.first.checkBoxes; if (!sf.ui.proTools.windows.first.children.whoseRole.is("AXStaticText").whoseValue.is("Quantize").first.exists) { sf.ui.proTools.getMenuItem('Event', 'Event Operations', 'Input Quantize...').elementClick(); }; sf.ui.proTools.windows.first.elementWaitFor({ waitType: 'Appear', timeout: 1000, pollingInterval: 50 }); for (var i = 0; i < 16; i++) { if (sf.ui.proTools.windows.first.buttons.allItems[i].title.value.startsWith('Collapser button: Expanded')) { sf.ui.proTools.windows.first.buttons.allItems[i].elementClick(); }; }; let quantizeMenuOpen = (sf.ui.proTools.windows.first.buttons.first.title.value === "Collapser button: Expanded - Input Quantize") if (!quantizeMenuOpen) { sf.ui.proTools.windows.first.buttons.whoseTitle.is("Collapser button: Collapsed - Input Quantize").first.elementClick(); }; checkBox.whoseTitle.is("Note On").first.checkboxSet({ targetValue: noteOnStatus }); checkBox.whoseTitle.is("Note Off").first.checkboxSet({ targetValue: noteOffStatus }); checkBox.whoseTitle.is("Preserve note duration").first.checkboxSet({ targetValue: preserveNoteDuration }); if (sf.ui.proTools.windows.first.popupButtons.first.isEnabled) { sf.ui.proTools.windows.first.popupButtons.first.popupMenuSelect({ menuPath: [whatToQuantizePopUp], }); }; if (sf.ui.proTools.windows.first.popupButtons.allItems[1].value.value != quantizeGridValue) sf.ui.proTools.windows.first.popupButtons.allItems[1].popupMenuSelect({ menuSelector: items => items.filter(i => i.path[0].includes(quantizeGridValue))[0] }); ///Tuplet checkBox.whoseTitle.is("Tuplet:").first.checkboxSet({ targetValue: tupletStatus }); if (checkBox.whoseTitle.is("Tuplet:").first.isCheckBoxChecked) { ///Tuplet Value setNumericValue(numericValues.allItems[0], tupletValue); ///inTime Value setNumericValue(numericValues.allItems[1], tupletInTimeValue); }; ///Swing checkBox.whoseTitle.is("Swing:").first.checkboxSet({ targetValue: swingStatus }); if (checkBox.whoseTitle.is("Swing:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[2], swingValue); ///Strength checkBox.whoseTitle.is("Strength:").first.checkboxSet({ targetValue: strengthStatus }); if (checkBox.whoseTitle.is("Strength:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[3], strengthValue); ///Offset checkBox.whoseTitle.is("Offset:").first.checkboxSet({ targetValue: offsetStatus }); if (checkBox.whoseTitle.is("Offset:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[4], offsetValue); ///Randomize checkBox.whoseTitle.is("Randomize:").first.checkboxSet({ targetValue: randomizeStatus }); if (checkBox.whoseTitle.is("Randomize:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[5], randomizeValue); ///Include Within checkBox.whoseTitle.is("Include within:").first.checkboxSet({ targetValue: includeWithinStatus }); if (checkBox.whoseTitle.is("Include within:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[6], includeWithinValue); ///Exclude Within checkBox.whoseTitle.is("Exclude within:").first.checkboxSet({ targetValue: excludeWithinStatus }); if (checkBox.whoseTitle.is("Exclude within:").first.isCheckBoxChecked) setNumericValue(numericValues.allItems[7], excludeWithinValue); sf.ui.proTools.windows.first.checkBoxes.whoseTitle.is("Enable").allItems[1].checkboxSet({ targetValue: 'Enable' }) }; quantizeSettings();
John Costello @John_Costello