Hi all,
I'm new to Javascript, so sorry if this is a Javascript 101 question.
I need to enter a variables text, or number value (eventually a loop from an array) individually from a script I have created into the "Edit Selection Length" , in the Edit Window and also into the "Rename Clip" Popup.
i.e.
When setting Var x=0.01.100
Click ui interface element then "Edit Selection Length" - Paste or type in Var x (0.01.100)
An example script would be great. Thanks
Kitch
- Christian Scheuer @chrscheuer2019-09-07 23:21:39.837Z
No need to apologize :) We're here to help with any question big or small!
The code to set the selection length to for example 3 seconds when in Timecode is as follows:
sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.selectionSet({ selectionLength: '00:00:03:00' });
If you had a variable
x
set to00:00:03:00
, it would look like this:var x = "00:00:03:00"; sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.selectionSet({ selectionLength: x });
Christian Scheuer @chrscheuer2019-09-07 23:22:38.384Z
Feel free to ask more specifically as well - ie. what is the workflow you're building here?
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-07 23:25:47.612Z
Wonderful I'll try that out thank you Christian.
Great to meet you the other night. :-) I'm really enjoying Soundflow so far!Christian Scheuer @chrscheuer2019-09-08 20:34:21.869Z
Happy to hear it! Great meeting you too :)
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-07 23:43:20.096Z
This script works great in Timecode mode but not in Mins:Secs mode.
Is there a standard way to enter Hours. Minutes, Seconds and Miliseconds in Mins:Secs mode?
Christian Scheuer @chrscheuer2019-09-08 20:33:24.952Z
Oh - good catch I see that it isn't working as expected in min:secs mode. That's a bug, we'll look into it.
What you can do for now is to use the selectionSetTimecode action instead, which will quickly switch to Timecode while setting the length and then switch back to whatever Time base you had before.
sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.selectionSetTimecode({ selectionLength: '00:00:03:00' });
Kitch Membery @Kitch2019-09-08 21:08:45.280Z
Thanks for that Christian. Let me know when you get a chance to fix it. Till then I have a work around.
By pressing the "/" key 3 times allows me to get to the the "Edit Selection Length" then I can enter the "0.00.000" Mins:Secs format.
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-08 23:11:40.412Z
Once that bug is fixed and I can enter Mins:Secs" into the "Edit Selection Length" this looped array script is gonna work a treat;
Let me know if you can see any improvements.
//This script will cut up room tone lengths from a piece of clean room tone that is longer than the largest array value. //Set Variable Array for room tone Clip lengths. var myList = [ '00:00:01:00', '00:00:02:00', '00:00:03:00', '00:00:04:00', '00:00:05:00', ]; //Activate Protools Main Window sf.ui.proTools.appActivateMainWindow(); //Create loop for the Array for (var i = 0; i < myList.length; i++) { //Enter Array variable into "Edit Selection Length" sf.ui.proTools.selectionSet({ selectionLength: myList[i] }); //Press the Menu Item for renaming clips. sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); //Wait for the "Name" window to appear: sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor(); //Enter "_RT " and Variable into "Name" window text field. sf.ui.proTools.windows.whoseTitle.is('Name').first.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: "_RT " + myList[i], }); //Press Enter sf.ui.proTools.windows.whoseTitle.is('Name').first.buttons.whoseTitle.is('OK').first.elementClick(); }
Room Tone Slicer 480.mov (468.41 kB)
Christian Scheuer @chrscheuer2019-09-08 23:20:36.076Z
Very very nice @Kitch!
Great job.There is room for a few improvements.
2 improvements that I didn't tell you about before but that will make the script slightly more stable.
And a few improvements to code quality/readability which I'll offer just for the Javascript lesson there is in it.First things first.
It would make sense after you press the OK (nit: it's not Enter, but an actual button-press on the OK button) you wait for the window to disappear, just like we wait for the window to appear in the first case. This is not super important for an action like this which we can assume would always be fast, but if Pro Tools for some reason was a little slow to close the window, the selectionSet command would fail on your next iteration.To wait for the "Name" window to disappear, add this at the end of your loop:
//Wait for "Name" window to disappear sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitForNoElement: true });
The 2nd functional improvement to the script is to add this line of code at the start of your loop:
sf.engine.checkForCancellation();
This line will check to make sure that the user didn't ask for us to cancel the command (for example by pressing Ctrl+Shift+Escape with default SoundFlow triggers enabled).
It's always a good idea to include this at the beginning of long-running loops.Now your entire script looks like this:
//This script will cut up room tone lengths from a piece of clean room tone that is longer than the largest array value. //Set Variable Array for room tone Clip lengths. var myList = [ '00:00:01:00', '00:00:02:00', '00:00:03:00', '00:00:04:00', '00:00:05:00', ]; //Activate Protools Main Window sf.ui.proTools.appActivateMainWindow(); //Create loop for the Array for (var i = 0; i < myList.length; i++) { sf.engine.checkForCancellation(); //Enter Array variable into "Edit Selection Length" sf.ui.proTools.selectionSet({ selectionLength: myList[i] }); //Press the Menu Item for renaming clips. sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); //Wait for the "Name" window to appear: sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor(); //Enter "_RT " and Variable into "Name" window text field. sf.ui.proTools.windows.whoseTitle.is('Name').first.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: "_RT " + myList[i], }); //Click OK sf.ui.proTools.windows.whoseTitle.is('Name').first.buttons.whoseTitle.is('OK').first.elementClick(); //Wait for "Name" window to disappear sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitForNoElement: true }); }
I'll add the mechanical (non-functional) improvement suggestions in my next post.
- In reply tochrscheuer⬆:
Christian Scheuer @chrscheuer2019-09-08 23:31:50.805Z
For the mechanical improvements:
- Rename
myList
to something more descriptive, for exampleloopLengths
. This is a general rule - choosing good names is half of coding since you're essentially distilling the concept, ie. what does this variable describe. - Instead of referring to
myList[i]
multiple times in your loop, assignmyList[i]
to a variable (myItem
, orloopLength
) in the beginning of the loop and refer to that. This improves readability and makes it easier to make other changes later. - Lastly, since we're referring to the "Name" window multiple times in the last half of the loop, we can do what's known as "Common Subexpression Elimination" or variable harvesting. Basically, assign
sf.ui.proTools.windows.whoseTitle.is('Name').first
to a variable that you can namenameWindow
and then use that variable to access the window.
I'm posting a little gif here of the process. Note since this is a purely mechanical change, there's no functional change to the script, it's only about improving the code quality.
Christian Scheuer @chrscheuer2019-09-08 23:32:36.015Z
Here's the script with my mechanical changes:
//This script will cut up room tone lengths from a piece of clean room tone that is longer than the largest array value. //Set Variable Array for room tone Clip lengths. var loopLengths = [ '00:00:01:00', '00:00:02:00', '00:00:03:00', '00:00:04:00', '00:00:05:00', ]; //Activate Protools Main Window sf.ui.proTools.appActivateMainWindow(); //Create loop for the Array for (var i = 0; i < loopLengths.length; i++) { var loopLength = loopLengths[i]; //Check if user cancelled our command. This will stop the script if the user cancelled sf.engine.checkForCancellation(); //Enter Array variable into "Edit Selection Length" sf.ui.proTools.selectionSet({ selectionLength: loopLength }); //Press the Menu Item for renaming clips. sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); //Define "Name" window variable var nameWindow = sf.ui.proTools.windows.whoseTitle.is('Name').first; //Wait for the "Name" window to appear: nameWindow.elementWaitFor(); //Enter "_RT " and Variable into "Name" window text field. nameWindow.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: "_RT " + loopLength, }); //Click OK nameWindow.buttons.whoseTitle.is('OK').first.elementClick(); //Wait for "Name" window to disappear nameWindow.elementWaitFor({ waitForNoElement: true }); }
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-08 23:38:55.788Z
Awesome! I shall implement all of these mechanical improvements.
Kitch Membery @Kitch2019-09-09 00:04:09.691Z
It seems that the var loopLength = loopLengths[i]; mechanical changes broke the script. As it is breaking down at line 24.
Christian Scheuer @chrscheuer2019-09-09 00:07:35.158Z
I don't think that's the source of the error. The script works fine here (as long as I'm in Timecode mode before running the script).
If you want it to work in min:secs mode you'll need to change theselectionSet
toselectionSetTimecode
Kitch Membery @Kitch2019-09-09 00:09:39.192Z
As soon as I posted my last post, I realized I had changed it back to Min:Secs.... Sorry for that.
Christian Scheuer @chrscheuer2019-09-09 00:15:23.306Z
No problem :)
Christian Scheuer @chrscheuer2019-09-09 00:18:12.905Z
For this case, actually let's make another change to the script.
All actions in SoundFlow take a 2nd parameter where you can add the error message it should show if the action fails.
The 1st parameter is the{...}
stuff, so after the closing curly bracket, you can add the error message.
So change these lines:sf.ui.proTools.selectionSet({ selectionLength: loopLength });
to:
sf.ui.proTools.selectionSet({ selectionLength: loopLength }, "Could not set selection. Are you in Timecode mode?");
And if you're in min:secs mode or the selection set fails for any other reason, it will show the error message "Could not set selection. Are you in Timecode mode?"
Kitch Membery @Kitch2019-09-09 00:25:20.919Z
You are too good mate!!
Christian Scheuer @chrscheuer2019-09-09 00:32:16.940Z
:)
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-09 20:50:32.196Z
How do I switch the Counter display from Timecode to Min:Secs, Bars:Beats, Samples, Feet+Frames etc?
Christian Scheuer @chrscheuer2019-09-10 03:08:21.412Z
For example like this:
sf.ui.proTools.mainCounterSetValue({ targetValue: 'Timecode' }); sf.ui.proTools.mainCounterSetValue({ targetValue: 'Min:Secs' }); //Etc..
The string needs to correspond to the View->Main Counter->... menu items.
Kitch Membery @Kitch2019-09-10 03:51:42.134Z
Perfect!... Here is my updated code with an "If then else" to change the name of the last piece of room tone to "_Fill". I have also added a hack to get the Min:Secs entry into the "Edit Loop Selection" (It seems that it wanted an extra "0." before it would accept the Minutes, Seconds, Miliseconds.
//This script will cut up room tone lengths from a piece of clean room tone that is longer than the largest array value. //Set Variable Array for room tone Clip lengths. var loopLengths = [ '0.00.400', '0.00.500', '0.00.600', '0.00.700', '0.00.800', '0.00.900', '0.01.000', '0.01.100', '0.01.200', '0.01.300', '0.01.400', '0.01.500', '0.01.600', '0.01.700', '0.01.800', '0.01.900', '0.02.000', '0.02.500', '0.04.000', '0.04.000', ]; //Create variable for Min:Secs input into Edit Selection Length field. (Till Bug is fixed) var timehack = '0.'; //Activate Protools Main Window sf.ui.proTools.appActivateMainWindow(); //Set main Counter to Min:Secs view sf.ui.proTools.mainCounterSetValue({ targetValue: 'Min:Secs' }); //Create loop for the Array for (var i = 0; i < loopLengths.length; i++) { var loopLength = loopLengths[i]; //Check if user cancelled our command. This will stop the script if the user cancelled sf.engine.checkForCancellation(); //Select the Edit Selection Length Field sf.ui.proTools.mainWindow.groups.whoseTitle.is('Counter Display Cluster').first.textFields.whoseTitle.is('Edit Selection Length').first.elementClick({}); //Enter Array variable into "Edit sf.keyboard.type({ text: timehack + loopLength }); //Press return to make Edit Selection Length accept loopLength sf.keyboard.press({ keys: "return" }); //Enter Array variable into "Edit Selection Length" (Disabled this step till bug is fixed) //sf.ui.proTools.selectionSet({ // selectionLength: loopLength //}); //Press the Menu Item for renaming clips. sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); //Define "Name" window variable var nameWindow = sf.ui.proTools.windows.whoseTitle.is('Name').first; //Wait for the "Name" window to appear: nameWindow.elementWaitFor(); //Lables the last array item as "_Fill" if (i == loopLengths.length - 1) { //Enter "_RT " and Variable into "Name" window text field. nameWindow.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: '_Fill', }); //Click OK nameWindow.buttons.whoseTitle.is('OK').first.elementClick(); //Wait for "Name" window to disappear nameWindow.elementWaitFor({ waitForNoElement: true }); } else { //Enter "_RT " and Variable into "Name" window text field. nameWindow.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: "_RT " + loopLength, }); //Click OK nameWindow.buttons.whoseTitle.is('OK').first.elementClick(); //Wait for "Name" window to disappear nameWindow.elementWaitFor({ waitForNoElement: true }); } }
My next step is to get the room tone and fill to export and reimport as whole audio files.
Thanks a million for your help Christian :-)
Christian Scheuer @chrscheuer2019-09-10 03:56:18.868Z
Sounds great, @Kitch!
You should definitely publish this as part of a package some time :)Kitch Membery @Kitch2019-09-10 04:09:06.665Z
Absolutly!
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-13 03:24:13.266Z
Christian, Sorry to bother you... I just tried to run this script today and It could not get past Line 93 (it was working yesterday and I dont remember changing anything). Would you be able to to take a look at it. I must have accidently changed somthing before I saved it.
Rock on
Kitch//This script will cut up room tone lengths from a piece of clean room tone that is longer than the largest array value. //Set Variable Array for room tone Clip lengths. var loopLengths = [ '0.00.400', '0.00.500', '0.00.600', '0.00.700', '0.00.800', '0.00.900', '0.01.000', '0.01.100', '0.01.200', '0.01.300', '0.01.400', '0.01.500', '0.01.600', '0.01.700', '0.01.800', '0.01.900', '0.02.000', '0.02.500', '0.04.000', '0.04.000', ]; //Create variable for Min:Secs input into Edit Selection Length field. (Till Bug is fixed) var timehack = '0.'; //Activate Protools Main Window sf.ui.proTools.appActivateMainWindow(); //Set main Counter to Min:Secs view. sf.ui.proTools.mainCounterSetValue({ targetValue: 'Min:Secs' }); //Create loop for the Array for (var i = 0; i < loopLengths.length; i++) { var loopLength = loopLengths[i]; //Check if user cancelled our command. This will stop the script if the user cancelled sf.engine.checkForCancellation(); //Select the Edit Selection Length Field sf.ui.proTools.mainWindow.groups.whoseTitle.is('Counter Display Cluster').first.textFields.whoseTitle.is('Edit Selection Length').first.elementClick({}); //Enter Array variable into "Edit sf.keyboard.type({ text: timehack + loopLength }); //Press return to make Edit Selection Length accept loopLength sf.keyboard.press({ keys: "return" }); //Enter Array variable into "Edit Selection Length" (Disabled this step till bug is fixed) //sf.ui.proTools.selectionSet({ // selectionLength: loopLength //}); //Press the Menu Item for renaming clips. sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); //Define "Name" window variable var nameWindow = sf.ui.proTools.windows.whoseTitle.is('Name').first; //Wait for the "Name" window to appear: nameWindow.elementWaitFor({ waitForNoElement: true }); //Lables the last array item as "_Fill" if (i == loopLengths.length - 1) { //Enter "_RT " and Variable into "Name" window text field. nameWindow.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: '_Fill', }); //Click OK nameWindow.buttons.whoseTitle.is('OK').first.elementClick(); //Wait for "Name" window to disappear nameWindow.elementWaitFor({ waitForNoElement: true }); } else { //Enter "_RT " and Variable into "Name" window text field. nameWindow.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: "_RT " + loopLength, }); //Click OK nameWindow.buttons.whoseTitle.is('OK').first.elementClick(); //Wait for "Name" window to disappear nameWindow.elementWaitFor({ waitForNoElement: true }); } }
- Rename
- In reply tochrscheuer⬆:
Kitch Membery @Kitch2019-09-08 00:38:22.610Z
Also, How do you enter a Variables Text or Value into the menu Item Clip>Capture... "Rename" popup. Thanks again.
Kitch Membery @Kitch2019-09-08 09:36:46.893Z2019-09-08 20:34:49.212Z
I figured out how to get the variable into the text field (using sf.keyboard.type function).... Unless there is a better way?
sf.ui.proTools.appActivateMainWindow(); var x = "00:00:03:00"; sf.ui.proTools.selectionSet({ selectionLength: x }); sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); sf.keyboard.type({ text: x });
Christian Scheuer @chrscheuer2019-09-08 20:35:56.893Z
Interesting! I don't know what the Capture dialog does.. How do I bring it up - mine is greyed out?
Kitch Membery @Kitch2019-09-08 21:03:26.992Z
It brings up the Rename popup. It is grey until you have to have a selection of audio selected. :-)
Christian Scheuer @chrscheuer2019-09-08 21:11:37.726Z
I see. Ok so the best way to set the value of that text field is like this:
sf.ui.proTools.windows.whoseTitle.is('Name').first.groups.whoseTitle.is('Name').first.textFields.first.elementSetTextFieldWithAreaValue({ value: "test 1.2.3", });
This is how I got that code:
--
But first you'll need to wait for the window to appear. (In a macro this would be the "Wait for UI Element" action.
In code this all looks like this:sf.ui.proTools.menuClick({ menuPath: ["Clip", "Capture..."], }); //Wait for the window to appear: sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor(); //Now set the Name to the value of the x variable sf.ui.proTools.windows.whoseTitle.is('Name').first.groups.whoseTitle.is('Name').first.textFields.first.elementSetTextFieldWithAreaValue({ value: x, }); //Click OK sf.ui.proTools.windows.whoseTitle.is('Name').first.buttons.whoseTitle.is('OK').first.elementClick();
Kitch Membery @Kitch2019-09-08 22:27:42.231Z
Out of interest... How do I make my coding show up as a script, and not as plain text in the forum?
Christian Scheuer @chrscheuer2019-09-08 22:28:55.837Z
You use 3 backticks on a line by itself, before and after the code, like this:
```
You can edit your posts to see how I did it :)Kitch Membery @Kitch2019-09-08 22:29:50.596Z
Thanks Legend!
- Progress
- Christian Scheuer @chrscheuer2019-09-18 06:02:27.986Z
Confirmed: Setting selection in min:secs mode is going to work in 3.0.1.
- Kitch Membery @Kitch2019-09-18 06:05:14.055Zreplies tochrscheuer⬆:
You are a legend! Thank you Christian :-)
- Kitch Membery @Kitch2019-09-21 23:47:44.917Zreplies tochrscheuer⬆:
Hi Christian,
I've tried the following code in Soundflow 3.0.1 and setting the Edit Selection Length in Min:Secs is still not working.
var clipDuration = "0.04.400"; //Activate Pro Tools Main Window sf.ui.proTools.appActivateMainWindow(); //Set main Counter to Min:Secs view. sf.ui.proTools.mainCounterSetValue({ targetValue: 'Min:Secs' }); //Set the Edit Selection Length to clipDuration. sf.ui.proTools.selectionSet({ selectionLength: clipDuration });
When you have a chance, could you take a look at my code just in case I've made an error.
Rock on
Kitch - Christian Scheuer @chrscheuer2019-09-22 02:54:24.642Zreplies toKitch⬆:
Hi @Kitch
You had an error in the format, it needs to be m:ss.fff (ie. colon instead of dot):
If you fix your first line to this, it should work:
var clipDuration = "0:04.400";