No internet connection
  1. Home
  2. Macro and Script Help

Move Track Selection and Eucon Attention in both Mix and Edit Windows

By Ben Rubin @Ben_Rubin
    2025-03-15 19:36:19.142Z

    Title

    Error thrown on trying to click Track Title

    What do you expect to happen when you run the script/macro?

    Supposed to move selection to the next track in either mix or edit window. Then click on the track name to attention the track in EUCON.

    When I run the script it does this but throws an error message and does not complete the script (dismissing the track rename window that comes up).

    Are you seeing an error?

    This is the error I get. I happens at the same line in either the mix or edit windows.

    Logging error in action (01) ClickButtonAction: Error invoking AXElement: kAXErrorCannotComplete
    !! Command Error: SELECT NEXT TRACK FULL [user:ck08xanhn0007p610i48im7ck:cm8ahcbld0000kd10vktqn5hi]:
    Error invoking AXElement: kAXErrorCannotComplete (SELECT NEXT TRACK FULL: Line 26)
    SoundFlow.Shortcuts.AXUIElementException: kAXErrorCannotComplete
    at SoundFlow.Shortcuts.AXUIElement.DoAction(String action) + 0x98
    at SoundFlow.Shortcuts.Automation.Actions.ClickButtonAction.d__11.MoveNext() + 0x7c

    What happens when you run this script?

    gave all the info already

    How were you running this script?

    Other

    How important is this issue to you?

    5

    Details

    {
        "inputExpected": "Supposed to move selection to the next track in either mix or edit window. Then click on the track name to attention the track in EUCON.\n\nWhen I run the script it does this but throws an error message and does not complete the script (dismissing the track rename window that comes up).",
        "inputIsError": true,
        "inputError": "This is the error I get. I happens at the same line in either the mix or edit windows. \n\nLogging error in action (01) ClickButtonAction: Error invoking AXElement: kAXErrorCannotComplete\n!! Command Error: SELECT NEXT TRACK FULL [user:ck08xanhn0007p610i48im7ck:cm8ahcbld0000kd10vktqn5hi]:\nError invoking AXElement: kAXErrorCannotComplete (SELECT NEXT TRACK FULL: Line 26)\n    SoundFlow.Shortcuts.AXUIElementException: kAXErrorCannotComplete\n   at SoundFlow.Shortcuts.AXUIElement.DoAction(String action) + 0x98\n   at SoundFlow.Shortcuts.Automation.Actions.ClickButtonAction.d__11.MoveNext() + 0x7c\n",
        "inputWhatHappens": "gave all the info already",
        "inputHowRun": {
            "key": "-MpfwoFyZNOpBC3X5xGI",
            "title": "Other"
        },
        "inputImportance": 5,
        "inputTitle": "Error thrown on trying to click Track Title"
    }

    Source

    sf.ui.proTools.appActivateMainWindow();
    
    const sup = sf.ui.proTools
    var allTracks = sup.trackGetVisibleTracks().names;
    var allTracksCount = allTracks.length
    var selTracks = sup.trackGetSelectedTracks().names;
    var currentTrack = selTracks[0]
    for (var i = 0; i < allTracksCount; i++) {
        if (allTracks[i].indexOf(currentTrack) == 0)
            break;
    }
    i = i + 1;
    if (i > allTracksCount - 1) { throw 0 }
    sup.trackSelectByName({
        names: [allTracks[i]]
    });
    
    //Get the current window name
    const focusedWindow = sf.ui.proTools.focusedWindow.title.invalidate().value.split(" ", 1)[0].slice(0, -1);
    
    // If Mix Window is Frontmost
    if (focusedWindow == 'Mix') {
        let trackName = sf.ui.proTools.selectedTrack.normalizedTrackName;
    
        // Click on Track Name in the Mix Window
        sf.ui.proTools.mixWindow.groups.whoseTitle.startsWith(trackName).first.popupButtons.whoseTitle.startsWith('Track name').first.elementClick();
    
    }
    // Else - Edit Window is front Most
    else if (focusedWindow == 'Edit') {
        let trackName = sf.ui.proTools.selectedTrack.normalizedTrackName;
        sf.ui.proTools.mixWindow.groups.whoseTitle.startsWith(trackName).first.popupButtons.whoseTitle.startsWith('Track name').first.elementClick();
    }   
    
    sf.ui.proTools.children.whoseRole.is("AXWindow").first.getElement("AXTitleUIElement").elementWaitFor();
    
    sf.ui.proTools.children.whoseRole.is("AXWindow").first.buttons.whoseTitle.is("OK").first.elementClick();
    

    Links

    User UID: yesbmwLVy0dRQLFNZzxo8kQx4ri2

    Feedback Key: sffeedback:yesbmwLVy0dRQLFNZzxo8kQx4ri2:-OLQIehWZoDfOyfpx5GK

    Feedback ZIP: gaDUnhNDMFQn2xFB50I8xXNwApjHc7xeSDrO5oSYoazg8SxbKyyl1K68qo8zxhr3Gbj4dup/38ltFnaVpynaEJdMNpnMQIWpyqib+ptU8qt9pUhsIWlboyD7h5wyvhaXfXIswBbsBPGLRjZ/PH10QL/7zkVI8U1m5A4vDmcilZFloOk22Q9+kGgleudS/UL+IxmUvHnwMg5VYCPpA179X54ivGkkbmOZgJhvVrfsPjLIx+m35ADfDdr7DKFMEQp3psDQHUWQPhPoZH5KgxxYpNJs5f4BfjkKHhzHNV1pKPlqVmregu/9AFXVN+tszs8wx/X7f74VWSBXe3JaqqFLHw==

    Solved in post #15, click to view
    • 20 replies

    There are 20 replies. Estimated reading time: 15 minutes

    1. Ben Rubin @Ben_Rubin
        2025-03-15 19:38:57.705Z

        Error will happen on either line 26 or 32 depending on the frontmost window.

        Im sure this a clunky way to do this so open to any alternatives from our resident SF geniuses.

        My ultimate goal is to get the next track in pro tools attentioned in EUCON by just running a script launched from an Avid Dock touchstrip.

        1. Ben Rubin @Ben_Rubin
            2025-03-17 20:17:11.517Z

            @Kitch, @samuel_henriques, @Chris_Shaw, any thoughts on this one?

            🙏

            1. In reply toBen_Rubin:
              Kitch Membery @Kitch2025-03-17 20:25:37.717Z

              Hi @Ben_Rubin

              Does running a script like this attention the track in EUCON?

              const focusTrackName = "Audio 1"; // Change this name to a track in your session.
              
              sf.app.proTools.selectTracksByName({
                  trackNames: [focusTrackName]
              });
              
              

              Let me know, and if so, it should be pretty simple. :-)

              1. In order for a track to be selected in Eucon (depending on preferences) the title button has to be clicked. I've come up with a semi robust solution but I think you could do better :)

                1. In reply toKitch:
                  Ben Rubin @Ben_Rubin
                    2025-03-18 03:22:59.250Z

                    Thanks @kitch but that doesnt work.

                  • In reply toBen_Rubin:

                    I'm assuming that you have "Attention most recently click DAW area" set to "Track Name" to attention the track in Econ (Which requires the track title to be clicked - not just selected).

                    You can simplify the script significantly and still have it work in the Edit or Mix windows.
                    When using elementClick() you have to set asyncSwallow to true otherwise it fails.

                    The downside to this is that if you re-trigger the script rapidly it causes the track rename window to appear or cause a timeout error. I've included a routine to check for a rename window and dismiss it if it appears.
                    But still, rapid triggering results in inconsistent behavior.
                    @Kitch will probably have a more robust solution.

                    /***
                     * Selects and attentions track in Eucon.
                     * If no parameter is specified it will select next track
                     * @param {'next' | 'previous'| null} [nextOrPrevious]
                     */
                    
                    function selectAndAttentionNextOrPreviousTracK(nextOrPrevious) {
                        sf.ui.proTools.mainWindow.invalidate()
                        sf.ui.proTools.appActivate();
                    
                        const visibleTracks = sf.ui.proTools.visibleTrackNames;
                        const currentTrackName = sf.ui.proTools.selectedTrackNames[0]
                    
                        const nextTrackDelta = nextOrPrevious == "next" || nextOrPrevious == null ? 1 : -1;
                    
                        const nextTrackIndex = visibleTracks.indexOf(currentTrackName) + nextTrackDelta
                    
                        // Bail if trying to select track outside of array start or end
                        if (nextTrackIndex == visibleTracks.length || nextTrackIndex < 0) throw 0;
                    
                        const nextTrackName = visibleTracks[nextTrackIndex]
                    
                        const nextTrackTitleButton = sf.ui.proTools.trackGetByName({ name: nextTrackName }).track.titleButton
                        nextTrackTitleButton.elementClick({ asyncSwallow: true, })
                    
                        const trackRenameWindow = sf.ui.proTools.windows.whoseTitle.is(nextTrackName).first
                    
                        sf.waitFor({
                            callback: () => trackRenameWindow.exists,
                            timeout:150,
                            onError:"Continue"
                        })
                    
                        if (trackRenameWindow.exists) {
                            trackRenameWindow.buttons.whoseTitle.is("OK").first.elementClick()
                            trackRenameWindow.elementWaitFor({ waitType: "Disappear" })
                        }
                    
                    }
                    
                    selectAndAttentionNextOrPreviousTracK('next')
                    
                    1. Ben Rubin @Ben_Rubin
                        2025-03-18 03:48:07.174Z

                        This seems to be working for me, @Chris_Shaw. Thanks so much! Def interested if @kitch can streamline or improve in any way. I dont think the P/; solution works for me since it doesnt work in the Mix Window.

                        1. Kitch Membery @Kitch2025-03-18 09:23:34.421Z

                          Hi @Ben_Rubin & @Chris_Shaw,

                          Let me know if this script attentions tracks via EUCON as expected. (Fingers crossed.)

                          /**
                           * @param {object} obj
                           * @param {'next'|'previous'} obj.direction
                           */
                          function navigateTracks({ direction } = { direction: "next" }) {
                              const visibleTrackNames = sf.ui.proTools.visibleTrackNames;
                              const selectedTrackName = sf.ui.proTools.selectedTrack.normalizedTrackName;
                          
                              const delta = direction === "next" ? 1 : -1;
                              const targetTrackIndex = visibleTrackNames.indexOf(selectedTrackName) + delta;
                          
                              if (targetTrackIndex < 0 || targetTrackIndex >= visibleTrackNames.length) return;
                          
                              const targetTrackName = visibleTrackNames[targetTrackIndex];
                          
                              sf.app.proTools.selectTracksByName({ trackNames: [targetTrackName] });
                          
                              try {
                                  const tracklistview = sf.ui.proTools.mainWindow.trackListView;
                                  const rows = tracklistview.childrenByRole("AXRow");
                          
                                  let trackSelector = null;
                          
                                  for (let i = 0; i < rows.length; i++) {
                                      const row = rows[i];
                                      const cells = row.childrenByRole("AXCell").allItems;
                                      
                                      if (cells.length > 1) {
                                          const button = cells[1].buttons.first;
                                          if (button && button.title.value.replace(/^Open\. /, "") === targetTrackName) {
                                              trackSelector = button;
                                              break;
                                          }
                                      }
                                  }
                          
                                  if (trackSelector) {
                                      trackSelector.elementClick();
                                  }
                              } catch (err) { }
                          }
                          
                          navigateTracks({ direction: "next" });
                          

                          And, to navigate to the previous track, change the call to...

                          navigateTracks({ direction: "previous" });
                          

                          Rock on!

                          1. It didn't work on my end. (SO close!)
                            I added this below line 37 log("Clicking") to see if it was finding the selected track and the script didn't log anything.
                            I then changed line 30 to :
                            if (button && button.title.value.startsWith("Selected.")) {
                            This change then logged "Clicking"; so the element is being found. The element is clicked but is then de-selected so the track isn't attentioned in Eucon

                            1. Kitch Membery @Kitch2025-03-18 16:13:34.655Z

                              Bummer!!! Back to the drawing board.

                              Thanks for checking @Chris_Shaw

                              1. Success!
                                This works:

                                /**
                                 * @param {object} obj
                                 * @param {'next'|'previous'} obj.direction
                                 */
                                function navigateTracks({ direction } = { direction: "next" }) {
                                
                                    const tracks = () => sf.app.proTools.tracks.invalidate().allItems;
                                    const visibleTrackNames = sf.ui.proTools.visibleTrackNames;
                                    const selectedTrackName = sf.ui.proTools.selectedTrack.normalizedTrackName;
                                
                                    const delta = direction === "next" ? 1 : -1;
                                    const targetTrackIndex = visibleTrackNames.indexOf(selectedTrackName) + delta;
                                
                                    if (targetTrackIndex < 0 || targetTrackIndex >= visibleTrackNames.length) return;
                                
                                    const targetTrackName = visibleTrackNames[targetTrackIndex];
                                
                                    const targetTrackHeader =sf.ui.proTools.trackGetByName({name:targetTrackName}).track
                                    targetTrackHeader.trackScrollToView()
                                    
                                    targetTrackHeader.titleButton.mouseClickElement({
                                        anchor:"TopLeft",
                                        relativePosition:{x:5,y:5}
                                    })
                                }
                                
                                navigateTracks({ direction: "next" });
                                
                                ReplySolution
                                1. I wonder if there is a bug with elementClick()ing the title button? PT is treating it as a double click and opens the rename window.

                                  1. In reply toChris_Shaw:
                                    Ben Rubin @Ben_Rubin
                                      2025-03-18 16:43:37.673Z

                                      This also works great for me. Thanks much, 🙏🙏🙏

                                      1. In reply toChris_Shaw:
                                        Kitch Membery @Kitch2025-03-18 16:52:48.042Z

                                        Nice one @Chris_Shaw.

                                        Can you try this script that uses the trackSelectByName method to select a track...

                                        /**
                                         * @param {object} obj
                                         * @param {'next'|'previous'} obj.direction
                                         */
                                        function navigateTracks({ direction } = { direction: "next" }) {
                                            const visibleTrackNames = sf.ui.proTools.visibleTrackNames;
                                            const selectedTrackName = sf.ui.proTools.selectedTrack.normalizedTrackName;
                                        
                                            const delta = direction === "next" ? 1 : -1;
                                            const targetTrackIndex = visibleTrackNames.indexOf(selectedTrackName) + delta;
                                        
                                            if (targetTrackIndex < 0 || targetTrackIndex >= visibleTrackNames.length) return;
                                        
                                            const targetTrackName = visibleTrackNames[targetTrackIndex];
                                        
                                            sf.ui.proTools.trackSelectByName({names:[targetTrackName]});
                                        }
                                        
                                        navigateTracks({ direction: "next" });
                                        
                                        1. Kitch Membery @Kitch2025-03-18 16:56:27.378Z

                                          I'd say it won't work, but it's worth testing to avoid the use of a mouse click.

                                          1. It selects the track but it doesn't attention the track. It seems only a click will do it.

                                            1. Kitch Membery @Kitch2025-03-18 17:32:22.151Z

                                              Figured as much. Thanks! :-)

                            2. In reply toBen_Rubin:
                              Kitch Membery @Kitch2025-03-18 00:16:10.613Z

                              @Chris_Shaw & @Ben_Rubin,

                              This works for me on the Avid Control (iPad app) through EUCON...

                              /**
                               * @param {object} obj
                               * @param {'next'|'previous'} obj.direction
                               */
                              function navigateTracks({ direction } = { direction: "next" }) {
                                  sf.ui.proTools.appActivateMainWindow();
                                  sf.ui.proTools.mainWindow.invalidate();
                              
                                  const visibleTrackNames = sf.ui.proTools.visibleTrackNames;
                                  const selectedTrackName = sf.ui.proTools.selectedTrack.normalizedTrackName;
                              
                                  const delta = { "next": +1, "previous": -1, }[direction];
                              
                                  const targetTrackIndex = visibleTrackNames.indexOf(selectedTrackName) + delta;
                                  const targetTrackName = visibleTrackNames[targetTrackIndex];
                              
                                  if (!targetTrackName) throw 0
                              
                                  sf.app.proTools.selectTracksByName({
                                      trackNames: [targetTrackName]
                                  });
                              }
                              

                              With the following calls...

                              // Next track
                              navigateTracks({
                                  direction: "next"
                              });
                              

                              &

                              // Previous track
                              navigateTracks({
                                  direction: "previous"
                              });
                              

                              Let me know if it works for you. :-)

                              1. I think the confusing issue here is the difference in Eucon parlance between "selected" and "attentioned".

                                Selecting a track can be done either physically or programmatically. A track is attentioned by either clicking a track header element with a mouse or selecting it using a button on a Eucon surface.
                                To see this in action, in Eucon preferences, set 'Track name' as an attention click area:

                                In your AVID Control app, at the very top of the display select 'Channel', then select the Pan display which will show the pan settings on an attentioned track.

                                If you switch track inPT by using the 'p' and ';' keys you'll notice that the attentioned track pan display in the AVID Control app does not change. Programmatically selecting a track does not change the display either. But if you select a track by clicking on it's title button with the mouse the channel pan display changes to the track you just clicked.

                                So the script needs to click the track title button in order to attention the selected track.

                                1. I think the easiest way to get around this is to use 'Edit selection move up/down' in EuCon prefs and just use the 'p' and ';' keys: