No internet connection
  1. Home
  2. How to

Import Session Data - wait for 'restoring tracks' progress bar

By Pinewood Studios @Pinewood_Studios
    2025-01-28 10:48:06.544Z

    Hi,

    I have a script designed to import Pro Tools sessions one by one into a master session. I use the SDK command to do this, however, the script does not seem to wait for each import to complete before moving to the next, meaning the sessions often get imported in the wrong order.

    I would like to wait until the 'restoring tracks' progress bar appears and then disappears, but I can't seem to pick this UI element no matter what I do. Does anyone know how I can wait for this (shown below) to appear then disappear?

    Thanks,

    Fergus

    • 23 replies

    There are 23 replies. Estimated reading time: 21 minutes

    1. Kitch Membery @Kitch2025-01-28 22:24:23.154Z

      To have SoundFlow wait for these kinds of windows in Pro Tools, we use the "Wait for No Modals" method. Like this...

      sf.ui.proTools.waitForNoModals();
      

      Sometimes, however if the modals window take a moment to appear, you may need a small wait before the "Wait for No Modals" method. Like this...

      sf.wait({intervalMs:200});
      sf.ui.proTools.waitForNoModals();
      

      I hope that helps. :-)

      1. Pinewood Studios @Pinewood_Studios
          2025-01-29 09:27:50.408Z

          Hey Kitch,

          Thanks for confirming. In this case, the modal window doesn't seem to pop up until after the entire script has run, with up to 6 sf.app.proTools.importSessionData() commands already called (confirmed with logging). So it'd have to be quite a long wait I imagine.

          Out of interest, are there any plans at all to implement a 'waitForModals()' method? That'd help in this exact scenario, at the least.

          Best wishes, and thanks for your response.

          Fergus

          1. Kitch Membery @Kitch2025-01-29 18:14:20.480Z

            Hi Fergus,

            Can you paste the script here in the thread so I can troubleshoot the issue further?

            Thanks in advance. :-)

            1. Pinewood Studios @Pinewood_Studios
                2025-01-30 17:41:09.916Z

                Of course. No judgement please... very much a WIP, ha!

                // PRO TOOLS START SCRIPT
                    if (!sf.ui.proTools.isRunning) throw 'Pro Tools is not running';
                    sf.ui.proTools.appActivateMainWindow();
                
                const enableLogging = "YES"
                
                sf.interaction.displayDialog({
                        prompt: "This script will search the directory above the one containing currently open session, looking for reels 2 onwards. You should already have open a session containing reel 1 open. If you don't, please do this then re-run this script",
                        buttons: ["Proceed","Cancel"],
                        defaultButton: "Proceed",
                });
                
                let numReels = Number(prompt("How many reels are there?"));
                if (isNaN(numReels)) throw 0;
                
                const currentSessionPath = sf.app.proTools.getSessionPath().sessionPath.replace(/:/g, "/");
                //const currentSessionDirectory = currentSessionPath.substring(0, currentSessionPath.lastIndexOf('/'));
                const mainDirectory = currentSessionPath.substring(0, currentSessionPath.lastIndexOf('/', currentSessionPath.lastIndexOf('/') - 1));
                const possibleDirectories = sf.file.directoryGetDirectories({path: mainDirectory}).paths
                
                if(enableLogging.toLowerCase() === "yes"){
                    log(possibleDirectories);
                }
                
                
                let sessionToImportPath;
                let allSessionPaths;
                let firstMatchingReelSessionPath;
                let directoryToTest;
                
                const possibleDirectoryNames = [
                    "R",
                    "R0",
                    "REEL",
                    "R-",
                    "R_",
                    "R-0",
                    "R_0"
                ];
                
                for (let index = 2 ; index<numReels+1; index++ ){
                   
                    for (const directoryName of possibleDirectoryNames) {
                
                        if(enableLogging.toLowerCase() === "yes"){
                            log(`Trying combination: ${directoryName}${index}`);
                        };
                        //sf.wait({intervalMs: 100});
                
                        directoryToTest = possibleDirectories.filter(directory => directory.includes(`${directoryName}${index}`))[0]
                
                        if(!directoryToTest){
                            if(enableLogging.toLowerCase() === "yes"){
                                log(`No possibilities found for combination ${directoryName}${index}`);
                            }
                            //Move to next possibility
                            continue;
                        }
                
                        //log("Testing " + directoryToTest);
                
                        if (sf.file.directoryExists({path: directoryToTest}).exists){
                            if(enableLogging.toLowerCase() === "yes"){
                                log("Successfully found: " + directoryToTest)
                            }
                            sessionToImportPath = directoryToTest;
                            break;
                        }
                    }
                
                    allSessionPaths = sf.file.directoryGetFiles({ path: sessionToImportPath, searchPattern: '*.ptx' }).paths;
                    firstMatchingReelSessionPath = allSessionPaths[0];
                 
                    if (!firstMatchingReelSessionPath) throw `No session found in directory: ${sessionToImportPath}`;
                    if(enableLogging.toLowerCase() === "yes"){
                        log(`Importing: ${firstMatchingReelSessionPath}`);
                    }
                    sf.app.proTools.importSessionData({
                        sessionPath: firstMatchingReelSessionPath,
                        audioMediaOptions: "LinkToSourceAudio",
                        audioHandleSize: 2000,
                        videoMediaOptions: "LinkToSourceVideo",
                        trackMatchOptions: "MatchTracks",
                        playlistOptions: "ImportOverlayNewOnExistingPlaylists",
                        importClipGain: true,
                        importClipsAndMedia: true,
                        importVolumeAutomation: false,
                        timecodeMappingUnits: "MaintainAbsoluteTimeCodeValues",
                        timecodeMappingStartTime: "00:00:00:00",
                        adjustSessionStartTimeToMatchSource: false,
                    });
                
                    //WE NEED TO WAIT HERE FOR THE FIRST REEL TO IMPORT BEFORE MOVING ON
                
                    //WAIT FOR PROGRESS BAR TO GO AWAY
                    sf.ui.proTools.waitForNoModals();
                    if(enableLogging.toLowerCase() === "yes"){
                        log("All Modals are closed");
                    }
                }
                
                1. Kitch Membery @Kitch2025-01-30 19:29:44.142Z

                  Hi Fergus,

                  Did you try it with a small wait after the import and before the sf.ui.proTools.waitForNoModals() method?

                  This may require a little setup on my side to test, so I'll endeavor to look into it early next week. :-)

                  1. Pinewood Studios @Pinewood_Studios
                      2025-01-31 15:45:15.137Z

                      I didn't try that yet no, sorry! I'll try and get round to it next week.

                      If you're going to set up to test this (and I really appreciate it!) it's worth noting that it seems to work fine on smaller sessions. But bigger sessions including automation, lots of tracks, files etc, seem to import in the wrong order.

                      Thanks again!

                      Fergus

                      1. Pinewood Studios @Pinewood_Studios
                          2025-01-31 18:03:08.981Z2025-01-31 22:40:22.361Z

                          Hey again Kitch, I got to test this today after all.

                          A 1000ms sf.wait does actually seem to help things! Obviously the wait time is a bit of a guessing game... I do wonder if a waitForModals() method would be a bit more robust. Would love to know your thoughts.. I'm no developer!

                          Fergus

                          1. Kitch Membery @Kitch2025-01-31 22:28:45.581Z

                            Hi Fergus?

                            I'll dig into this next week.

                            My thought is that the script might require an sf.waitFor() method with a custom callback to see when the action has been completed.

                            Is there something that happens to the session that proves the import has been successful? Working this out will be the key to finding a robust solution rather than an arbitrary wait.

                            1. Pinewood Studios @Pinewood_Studios
                                2025-01-31 22:40:11.009Z

                                I suppose given the purpose of this specific script, we know the import has been successful if there are additional clips on the timeline... or perhaps additional automation nodes if there are no clips to import. It's a difficult one I guess...

                                It is worth nothing though, that so far (and I've run the script a lot today) the 1 second arbitrary wait, followed by the waitForNoModals() method is flawless, so I really appreciate that tip from you.

                                Fergus

                                // PRO TOOLS START SCRIPT
                                    if (!sf.ui.proTools.isRunning) throw 'Pro Tools is not running';
                                    sf.ui.proTools.appActivateMainWindow();
                                
                                const enableLogging = "NO"
                                
                                sf.interaction.displayDialog({
                                        prompt: "This script will search the directory above the one containing currently open session, looking for reels 2 onwards. You should already have open a session containing reel 1 open. If you don't, please do this then re-run this script",
                                        buttons: ["Proceed","Cancel"],
                                        defaultButton: "Proceed",
                                });
                                
                                let numReels = Number(prompt("How many reels are there?"));
                                if (isNaN(numReels)) throw 0;
                                
                                const currentSessionPath = sf.app.proTools.getSessionPath().sessionPath.replace(/:/g, "/");
                                //const currentSessionDirectory = currentSessionPath.substring(0, currentSessionPath.lastIndexOf('/'));
                                const mainDirectory = currentSessionPath.substring(0, currentSessionPath.lastIndexOf('/', currentSessionPath.lastIndexOf('/') - 1));
                                const possibleDirectories = sf.file.directoryGetDirectories({path: mainDirectory}).paths
                                
                                if(enableLogging.toLowerCase() === "yes"){
                                    log(possibleDirectories);
                                }
                                
                                let sessionToImportPath;
                                let allSessionPaths;
                                let firstMatchingReelSessionPath;
                                let directoryToTest;
                                
                                const possibleDirectoryNames = [
                                    "R",
                                    "R0",
                                    "REEL",
                                    "R-",
                                    "R_",
                                    "R-0",
                                    "R_0"
                                ];
                                
                                for (let index = 2 ; index<numReels+1; index++ ){
                                
                                    if(enableLogging.toLowerCase() === "yes"){
                                        log("Resetting Variables..");
                                    }
                                
                                    //Reset the paths
                                    sessionToImportPath = null
                                    firstMatchingReelSessionPath = null
                                    allSessionPaths = null
                                
                                    for (const directoryName of possibleDirectoryNames) {
                                
                                        if(enableLogging.toLowerCase() === "yes"){
                                            log(`Trying combination: ${directoryName}${index}`);
                                        };
                                        //sf.wait({intervalMs: 100});
                                
                                        directoryToTest = possibleDirectories.filter(directory => directory.includes(`${directoryName}${index}`))[0]
                                
                                        if(!directoryToTest){
                                            if(enableLogging.toLowerCase() === "yes"){
                                                log(`No possibilities found for combination ${directoryName}${index}`);
                                            }
                                            //Move to next possibility
                                            continue;
                                        }
                                
                                        //log("Testing " + directoryToTest);
                                
                                        if (sf.file.directoryExists({path: directoryToTest}).exists){
                                            if(enableLogging.toLowerCase() === "yes"){
                                                log("Successfully found: " + directoryToTest)
                                            }
                                            sessionToImportPath = directoryToTest;
                                            break;
                                        }
                                    }
                                
                                    //If we found a folder path, we then search for the .ptx file within it.
                                    //If none or multiple .ptx sessions are found within, then we ask the
                                    //user to select the right one
                                    if(sessionToImportPath){
                                
                                        allSessionPaths = sf.file.directoryGetFiles({ path: sessionToImportPath, searchPattern: '*.ptx' }).paths;
                                
                                        if(allSessionPaths.length > 1){
                                
                                            if(enableLogging.toLowerCase() === "yes"){
                                                log(`Multiple .ptx sessions were found for Reel ${index}. Prompting for manual selection.`);
                                            }
                                            firstMatchingReelSessionPath = sf.interaction.selectFile({
                                                allowedFileTypes: ["ptx"],
                                                prompt: `Multiple ptx sessions found for Reel ${index}. Please select the .ptx file for this reel.`,
                                                defaultLocation: sessionToImportPath
                                            }).path;
                                
                                        } else if(allSessionPaths.length === 0){
                                            
                                            if(enableLogging.toLowerCase() === "yes"){
                                                log(`No .ptx sessions were found for Reel ${index}. Prompting for manual selection.`);
                                            }
                                            firstMatchingReelSessionPath = sf.interaction.selectFile({
                                                allowedFileTypes: ["ptx"],
                                                prompt: `No ptx sessions found for Reel ${index}. Please select the .ptx file for this reel.`,
                                                defaultLocation: sessionToImportPath
                                            }).path;
                                
                                        } else {
                                
                                            if(enableLogging.toLowerCase() === "yes"){
                                                log(`One .ptx session was found for Reel ${index}.`);
                                            }
                                            firstMatchingReelSessionPath = allSessionPaths[0];
                                
                                        }
                                    
                                    } else {
                                
                                        if(enableLogging.toLowerCase() === "yes"){
                                            log(`No folder was found for Reel ${index}. Prompting for manual selection.`);
                                        }
                                
                                        firstMatchingReelSessionPath = sf.interaction.selectFile({
                                            allowedFileTypes: ["ptx"],
                                            prompt: `Reel ${index} folder not found. Please select the .ptx file for this reel.`
                                        }).path;
                                    }
                                
                                    if(enableLogging.toLowerCase() === "yes"){
                                        log(`Importing: ${firstMatchingReelSessionPath}`);
                                    }
                                
                                    sf.app.proTools.importSessionData({
                                        sessionPath: firstMatchingReelSessionPath,
                                        audioMediaOptions: "LinkToSourceAudio",
                                        audioHandleSize: 2000,
                                        videoMediaOptions: "LinkToSourceVideo",
                                        trackMatchOptions: "MatchTracks",
                                        playlistOptions: "ImportOverlayNewOnExistingPlaylists",
                                        importClipGain: true,
                                        importClipsAndMedia: true,
                                        importVolumeAutomation: false,
                                        timecodeMappingUnits: "MaintainAbsoluteTimeCodeValues",
                                        timecodeMappingStartTime: "00:00:00:00",
                                        adjustSessionStartTimeToMatchSource: false,
                                    });
                                
                                    //WE NEED TO WAIT HERE FOR THE FIRST REEL TO IMPORT BEFORE MOVING ON
                                    sf.wait({intervalMs: 1000});
                                
                                    //WAIT FOR PROGRESS BAR TO GO AWAY
                                    sf.ui.proTools.waitForNoModals();
                                    if(enableLogging.toLowerCase() === "yes"){
                                        log("All Modals are closed");
                                    }
                                }
                                
                                1. Kitch Membery @Kitch2025-01-31 22:48:45.554Z

                                  When you run the importSessionData does the import happen all in one go? Or does it do it track by track/clip by clip etc?

                                  If it happens in one go, you could have the sf.waitFor() callback check the track count or clip count, and when it changes move on.

                                  If you could upload a screen recording of the script running with the sf.wait({intervalMs: 1000});, that would be great.

                                  1. Pinewood Studios @Pinewood_Studios
                                      2025-02-03 20:59:31.674Z

                                      Hi Kitch,

                                      No problem at all. I will run the script when I next have the chance and send the video.

                                      Fergus

                                      1. Pinewood Studios @Pinewood_Studios
                                          2025-02-04 09:47:26.726Z
                                          1. Kitch Membery @Kitch2025-02-04 20:03:24.950Z

                                            Thanks, Fergus.

                                            The video was helpful... Are you by chance around to jump on a quick Zoom call?

                                            1. Pinewood Studios @Pinewood_Studios
                                                2025-02-04 20:11:08.663Z

                                                I am yes, feel free to send an invite to fergus.pateman@pinewoodgroup.com.

                                                Fergus

                                                1. Kitch Membery @Kitch2025-02-04 20:14:34.504Z

                                                  Email sent :-)

                                                  1. Kitch Membery @Kitch2025-02-04 20:20:59.256Z

                                                    Hi Fergus, did you get the Zoom link I emailed?

                                                    1. Pinewood Studios @Pinewood_Studios
                                                        2025-02-04 20:22:51.591Z

                                                        I did not.. could you possibly re-send? Or alternatively I can call you.

                                                        Fergus

                                                        1. Kitch Membery @Kitch2025-02-04 20:25:24.277Z

                                                          I'll resend it right now.

                                                          1. Pinewood Studios @Pinewood_Studios
                                                              2025-02-04 20:29:38.800Z

                                                              Nothing yet. Could you try fergus.pateman@gmail.com instead? Might be getting caught up in our company filter.

                                                              Fergus

                                                              1. Kitch Membery @Kitch2025-02-04 20:31:34.172Z

                                                                Sent :-)

                                                            • Kitch Membery @Kitch2025-02-04 20:28:09.571Z

                                                              Sent.

                                                              1. Kitch Membery @Kitch2025-02-04 20:29:30.924Z

                                                                If you did not receive the link, please send me an email at support@soundflow.org. :-)

                                                        2. Kitch Membery @Kitch2025-02-04 21:28:40.666Z

                                                          Hi Fergus,

                                                          As we spoke about on our call, here is a possible solution using the sf.waitFor() method to wait for new clips to be added to the session, this will hopefully prove that each import has finished.

                                                          // Make sure the Clips List is open
                                                          
                                                          const proTools = sf.ui.proTools;
                                                          const mainWindow = proTools.mainWindow;
                                                          const clipsList = mainWindow.clipListView;
                                                          const rows = clipsList.childrenByRole("AXRow");
                                                          
                                                          const originalClipCount = rows.invalidate().length;
                                                          
                                                          // Main code to import here here
                                                          
                                                          sf.waitFor({
                                                              callback: () => rows.invalidate().length > originalClipCount,
                                                              timeout: 10000,
                                                          });
                                                          

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