No internet connection
  1. Home
  2. How to

Go to Closest Marker?

By Owen Granich-Young @Owen_Granich_Young
    2024-08-26 18:41:58.436Z

    Does anybody have a piece of code that goes to the CLOSEST marker - wether it's before or after the 'current timeline selection?' Not finding something of that nature, nor 100% sure how I'd best implement it. Could be Track specific if that's easier but any track/ruler probably better?

    Thanks,
    Owen

    • 11 replies
    1. B
      Brandon Jiaconia @Brandon_Jiaconia
        2024-08-26 19:03:24.811Z

        In the Glenn PT package by @Glenn_Eanes there is a Go To Nearest Marker command - here is the 'View Source':

        //Get original TC
        const originalTC = sf.ui.proTools.getCurrentTimecode().stringValue;
        
        //Calling command "Extend Selection to Previous Marker" from package "undefined" (installed from user/pkg/version "srAasovvDiQacRZ2mcId4RrOA8R2/ckp49i4j60000a2100yfwywgf/cl5crym5u00037710iypigwju")
        sf.soundflow.runCommand({
            commandId: 'user:ckp49i4j60000a2100yfwywgf:ckou1qcq5007pzv100i8xeycq',
            props: {}
        });
        
        // toPrevSamps is the length from original TC to the previous marker in samples
        const toPrevSamps = sf.ui.proTools.selectionGetInSamples().selectionLength;
        
        //Go back to original TC
        sf.ui.proTools.selectionSetTimecode({
            mainCounter: originalTC,
        });
        
        
        //Calling command "Extend Selection to Next Marker" from package "undefined" (installed from user/pkg/version "srAasovvDiQacRZ2mcId4RrOA8R2/ckp49i4j60000a2100yfwywgf/cl5crym5u00037710iypigwju")
        sf.soundflow.runCommand({
            commandId: 'user:ckp49i4j60000a2100yfwywgf:ckou1qcq5007ozv10n96bgqcj',
            props: {}
        });
        
        // toNextSamps is the length from original TC to the next marker in samples
        const toNextSamps = sf.ui.proTools.selectionGetInSamples().selectionLength;
        
        //If previous marker is closer go to it, otherwise stay on next marker
        if (toPrevSamps < toNextSamps) {
            //Calling command "Go to Previous Marker" from package "undefined" (installed from user/pkg/version "srAasovvDiQacRZ2mcId4RrOA8R2/ckp49i4j60000a2100yfwywgf/cl5crym5u00037710iypigwju")
            sf.soundflow.runCommand({
                commandId: 'user:ckp49i4j60000a2100yfwywgf:ckou1qcq5007nzv10fdrue0q0',
                props: {}
            });
        } else {
            sf.ui.proTools.selectionSetTimecode({
                mainCounter: originalTC,
                selectionLength: "00:00:00:00"
            });
        
            //Calling command "Go to Next Marker" from package "undefined" (installed from user/pkg/version "srAasovvDiQacRZ2mcId4RrOA8R2/ckp49i4j60000a2100yfwywgf/cl5crym5u00037710iypigwju")
            sf.soundflow.runCommand({
                commandId: 'user:ckp49i4j60000a2100yfwywgf:ckou1qcq5007mzv10u5biiplz',
                props: {}
            });
        }
        
        
        1. Interesting, I'll check out his package thanks.

          1. Hmm that bugs out, but at least it gives me some ideas. I prolly have to do this one by hand if someone hasn't built.

        2. Raphael Sepulveda @raphaelsepulveda2024-08-26 22:30:23.503Z2024-08-26 22:41:27.515Z

          @Owen_Granich_Young, a little mathy math 🤝 PT SDK *

          function goToNearestMemoryLocation() {
              const memoryLocations = sf.app.proTools.memoryLocations.invalidate()
                  .allItems.map(memLoc => memLoc);
                  
              const playheadLocationSamples = Number(sf.app.proTools.getTimelineSelection({
                  timeScale: "Samples"
              }).inTime);
          
              // Sort Memory Locations by distance to playhead
              memoryLocations.sort((a, b) => {
                  const aDistanceToPlayhead = Number(a.startTimeInSamples) - playheadLocationSamples;
                  const bDistanceToPlayhead = Number(b.startTimeInSamples) - playheadLocationSamples;
                  return Math.abs(aDistanceToPlayhead) - Math.abs(bDistanceToPlayhead);
              });
          
              sf.app.proTools.selectMemoryLocation({ number: memoryLocations[0].number });
          }
          
          goToNearestMemoryLocation();
          

          *Not specific to a marker ruler or track

          1. Sweeeeet! Now I didn't have to figure it out. This one's going in the 'useful A F' Functions pile.

            1. Ok I built it. Clips sync point to closest marker.

              function goToNearestMemoryLocation() {
                  const memoryLocations = sf.app.proTools.memoryLocations.invalidate()
                      .allItems.map(memLoc => memLoc);
              
                  const playheadLocationSamples = Number(sf.app.proTools.getTimelineSelection({
                      timeScale: "Samples"
                  }).inTime);
              
                  // Sort Memory Locations by distance to playhead
                  memoryLocations.sort((a, b) => {
                      const aDistanceToPlayhead = Number(a.startTimeInSamples) - playheadLocationSamples;
                      const bDistanceToPlayhead = Number(b.startTimeInSamples) - playheadLocationSamples;
                      return Math.abs(aDistanceToPlayhead) - Math.abs(bDistanceToPlayhead);
                  });
              
                  sf.app.proTools.selectMemoryLocation({ number: memoryLocations[0].number });
              }
              
              function main() {
                  sf.app.proTools.cut()
                  goToNearestMemoryLocation()
                  sf.app.proTools.paste()
                  sf.keyboard.press({
                      keys: "j",
                      fast: true
                  })
              
              }
              
              main();
              
              1. Yo Raph, would it be easy to filter it to do closest marker on selected track? Deff been having a few hickups in working with this and that making it selected track/s specific would take a lot of problem cases out of the equation.

                1. Yeah, not as clean as the first one but this will get it done 👇🏼

                  /** @param {{ scope?: "Global" | "Selected Track" }} [args] */
                  function goToNearestMemoryLocation({ scope = "Global" } = {}) {
                      let memoryLocations = sf.app.proTools.memoryLocations.invalidate()
                          .allItems.map(memLoc => memLoc);
                  
                      if (scope === "Selected Track") {
                          // Get selected track
                          const selectedTrack = sf.app.proTools.tracks.invalidate()
                              .allItems.find(track => track.isSelected);
                  
                          if (selectedTrack) { // If there is a selected track...
                              // Filter Memory Locations by selected track name
                              memoryLocations = memoryLocations.filter(memLoc =>
                                  memLoc.trackName === selectedTrack.name
                              );
                          } // If not, revert to "Global" scope behaviour
                      }
                  
                      if (memoryLocations.length === 0) return;
                  
                      const playheadLocationSamples = Number(sf.app.proTools.getTimelineSelection({
                          timeScale: "Samples"
                      }).inTime);
                  
                      // Sort Memory Locations by distance to playhead
                      memoryLocations.sort((a, b) => {
                          const aDistanceToPlayhead = Number(a.startTimeInSamples) - playheadLocationSamples;
                          const bDistanceToPlayhead = Number(b.startTimeInSamples) - playheadLocationSamples;
                          return Math.abs(aDistanceToPlayhead) - Math.abs(bDistanceToPlayhead);
                      });
                  
                      sf.app.proTools.selectMemoryLocation({ number: memoryLocations[0].number });
                  }
                  
                  goToNearestMemoryLocation({ scope: "Selected Track" });
                  

                  Oh, and in anticipation of the follow-up question—no, we unfortunately cannot query different marker lanes just yet lol Hopefully soon 🤞🏼

                  1. haha yeah I know about the different marker lane issue sadly.

              2. G
                Glenn Eanes @Glenn_Eanes
                  2024-08-27 00:21:24.633Z

                  Thanks @raphaelsepulveda
                  @Owen_Granich_Young, it's been a while since I wrote the Glenn PT package. Pro tools has progressed a lot in the markers department.

                  1. Oh I have quite a number of those packages in the store myself LOL