I guess you'll have to do that with the "Get Selection" action and then do JavaScript magic.
(The solution has a bonus to extend the automation of a selection by 1 sec.)
Linked from:
- Kitch Membery @Kitch2020-07-24 20:54:24.237Z
Hi Danny,
Can you explain your full workflow? As there may be a better way to achieve what you are after. The more detail the better. :-)
Rock on!
- In reply toDanny_van_Spreuwel⬆:Danny @Danny_van_Spreuwel
I have a selection. Most of the time this selection is made by double clicking a clip. To write automation with a bit of slack before and after the selection I extend the selection and then write the automation.
Kitch Membery @Kitch2020-07-24 22:25:49.004Z
I see.. One more quick question before I answer... Is your main counter set to "Mins:sec"?
- In reply toDanny_van_Spreuwel⬆:
Kitch Membery @Kitch2020-07-24 22:31:31.046Z
If your "Main Counter" is in Mins:Secs mode then this should do the trick;
function extendSelection() { const originalSelection = sf.ui.proTools.selectionGet(); const counterValue = sf.ui.proTools.mainWindow.counterDisplay.mainCounter.value.invalidate().value; let clipStartPoint = originalSelection.selectionStart; let clipEndtPoint = originalSelection.selectionEnd; function timeAdjust(selectionTime) { let startTime = { mins: selectionTime.split(':')[0], secs: selectionTime.split(':')[1].split('.')[0], ms: selectionTime.split('.')[1], } return { start: startTime.mins + ':' + (Number(startTime.secs) - 1) + '.' + startTime.ms, end: startTime.mins + ':' + (Number(startTime.secs) + 1) + '.' + startTime.ms, } } sf.ui.proTools.selectionSet({ selectionStart: timeAdjust(clipStartPoint).start, selectionEnd: timeAdjust(clipEndtPoint).end, }); } extendSelection();
Dustin Harris @Dustin_Harris
Ohh that is lovely. .split(“:”)[x] is so much nicer than a bunch of .slice(x,y). I’ll be updating a bunch of scripts in the morning :)
- In reply toKitch⬆:
Danny @Danny_van_Spreuwel
Wow. Thank you for this script. My main counter is set to TC. Does that make the calculation more complicated? I can image that subtracting 1 sec of a TC 01:00:00:00 would be a challenge.
Kitch Membery @Kitch2020-07-25 08:51:47.161Z
Yes and I think the same thing might occur in my script above. I did not think of that scenario. I may need a few days to think about it. Sorry bout that Danny.
Danny @Danny_van_Spreuwel
No need for sorry. You already made a fantastic first draft in a zippy.
Maybe we need to use Pro Tools to do the time calculation. Meaning that we might need to skip the JavaScript and use keyboard keys to enter the selection fields. I thought it would be more safer to dive into JavaScript instead of the key simulations.
What I found, and also reported to the SoundFlow company, is that I think Pro Tools changed the way of working of the calculation method in the selection fields. The default "select between macros" action isn't working properly anymore in PT 2020.5. When entering a timecode in the selection field ("/") and use "+ 2 0 0 / " it doesn't automatically calculates anymore. You need to "enter" first and then go to the next field with "/". Unfortunately after the "enter" command the cursor exits the selection fields.
Andrew Scheps @Andrew_Scheps
I have a feeling the better way to do this is check the session's sample rate and then you can easily add 1 second's worth of samples to either side of the selection no matter what time format you like to display. And if you always work at one sample rate then you can just set a constant and don't have to open the session setup window to look.
Kitch Membery @Kitch2020-07-25 22:06:50.741Z
Good call!
Andrew Scheps @Andrew_Scheps
Something like:
const oneSec = 48000; var selection = sf.ui.proTools.selectionGetInSamples(); sf.ui.proTools.selectionSetInSamples({ selectionStart: Number(selection.selectionStart) - oneSec, selectionEnd: Number(selection.selectionStart) + oneSec });
Kitch Membery @Kitch2020-07-25 22:11:37.701Z
Bam!!!!
- In reply toAndrew_Scheps⬆:
Kitch Membery @Kitch2020-07-25 22:14:51.355Z
Small correction;
The selectioinEnd was calculating from the selectionStart.
const oneSec = 48000; var selection = sf.ui.proTools.selectionGetInSamples(); sf.ui.proTools.selectionSetInSamples({ selectionStart: Number(selection.selectionStart) - oneSec, selectionEnd: Number(selection.selectionEnd) + oneSec });
Andrew Scheps @Andrew_Scheps
Duh, thanks for fixing!
Kitch Membery @Kitch2020-07-25 22:19:26.305Z
Your global thinking solved the riddle!
- In reply toKitch⬆:
Danny @Danny_van_Spreuwel
Kitch and Andrew, this is fantastic. Great work guys. My script of extending the selection and write automation would be something like this:
var selection = sf.ui.proTools.selectionGetInSamples(); sf.keyboard.press({ keys: "shift+slash", }); sf.ui.proTools.selectionSetInSamples({ selectionStart: Number(selection.selectionStart) - oneSec, selectionEnd: Number(selection.selectionEnd) + oneSec }); sf.ui.proTools.menuClick({ menuPath: ["Edit","Automation","Write to All Enabled"], }); sf.keyboard.press({ keys: "shift+slash", });
Danny @Danny_van_Spreuwel
Mmmm, how do you get that fancy code formatting in your post?
Kitch Membery @Kitch2020-07-25 22:32:12.702Z
Check this post regarding formatting.
https://forum.soundflow.org/-1468#post-9
- In reply toDanny_van_Spreuwel⬆:
Kitch Membery @Kitch2020-07-25 22:33:10.523Z
Nice one. What does "Shift+Slash" do?
Danny @Danny_van_Spreuwel
It links and breaks the Timeline and Edit selection.
Kitch Membery @Kitch2020-07-25 22:38:13.022Z
Is it activating or deactivating the the "Link timeline and Edit Selection" in this script?
Danny @Danny_van_Spreuwel
It's deactivating. Actually the shift-slash toggles this mode. In most cases the link is activated. Otherwise you need to check first what the status is of this function.
Kitch Membery @Kitch2020-07-25 22:50:17.668Z2020-07-25 23:01:55.375Z
Gotya! It's best to replace the key press with UI scripting for stability :-)
So... To activate;
const btn = sf.ui.proTools.mainWindow.cursorToolCluster.buttons.whoseTitle.is('Link Timeline and Edit Selection').first; //This will activate the button if (btn.value.invalidate().value !== 'Selected') { btn.elementClick(); }
&
To inactive;
const btn = sf.ui.proTools.mainWindow.cursorToolCluster.buttons.whoseTitle.is('Link Timeline and Edit Selection').first; //This will deactivate the button if (btn.value.invalidate().value === 'Selected') { btn.elementClick(); }
Danny @Danny_van_Spreuwel
It's getting better and better. Here's the version with the UI element:
const oneSec = 48000; const btn = sf.ui.proTools.mainWindow.groups.whoseTitle.is('Cursor Tool Cluster').first.buttons.whoseTitle.is('Link Timeline and Edit Selection').first; var selection = sf.ui.proTools.selectionGetInSamples(); //Deactivate link Timeline and Edit selection if (btn.value.invalidate().value === 'Selected') { btn.elementClick(); } sf.ui.proTools.selectionSetInSamples({ selectionStart: Number(selection.selectionStart) - oneSec, selectionEnd: Number(selection.selectionEnd) + oneSec }); sf.ui.proTools.menuClick({ menuPath: ["Edit","Automation","Write to All Enabled"], }); //Activate link Timeline and Edit selection if (btn.value.invalidate().value !== 'Selected') { btn.elementClick(); }
Kitch Membery @Kitch2020-07-25 23:09:59.879Z
Yes you got it! My most recent post just wraped it in a reusable function :-)
- In reply toDanny_van_Spreuwel⬆:
Kitch Membery @Kitch2020-07-25 23:08:29.288Z
All together it should look like this (I've not tested it though);
function writeToBufferedSelection() { const oneSec = 48000; const btn = sf.ui.proTools.mainWindow.cursorToolCluster.buttons.whoseTitle.is('Link Timeline and Edit Selection').first; const selection = sf.ui.proTools.selectionGetInSamples(); if (btn.value.invalidate().value === 'Selected') { btn.elementClick(); } sf.ui.proTools.selectionSetInSamples({ selectionStart: Number(selection.selectionStart) - oneSec, selectionEnd: Number(selection.selectionEnd) + oneSec }); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Automation", "Write to All Enabled"], }); if (btn.value.invalidate().value !== 'Selected') { btn.elementClick(); } } writeToBufferedSelection();
Danny @Danny_van_Spreuwel
You mean this function can be used in other SoundFlow scripts?
Kitch Membery @Kitch2020-07-25 23:13:54.426Z
Not quite... The function can be called multiple times by using the call ie
writeToBufferedSelection();
but the function code still needs to live within the comand that you are using.Danny @Danny_van_Spreuwel
Aha. Check. I was wondering how to make snippets of reusable codes. Can you call a script within a script?
Kitch Membery @Kitch2020-07-25 23:32:13.469Z
Yes you can do this by using a "Run Command" action from the "Macro Editor" by copying and pasting the "Command ID" you want to use from the Command menu in SoundFlow.
Then by clicking the "Copy as Javascript" ie "..." you can paste the code into the command you want to add it to.
- In reply toKitch⬆:
Dustin Harris @Dustin_Harris
FWIW, I did make a function for adding and subtracting timecode.. I'm sure there is a slicker way to code it, but here it is if it helps anyone:
function timeCodeAddSubtract(time, offset) { //offset is whole number in seconds var hours = time.slice(0, 2); var minutes = time.slice(3, 5); var seconds = time.slice(6, 8); var frames = time.slice(09, 11); seconds = (+seconds + +offset); if (seconds < 0) { minutes = (+minutes - 1); seconds = (60 + seconds); } else if (seconds >= 60) { minutes = (+minutes + 1); seconds = (seconds - 60); } if (minutes < 0) { hours = (hours - 1); minutes = (60 + minutes); } else if (minutes >= 60) { hours = (hours + 1); minutes = (minutes - 60); } seconds = String(seconds); minutes = String(minutes); hours = String(hours); function AddZeros(value) { if (value.length == 1) value = String(`0${value}`); return value; } seconds = AddZeros(seconds); minutes = AddZeros(minutes); hours = AddZeros(hours); var output = (`${hours}:${minutes}:${seconds}:${frames}`); return output; }
Kitch Membery @Kitch2020-07-26 03:16:48.694Z
Great stuff!
Dustin Harris @Dustin_Harris
ostensibly I could turn this:
var hours = time.slice(0, 2); var minutes = time.slice(3, 5); var seconds = time.slice(6, 8); var frames = time.slice(9, 11);
into this?
var hours = time.split(':')[0]; var minutes = time.split(':')[1]; var seconds = time.split(':')[2]; var frames = time.split(':')[3];
(I should check if it throws a ';' in for drop frame though)