No internet connection
  1. Home
  2. How to

spot to original time stamp macro/script?

By Daniel Perez @daniel_perez
    2023-09-25 16:57:37.891Z

    is there a way to script "spot to original time stamp"?

    Solved in post #9, click to view
    • 10 replies

    There are 10 replies. Estimated reading time: 14 minutes

    1. Daniel Perez @daniel_perez
        2023-09-25 16:58:14.491Z
        1. Dustin Harris @Dustin_Harris
            2023-09-25 17:10:02.923Z

            I think I make something like this a while ago....

            try this:

            function getClipInfo() {
                try {
                    //shorten name
                    const clipNameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first;
            
                    //show clip list if it's not currently shown
            
                    let clipListIsClosed = !sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is("Clip List").first.exists;
            
                    if (clipListIsClosed) {
                        sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Show/Hide Clip List").first.elementClick({}, `could not show clip list`);
                    }
            
                    //shorten name
                    const clipInfoGrp = clipNameWin.groups.whoseTitle.is('Clip Info').first.children.whoseRole.is("AXStaticText");
            
                    sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                        isRightClick: true,
                        menuPath: ["Show", "Auto-Created"],
                        targetValue: "Enable"
                    }, `could not enable show auto-created regions`);
            
                    sf.ui.proTools.menuClick({
                        menuPath: ["Clip", "Rename..."],
                    });
            
                    clipNameWin.elementWaitFor({}, `could not open clip rename window`);
            
                    //check to see if window needs expanding, and expand it if necessary
                    if (!clipInfoGrp.whoseValue.is('User Time Stamp:').first.exists) {
            
                        clipNameWin.groups.whoseTitle.is('Clip Info').first.mouseClickElement({
                            relativePosition: { "x": 12, "y": 12 },
                        });
                    };
            
                    let clipInfo = {
            
                        originalTimeStamp: clipInfoGrp.allItems[21].value.invalidate().value.split('.')[0],
            
                        duration: clipInfoGrp.allItems[19].value.invalidate().value.split('.')[0],
            
                    };
            
            
                    clipNameWin.buttons.whoseTitle.is('Cancel').first.elementClick({}, `could not cancel out of clip rename window`);
            
                    if (clipListIsClosed) {
                        sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Show/Hide Clip List").first.elementClick({}, `could not show clip list`);
                    }
            
            
                    return clipInfo;
            
                } catch (err) {
                    throw (err === 0) ? 0 : `Error in getClipInfo: ${err}`
                }
            }
            
            function main() {
            
                sf.ui.proTools.appActivateMainWindow()
            
                const selectedTracks = sf.ui.proTools.selectedTrackNames;
                const { selectionStart, selectionEnd } = sf.ui.proTools.selectionGet();
            
                let clipInfo = getClipInfo();
            
                sf.ui.proTools.selectionSet({ selectionStart: clipInfo.originalTimeStamp, selectionLength: clipInfo.duration })
            
                sf.keyboard.press({ keys: "left" })
            
                let consent = confirm('click OK to return to original selection, cancel to cancel')
            
                if (consent) {
            
                    sf.ui.proTools.trackSelectByName({ names: selectedTracks })
                    sf.ui.proTools.selectedTrackHeaders[0].trackScrollToView();
                    sf.ui.proTools.selectionSet({ selectionStart, selectionEnd })
            
                    sf.keyboard.press({ keys: "left" })
                }
            
                else {
                    log('Cancelled')
                }
            
            }
            
            main();
            

            Wrong script, that one goes to the original timestamp location of the selected clip.

            1. Dustin Harris @Dustin_Harris
                2023-09-25 17:15:17.339Z

                This one; and I have it set to a window trigger of 'When a window titled 'Spot Dialog' is focused in Pro Tools.

                //hack to make sure everything loads
                sf.ui.proTools.clipSpotDialog.invalidate().buttons.whoseTitle.is("OK").first.elementWaitFor();
                
                const currentStart = () => sf.ui.proTools.clipSpotDialog.textFields.first.value.invalidate().value;
                const originalTimeStamp = () => sf.ui.proTools.clipSpotDialog.children.whoseRole.is("AXStaticText").allItems[7].value.invalidate().value.split(".")[0];
                
                if (originalTimeStamp() != currentStart()) {
                    while (originalTimeStamp() != currentStart()) {
                        sf.ui.proTools.clipSpotDialog.mouseClickElement({
                            relativePosition: { x: 274, y: 256 }
                        })
                
                        sf.wait({intervalMs:100})
                    }
                
                    sf.ui.proTools.clipSpotDialog.buttons.whoseTitle.is("OK").first.elementClick();
                } else {
                    sf.ui.proTools.clipSpotDialog.buttons.whoseTitle.is("Cancel").first.elementClick();
                }
                
                sf.ui.proTools.clipSpotDialog.elementWaitFor({ waitForNoElement: true })
                
                1. Daniel Perez @daniel_perez
                    2023-09-25 17:29:59.732Z

                    can i trigger it with a standard keyboard shortcut, without having the spot to dialogue open?

                    by the way, will we actually have more or less everything as "commands", directly manipulating all the pt functions without the need to open and close windows and dialogues in a not too distant future?
                    basically, will pt open up to soundflow so much, that we will be able to control what we need, without being dependant on the pt UI?
                    i dont really get, why we dont have this yet, as the commands inside pt are there, the UIs just connect to them, right?
                    but avid goes already into a very good direction i'd say.

                    1. Chad Wahlbrink @Chad2023-09-26 19:57:39.495Z

                      @daniel_perez - regarding the idea of interfacing directly with Pro Tools. This is the benefit of the Pro Tools Scripting SDK. Currently, only a limited number of commands are exposed by Avid, and SoundFlow is reliant on Avid continuing to update and maintain the available commands.

                      We do not have access to every command in Pro Tools yet, but the future is promising.

                      If you are interested, you can poke around the available actions by using sf.app.proTools. in a script and seeing what actions are currently available through SoundFlow:

                      Also, a fun example from recent forum projects for me was this script, which will export a CSV of the markers in the current session without touching the PT UI.
                2. In reply todaniel_perez:
                  Chad Wahlbrink @Chad2023-09-26 19:33:29.753Z

                  Hey @daniel_perez,

                  Spot first clip in clip list to original time stamp #post-8
                  There is a lot of discussion on this thread about this workflow.

                  Here's my take on it that works well from a keyboard shortcut:

                  // If Auto Spot Clips is On, turn it off
                  if(sf.ui.proTools.getMenuItem('Options', 'Auto-Spot Clips').isMenuChecked) { sf.ui.proTools.menuClick({ menuPath: ['Options', 'Auto-Spot Clips'], });
                  }
                  
                  //Switch to the "Grabber" tool
                  sf.ui.proTools.toolsSelect({
                      tool: "Grabber",
                  });
                  
                  //Open the “Spot Dialog” window
                  sf.ui.proTools.clipOpenSpotDialog();
                  
                  //Wait for “Spot Dialog” window
                  sf.ui.proTools.clipSpotDialog.elementWaitFor();
                  
                  //Click "Original Time Stamp button" in “Spot Dialog” window
                  sf.ui.proTools.clipSpotDialog.mouseClickElement({
                      relativePosition: {"x":270,"y":250},
                  });
                  
                  //Click “OK” button in “Spot Dialog” window
                  sf.ui.proTools.clipSpotDialog.buttons.whoseTitle.is('OK').first.elementClick();
                  
                  // Set back to Smart Tool
                  sf.ui.proTools.toolsSelect({
                      tool: "Smart",
                  });
                  // Set back to slip mode
                  sf.ui.proTools.editModeSet({
                    mode: "Slip",
                  });
                  
                  1. Chad Wahlbrink @Chad2023-09-26 19:45:37.103Z

                    I think some errors are possible with .clipOpenSpotDialog() currently.

                    I do think @Dustin_Harris's script based on the Spot Dialog being focused may be your best bet for now:

                3. In reply todaniel_perez:
                  Daniel Perez @daniel_perez
                    2023-09-27 04:47:09.186Z

                    this one works:

                    var menu = sf.ui.proTools.clipOpenContextMenu().popupMenu;
                    menu.menuClickPopupMenu({
                        menuPath: ['Spot...'],    
                    });
                    
                    
                    sf.ui.proTools.clipSpotDialog.elementWaitFor();
                    
                    
                    //hack to make sure everything loads
                    sf.ui.proTools.clipSpotDialog.invalidate().buttons.whoseTitle.is("OK").first.elementWaitFor();
                    
                    const currentStart = () => sf.ui.proTools.clipSpotDialog.textFields.first.value.invalidate().value;
                    const originalTimeStamp = () => sf.ui.proTools.clipSpotDialog.children.whoseRole.is("AXStaticText").allItems[7].value.invalidate().value.split(".")[0];
                    
                    if (originalTimeStamp() != currentStart()) {
                        while (originalTimeStamp() != currentStart()) {
                            sf.ui.proTools.clipSpotDialog.mouseClickElement({
                                relativePosition: { x: 274, y: 256 }
                            })
                    
                            sf.wait({intervalMs:100})
                        }
                    
                        sf.ui.proTools.clipSpotDialog.buttons.whoseTitle.is("OK").first.elementClick();
                    } else {
                        sf.ui.proTools.clipSpotDialog.buttons.whoseTitle.is("Cancel").first.elementClick();
                    }
                    
                    sf.ui.proTools.clipSpotDialog.elementWaitFor({ waitForNoElement: true })
                    
                    Reply2 LikesSolution
                    1. Chad Wahlbrink @Chad2023-09-27 11:58:12.635Z

                      Excellent, nice work!

                      1. In reply todaniel_perez:
                        MMatt Friedman @Matt_Friedman
                          2024-04-26 23:00:35.715Z

                          Line 14 does not always work

                          const originalTimeStamp = () => sf.ui.proTools.clipSpotDialog.children.whoseRole.is("AXStaticText").allItems[7].value.invalidate().value.split(".")[0];
                          

                          Sometime it gives the value, other times, it gives an error:
                          Couldn't get item #7 as the array length was 0 - sf.ui.app('com.avid.ProTools')..children.whoseRole.is('AXStaticText')[7] (AxElementArrayIndexedItem)

                          One way to reproduce, open spot win 1st time and it should work. open spot win a 2nd time and it won't work anymore.

                          clipSpotDialog needs an invalidate()

                          Also currentStart should return a timecode with no subframes too (in case the subframes box is ticked).

                          I changed lines 13 and 14 to this to prevent an infinite while loop:

                          const currentStart = () => spotWin.invalidate().textFields.first.value.invalidate().value.split(".")[0];
                          const originalTimeStamp = () => spotWin.invalidate().children.whoseRole.is("AXStaticText").allItems[7].value.invalidate().value.split(".")[0];