No internet connection
  1. Home
  2. How to

Copy first clip name of selected tracks, to track name

By samuel henriques @samuel_henriques
    2021-09-09 21:32:43.002Z2021-09-10 07:14:07.383Z

    Hello @Chris_Shaw and @Matt_Friedman,
    here's my take on copy the name of the first clip on selected tracks to the track name.

    It should dismiss repeated track names by appending the index of the selected track at the end of name
    Works if within track selection there are tracks without any clip
    Select a range of tracks or pick tracks.

    Let me know how it's working.

    function selectFirstClip() {
    
        const returntoZero = () => sf.ui.proTools.mainWindow.groups.allItems[5].groups.first.buttons.whoseTitle.is("Return to Zero").first.elementClick();
        const selectionHasClip = () => sf.ui.proTools.getMenuItem("Clip", "Edit Lock/Unlock").isEnabled
    
        returntoZero()
    
        // Need a maximum of 3x shift+tab.  if there is a fade on first clip, need 3x tab
        // Need to start with shift+tab in case a clip starts at 0 on the timeline
        sf.keyboard.press({ keys: "shift+tab" });
        if (!selectionHasClip()) { sf.keyboard.press({ keys: "shift+tab" }) }
        if (!selectionHasClip()) { sf.keyboard.press({ keys: "shift+tab" }) }
        return selectionHasClip()
    }
    
    function getClipName() {
    
        if (selectFirstClip()) {
            sf.ui.proTools.menuClick({ menuPath: ["Clip", "Rename..."] })
    
            const renameWin = sf.ui.proTools.windows.whoseTitle.is("Name").first.elementWaitFor().element
    
            const clipName = renameWin.groups.whoseTitle.is("Name").first.textFields.first.value.invalidate().value
    
            renameWin.buttons.whoseTitle.is("Cancel").first.elementClick();
    
            renameWin.elementWaitFor({ waitType: "Disappear" })
    
            return clipName
        }
    }
    
    
    function getTrackClipList() {
        const originalTracks = sf.ui.proTools.selectedTrackHeaders;
    
        let trackClipList = []
        originalTracks.slice().map(track => {
    
            track.trackSelect();
            track.trackScrollToView();
            const clipName = getClipName()
    
            if (clipName) {
                trackClipList.push({
                    trackName: track,
                    clipName: clipName
                })
            }
        });
        sf.ui.proTools.trackSelectByName({ names: originalTracks.map(x => x.normalizedTrackName) });
        return trackClipList
    }
    
    function getSelectedCount() {
        const visibleTracks = sf.ui.proTools.visibleTrackNames
        const selectedTracks = sf.ui.proTools.selectedTrackNames
        const firstSelectedIndex = visibleTracks.indexOf(selectedTracks[0])
        const lastSelectedIndex = visibleTracks.indexOf(selectedTracks[selectedTracks.length - 1])
    
        return lastSelectedIndex - firstSelectedIndex + 1
    }
    
    function dismissNameExistsWarning(name, index, action) {
        if (sf.ui.proTools.confirmationDialog.invalidate().buttons.whoseTitle.is('OK').first.exists) {
            sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('OK').first.elementClick();
            sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('OK').first.elementWaitFor({ waitType: "Disappear" })
            sf.ui.proTools.focusedWindow.textFields.first.elementSetTextFieldWithAreaValue({
                value: name + "_" + (index + 1)
            });
            action.elementClick()
        }
    }
    
    function setTrackNames() {
    
    
        const firstToLastSelectedCount = getSelectedCount()
    
        //Get my list
        const trackClipList = getTrackClipList()
    
        //Scrool to view first track
        trackClipList[0].trackName.trackSelect();
        trackClipList[0].trackName.trackScrollToView()
    
        // Open rename window
        trackClipList[0].trackName.popupButtons.first.mouseClickElement({ clickCount: 2 })
    
        // Wait for rename window
        sf.ui.proTools.windows.whoseTitle.is(trackClipList[0].trackName.popupButtons.first.value.invalidate().value).first.elementWaitFor();
    
        // //Get the elements of buttons 
        const [ok, cncl, pr, next] = sf.ui.proTools.focusedWindow.buttons.map(x => x)
    
        // // Loop selected tracks
    
        for (let i = 0; i < firstToLastSelectedCount; i++) {
    
            const oldTrackName = () => sf.ui.proTools.focusedWindow.textFields.first.value.invalidate().value;
            const newName = trackClipList.filter(x => x.trackName.normalizedTrackName == oldTrackName())[0]
            if (trackClipList.some(x => x.trackName.normalizedTrackName == oldTrackName())) {
    
                // Set track name
                while (true) {
    
                    if (oldTrackName() != newName.clipName) {
                        sf.ui.proTools.focusedWindow.textFields.first.elementSetTextFieldWithAreaValue({
                            value: newName.clipName
                        });
                        sf.wait({ intervalMs: 5 })
                    } else {
                        next.elementClick()
                        dismissNameExistsWarning(newName.clipName, i, next)
                        break;
                    }
                };
    
            } else {
                next.elementClick()
            }
    
            // If its the last track press ok
            if (i === firstToLastSelectedCount - 1) {
                ok.elementClick()
            }
    
    
        };
    };
    
    sf.ui.proTools.appActivateMainWindow()
    sf.ui.proTools.invalidate()
    
    setTrackNames()
    
    • 4 replies
    1. M
      Matt Friedman @Matt_Friedman
        2021-09-10 01:05:13.568Z

        That works out awesome, way better than the clunky and easily broken hack I came up with!

        Thanks Samuel!

        1. samuel henriques @samuel_henriques
            2024-10-09 15:57:54.173Z2024-10-09 16:21:54.025Z

            Here's a new version using PT API.

            // Fix if track name exists
            function checkTrackDuplicate(trackName) {
            
                const trackNameExists = sf.app.proTools.tracks.invalidate().allItems.find(tn => tn.name === trackName)
            
                if (trackNameExists && trackNameExists.name) {
                    return trackName + ".1"
                } else {
                    return trackName
                };
            };
            
            // GROUP CLIP NAMES ARE ERRONEOUS ON track widths more than mono!!!
            function clipNameToTrackName() {
            
                const clipInfo = sf.app.proTools.getSelectedClipInfo().clips
            
                let trackInfoFilter = []
                let obj = {}
                for (let i = 0; i < clipInfo.length; i++) {
            
                    const trackName = clipInfo[i]["TrackName"];
                    const clipName = clipInfo[i]["ClipName"];
                    const cleanClipName = clipName && clipName.split(".").slice(0, 1).join()
            
                    let isClip = !clipName.startsWith("(fade ") && !clipName.endsWith(" fade)")
            
            
                    if (!obj[trackName] && isClip) {
                        obj[trackName] = cleanClipName
            
                        trackInfoFilter.push({ trackName, clipName: cleanClipName })
                    };
                };
            
                trackInfoFilter.forEach(tr => {
            
                    let oldName = tr.trackName
                    let newName = tr.trackName !== tr.clipName ? checkTrackDuplicate(tr.clipName) : tr.trackName
            
                    sf.app.proTools.renameTrack({
                        oldName,
                        newName,
                        onError: "Continue"
                    });
            
            
            
                    globalState.clipNameToTrackNameUndo.push({
                        oldName: newName,
                        newName: oldName
                    })
            
                   
                })
            };
            
            function undoTrackRename() {
                globalState.clipNameToTrackNameUndo.reverse().forEach(tr => {
            
                      sf.app.proTools.renameTrack({
                          oldName: tr.oldName,
                          newName: tr.newName,
                          onError: "Continue"
                      });
            
                })
            }
            
            
            // Press ALT + Triger for undo.
            if (event.keyboardState.hasAlt) {
                undoTrackRename();
            
            } else {
                
                globalState.clipNameToTrackNameUndo = []
                clipNameToTrackName();
            }
            
            1. MMatt Friedman @Matt_Friedman
                2024-10-09 17:05:12.965Z

                Everything gets better with PT API!! Thanks Samuel

              • A
                Alessandro Tsamis @Alessandro_Tsamis
                  2025-01-02 09:51:02.747Z

                  Cane someone make a version for all selected tracks?