Hi Community,
is there a more elegant way to get the name of the selected clip from the clip list? I know, I can get the clip name from the rename window, but this won't be an option for my usecase.
The code below does the job, but is pretty slow and outputs very unhandy strings like "{"title":"Selected. Audio Clip\n\"test PT Text TOols_01\" ","role":"AXStaticText","fullRole":"AXStaticText"}" with "test PT Text TOols_01" being the clip name.
var i = 1
var y = -1
for (i = 0; i < 16; i++) {
var test = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first.children.whoseRole.is("AXRow").whoseValue.is('').allItems[i].children.whoseRole.is("AXCell").allItems[1].children.whoseRole.is("AXStaticText").whoseTitle.contains('Selected').exists
if (test === true ){break ;}
//log(i, test)
//log ("y",y)
}
var y = i;
var selectedClip = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first.children.whoseRole.is("AXRow").whoseValue.is('').allItems[y].children.whoseRole.is("AXCell").allItems[1].children.whoseRole.is("AXStaticText").whoseTitle.contains('Selected').first
log(selectedClip)
Any suggestions?
Cheers from Berlin
Linked from:
- Raphael Sepulveda @raphaelsepulveda2021-01-19 22:11:24.469Z
Hey Benjamin!
This should do it!
function getSelectedClipNamesFromClipList() { const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first; // Get all selected clips const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row => row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. ')); // Extract clip names const clipNames = selectedClips.map(c => c.split('"')[1]); return clipNames }; const selectedClip = getSelectedClipNamesFromClipList()[0]; log(selectedClip)
Benjamin Hörbe @Benjamin_Horbe
It works like a charm!
Thanks a lot!
- BIn reply toBenjamin_Horbe⬆:Brian Mullany @Brian_Mullany
Heya @raphaelsepulveda , this no longer works in PT 2024.10.
Something around the clipsTable is returning nothing. Any chance something in the backend has changed and needs to be updated here?
The log of selectedClip returns
undefined
.
The log of clipNames returns[]
Any help?
tying to log clipsTable bombs SoundFlow out with the following error:
!! Command Error: test 2 [user:cl32uwy7y00010b10mqt1wp9o:cm3fu6a0q0000bo108nt9ysy7]:
Error: Couldn't get item #0 as the array length was 0 - sf.ui.app('com.avid.ProTools')..tables.whoseTitle.is('CLIPS').first (AxElementArrayIndexedItem)
(test 2 line 6)Raphael Sepulveda @raphaelsepulveda2024-11-13 18:13:26.353Z2025-02-04 17:53:45.594Z
Hey @Brian_Mullany, nowadays I would opt for a different approach for this.
Updated Feb 4th, 2025 — Fades are now removed by default (Thanks Chris Shaw!)
/** @param {{ includeFades?: boolean }} [args] */ function getSelectedClipInfo({ includeFades = false } = {}) { const selectionInTime = Number( sf.app.proTools.getTimelineSelection().inTime ); const selectionOutTime = Number( sf.app.proTools.getTimelineSelection().outTime ); const fullySelectedClips = sf.app.proTools.getSelectedClipInfo().clips .reduce((clips, clip) => { if (!includeFades) { if (clip.clipName.startsWith("(fade") || clip.clipName === "(cross fade)") { return clips; } } const clipStartTime = Number(clip.startTime); const clipEndTime = Number(clip.endTime) - 1; const isClipFullySelected = clipStartTime >= selectionInTime && clipEndTime < selectionOutTime; if (isClipFullySelected) { // Remove any extensions from clipName (.L, .R...) const clipName = clip.clipName.replace(/\.\w+$/, ""); // Filter repeated clips if (clips.some(clip => clip.clipName === clipName)) return clips; clips.push({ clipName, trackName: clip.trackName, startTime: clipStartTime, endTime: clipEndTime }); } return clips; }, []); const names = fullySelectedClips.map(clip => clip.clipName); return { clips: fullySelectedClips, names }; } const selectedClipNames = getSelectedClipInfo().names; log(selectedClipNames);
This script does the following:
- Gets clip info through the PT SDK, which is more robust than scraping the UI.
- Fixes an issue with the original SDK command where adjacent clips would be listed as selected.
- Removes multichannel duplicates (i.e. stereo files would be listed as two different files).
- BBrian Mullany @Brian_Mullany
You’re amazing thank you.
I’ll try tomorrow morning and let you know :)
Appreciate the super fast help
- BBrian Mullany @Brian_Mullany
Unfortunately it doesn't work :(
It returns the stereo pair information (.L and .R) when I need it to just return the clip name in the edit window as a single line string.
14.11.2024 10:48:35.20 [Backend]: [LOG] [
"Reference Track_01.L",
"Reference Track_01.R"
]It should just return
Reference Track_01
in this example
:)
edit
I've frankenstined something together that works on stereo clips, but it is deeply inelegant because I'm a complete noob. And it wouldn't work on Mono Clips that don't append the .L or .R
const selectedClipFull = getSelectedClipNames().names[0]; let selectedClip = selectedClipFull.slice(0, -2); log(selectedClip)
- BBrandon Jiaconia @Brandon_Jiaconia
I use something similar to get rid of the .L .R in clips names. The cool thing about Raphaels script is it returns the names of multiple clips. I've been using this for only one selected clip. I'm also a noob so I'm sure there is a better way to go about it.
sf.ui.proTools.appActivateMainWindow(); const selectedClipInfo = sf.app.proTools.getSelectedClipInfo().clips; const firstSelectedClipName = selectedClipInfo[0].clipName.replace(/\.[LR]$/, ""); log(firstSelectedClipName);
Raphael Sepulveda @raphaelsepulveda2024-11-14 16:56:55.762Z
Hey @Brian_Mullany, @Brandon_Jiaconia,
I've updated the script above to take care of this.
Give it another whirl!
- In reply toraphaelsepulveda⬆:
Chris Shaw @Chris_Shaw2024-11-22 21:33:46.100Z2024-11-22 21:39:53.019Z
This is great!
The only issue is that it lists fades as clips so some additional filtering is needed if you only want clips. You can just add this to the code:const clipsAndFadesInfo = getSelectedClipInfo() const clipsOnlyInfo = { "clips": clipsAndFadesInfo.clips .filter(c => !c.clipName.startsWith("(fade") && c.clipName !== "(cross fade)"), "names": clipsAndFadesInfo.names.filter(n => !n.startsWith("(fade") && n == "(cross fade)") } log(clipsOnlyInfo)
Chris Shaw @Chris_Shaw2024-11-22 21:40:37.832Z
Oops! Forgot to check for cross fades as well.
I've updated the code above.Raphael Sepulveda @raphaelsepulveda2024-11-23 04:14:47.337Z
Teamwork makes the dream work. Thanks @Chris_Shaw! 🙏🏼
- BIn reply toBenjamin_Horbe⬆:Brian Mullany @Brian_Mullany
Hey Team, I'm struggling with this to just get the clip name out as a string.
Running Raphael's script I get
04.02.2025 13:28:02.49 <info> [Backend]: [LOG] [ "(fade in)", "AMBRain_Rain Drops on Plastic Pool Tarp 01_tonic_48khz", "(fade out)" ]
Then adding Chris's Filter I get:
04.02.2025 13:29:08.11 <info> [Backend]: [LOG] { "clips": [ { "clipName": "AMBRain_Rain Drops on Plastic Pool Tarp 01_tonic_48khz", "trackName": "Mono", "startTime": 2983936, "endTime": 35831807 } ], "names": []
All I would love to have is the part AMBRain_Rain Drops on Plastic Pool Tarp 01_tonic_48khz as an output so I can copy it to my clipboard in my other script. Please help! I've tried a million little things but this is so beyond me
Raphael Sepulveda @raphaelsepulveda2025-02-04 17:57:39.686Z
Hey @Brian_Mullany, I just updated my script above incorporating Chris' method of removing fades, that now allows us to easily get the first selected clip name like so:
const selectedClipNames = getSelectedClipInfo().names; const firstSelectedClipName = selectedClipNames[0];
- BBrian Mullany @Brian_Mullany
Thanks! Unfortunately it's not quite working.
It outputs
[ "AMBRain_Rain Drops on Plastic Pool Tarp 01_tonic_48khz" ]
When it should output:
AMBRain_Rain Drops on Plastic Pool Tarp 01_tonic_48khz
Without ][, line breaks, and "". Any ideas? :)
Raphael Sepulveda @raphaelsepulveda2025-02-06 21:41:46.372Z
@Brian_Mullany, here's a quick walkthrough on how to get it working correctly 👇🏼
- BBrian Mullany @Brian_Mullany
Oh I see! I needed that extra bit of code. Sorry I thought it was included :) thanks so much for the video walkthrough as well. Really appreciate it! Thanks!
Raphael Sepulveda @raphaelsepulveda2025-02-06 21:46:29.793Z
No problem! Glad it's all sorted 🙌🏼