No internet connection
  1. Home
  2. Script Sharing

Select Track by Name with Deselect-Others - Logic Pro

By Nicolas Aparicio @Nicolas_Aparicio
    2024-08-21 00:14:47.131Z

    Hi team,

    I've created a code for selecting tracks by name in Logic Pro, that can deselect other tracks if needed.
    It won't be as clean or robust as Kitch's code but thought of sharing it for now while he's probably cooking something 10 times better than this.

    @Kitch, I struggled a bit trying to select tracks with the same name, as the code recalcutes their position one after the other. Am I complicating it too much or can it be done during the loop function from lines 30-58?

    Cheers,
    Nic.

    function selectTracksByName({ trackNames, deselectOthers }) {
    
        function getTracksInfo() {
    
            try {
    
                const visibleTracksInfo = trackHeaders.map(track => ({
                    name: track.getString('AXDescription').match(/“(.*)”/)[1],
                    positionX: track.textFields.first.frame.x,
                    positionY: track.textFields.first.frame.y,
                }));
    
                return visibleTracksInfo
    
            } catch (err) {
                alert(`⚠️ Track Names must be visible\nfor this code to work! ⚠️`)
                throw 0
            };
    
        }
    
        function selectTracks() {
    
            function mouseClick({ clickX, clickY, scrollCompensate }) {
                sf.mouse.click({ position: { x: clickX, y: clickY + scrollCompensate }, isCommand: true })
            }
    
            for (let i = 0; i < trackNames.length; i++) {
    
                const visibleTracksInfo = getTracksInfo();
                const trackNameInfo = visibleTracksInfo.filter(track => track.name === trackNames[i])[0]
                const editArea = scrollAreas.allItems[1]
                const trackPosition = trackNameInfo.positionY
                const scrollValue = (editArea.frame.y - trackPosition) / 10
                const mouseClickX = trackNameInfo.positionX + 20
                const mouseClickY = trackPosition + 20
    
                if (trackPosition > editArea.frame.y && trackPosition < editArea.frame.h) {//Click within view
                    if (i === 0 && deselectOthers === true) {
                        sf.mouse.click({ position: { x: trackNameInfo.positionX, y: trackNameInfo.positionY + 20 }, isOption: true })//De-Select other tracks})
                    };
                    mouseClick({ clickX: mouseClickX, clickY: mouseClickY, scrollCompensate: null })
    
                } else {//Scroll Into View
                    if (i === 0) { sf.wait({ intervalMs: 50 }) } //Wait for popup menu to disappear
    
                    sf.mouse.setPosition({ position: { x: editArea.frame.x + 50, y: editArea.frame.y + 50 } }) //Set mouse position for scroll
                    sf.mouse.scroll({ delta: scrollValue })
    
                    if (i === 0 && deselectOthers === true) {
                        sf.mouse.click({ position: { x: mouseClickX, y: mouseClickY + (+scrollValue * 10) }, isOption: true })//De-Select other tracks
                    };
                    mouseClick({ clickX: mouseClickX, clickY: mouseClickY, scrollCompensate: (+scrollValue * 10) })
                };
    
            };
    
        }
    
        if (!sf.ui.logic.isRunning) throw `Logic Pro is not running`;
    
        const logicWindow = sf.ui.logic.mainWindow
        const tracksArea = logicWindow.groups.whoseDescription.is("Tracks").first.groups.whoseDescription.is("Tracks").allItems[1]
        const scrollAreas = tracksArea.splitGroups.first.splitGroups.allItems[1].scrollAreas
        const trackHeaders = scrollAreas.first.groups.whoseDescription.is("Tracks header").first.children.whoseRole.is("AXLayoutItem")
    
        sf.ui.logic.appActivate();
    
        selectTracks();
    
    }
    
    selectTracksByName({ trackNames: 'Add Here', deselectOthers: true });
    
    • 1 replies
    1. Kitch Membery @Kitch2024-08-21 00:29:06.851Z

      Hi Nic,

      I'll take a look at this when I get a chance.

      In your script you're using a lot of mouse and scroll simulation which is not the most stable way of automating with SoundFlow.

      There are ways of setting values for scrollbars directly that would make this approach more stable, but still not bulletproof.

      Thankfully I've been making some good progress on a stable solution.