No internet connection
  1. Home
  2. How to

Logic Pro X: How to automate printing tracks

By Oscar Fogelstrom @Oscar_Fogelstrom
    2020-01-29 15:59:08.464Z

    Printing tracks.
    A very simple request (?)
    Is it possible to select the top track, and then

    1. Have soundflow "press" ctrl + B (For bouncing in place)
    2. Move down one track
    3. Check if there are regions on that track.
    4. IF there are regions on that track, "press" ctrl + B (For bouncing in place)
    5. Otherwise move down one track
    6. Until the bottom track is reached
    Solved in post #18, click to view
    • 26 replies

    There are 26 replies. Estimated reading time: 16 minutes

    1. Hi Oscar.

      What's your version of Logic?
      I think some of these steps should be fairly easy, but this one: "Check if there are regions on that track." is the hard one.

      1. OOscar Fogelstrom @Oscar_Fogelstrom
          2020-01-29 19:33:11.268Z

          I understand.
          I’m on Logic 10.4.4

          1. OOscar Fogelstrom @Oscar_Fogelstrom
              2020-02-03 08:46:45.830Z

              Correction, I am on Logic 10.4.8

          2. Do you want it to replace the track, create a new track or just export the regions?

            I guess the point of the script is to make it possible to play the session without any plugins, so basically what you have to do when you deliver your session to Netflix or similar?

            1. Jesper Ankarfeldt @JesperA2020-01-29 23:55:17.202Z2020-02-03 19:19:15.663Z

              Anyway here's a script that should do all you need. If it fails maybe take a screen grab so we can see how/when it fails.
              You an see I've used "Bounce Region in Place", and the current settings the menu have. You could add to the script that it sets specific settings.
              But maybe try with a simple session and see how it works first.

              Also you should make sure you are using SF 3.5:

              var app = sf.ui.app('com.apple.logic10')
              
              function checkTrackName() {
                  sf.clipboard.clear();
                  app.getMenuItem('Track', 'Rename Track').elementClick();
                  app.getMenuItem('Edit', 'Copy').elementClick();
                  sf.keyboard.press({ keys: 'escape' })
                  var trackName = sf.clipboard.waitForText().text;
                  sf.wait({ intervalMs: 100 })
                  return trackName
              }
              
              function checkForRegionsOnSelectedTrack() {
                  app.getMenuItem('Edit', 'Select', 'Deselect All').elementClick();
                  sf.keyboard.press({ keys: 'right' })
                  sf.wait({ intervalMs: 500 })
                  if (app.getMenuItem('Edit', 'Repeat', 'Once').isEnabled)
                      return true
                  else return false
              }
              
              function checkForLastTrack() {
                  var oldTrackName = checkTrackName()
                  sf.keyboard.press({ keys: 'down' })
                  var newTrackName = checkTrackName();
                  if (oldTrackName == newTrackName)
                      return true
                  else return false
              }
              
              function waitForBounceToComplete() {
                  while (true) {
                      try {
                          if (!app.windows.whoseTitle.is('Logic Pro X').first.exists) {
                              //We didn't get an error - and the modal popup doesn't exist.
                              //Break out, the bounce is complete
                              break;
                          }
                      } catch (err) {
                          //We got an error. Logic is still busy. Continue with another loop
                      }
              
                      //Wait a bit before continuing
                      sf.wait({ intervalMs: 200 });
                  }
              }
              
              function bounceRegions() {
                  app.getMenuItem('File', 'Bounce', 'Regions in Place...').elementClick();
                  app.mainWindow.sheets.first.elementWaitFor();
                  app.mainWindow.sheets.first.buttons.whoseTitle.is('OK').first.elementClick({
                      asyncSwallow: true
                  });
              
                  //Wait for the progress window to appear
                  sf.wait({ intervalMs: 2000 });
              
                  //Wait for the progress window to disappear
                  waitForBounceToComplete();
              }
              
              function main() {
                  while (true) {
                      if (checkForRegionsOnSelectedTrack()) {
                          app.getMenuItem('Edit', 'Select', 'All Following of Same Track').elementClick();
                          sf.wait({ intervalMs: 100 })
                          bounceRegions()
                      }
                      if (checkForLastTrack()) {
                          log('Command Finished', 'Last Track Reached')
                          break;
                      }
                  }
              }
              
              main();
              
              1. I love this script!! This is good work.

                1. In reply toJesperA:
                  OOscar Fogelstrom @Oscar_Fogelstrom
                    2020-01-30 07:30:11.336Z

                    Great, thanks!! Let me try today!

                    1. In reply toJesperA:
                      Kitch Membery @Kitch2020-02-01 11:16:05.534Z

                      Fantastic script Jesper this one will come in handy!

                      I only had to change one thing to make it work for me in both 10.4.5 and 10.4.8.

                      I changed "Regions in Place..." to "Regions in Place…" (The three dots are typed with option + ";" rather than three periods in a row.)

                      Thanks for this one mate.
                      K

                      1. Great to hear it works for you @Kitch.
                        I've done something similar in Cubase, so could fairly easily see how it could be made.
                        Got a little help from Christian with the "waitForBounceToComplete" part, as that was tricky, cause Logic didn't directly give any info when it starts bouncing.
                        That great thing about making the scripts in functions like this is that you can easily copy them in to other scripts.

                        1. Kitch Membery @Kitch2020-02-03 09:18:10.103Z

                          I love the use of functions to build the complete workflow. I will definitely be adopting this process from here on out. :-)

                        2. In reply toKitch:
                          OOscar Fogelstrom @Oscar_Fogelstrom
                            2020-02-03 08:55:39.118Z

                            Kitch: When I type option + ";" I get "‚‚‚"

                            1. Kitch Membery @Kitch2020-02-03 09:14:00.560Z

                              It works for me hmmmm. Just copy and paste this "…" into the script.

                              1. OOscar Fogelstrom @Oscar_Fogelstrom
                                  2020-02-03 09:38:23.207Z

                                  Yeah, now it did something different. It seems it bounces the audio tracks, but not the midi tracks for me at this point

                                  1. Kitch Membery @Kitch2020-02-03 10:28:12.783Z

                                    I think that this line if (app.getMenuItem('Edit', 'Move', 'To Recorded Position').isEnabled) is what is stopping the midi from printing.

                                    I changed it to this if (app.getMenuItem('Edit', 'Repeat', 'Once').isEnabled)

                                    It now prints both Audio and Midi tracks. :-)

                                    1. OOscar Fogelstrom @Oscar_Fogelstrom
                                        2020-02-05 05:26:45.501Z

                                        thnx! will check!

                                      • Interesting. I guess I only tried with Audio in the session I sat with, so maybe @Kitch fix above works?

                                        1. Kitch Membery @Kitch2020-02-04 02:54:12.809Z

                                          Hi Jesper

                                          I liked this script so much I decided to add a few lines to to iron out some of Logic Pro's quirks.

                                          In the bounceRegion function I added sf.keyboard.press({ keys: "alt+shift+n", }); (this changes the tracks regions to the same name as the track) so that the newly bounced track names would reflect the original track names.
                                          I then added the following three lines;

                                              app.mainWindow.sheets.first.checkBoxes.whoseTitle.is('Bypass Effect Plug-ins').first.checkboxSet({ targetValue: "Disable", });
                                              app.mainWindow.sheets.first.checkBoxes.whoseTitle.is('Include Audio Tail in File').first.checkboxSet({ targetValue: "Enable", });
                                              app.mainWindow.sheets.first.checkBoxes.whoseTitle.is('Include Audio Tail in Region').first.checkboxSet({ targetValue: "Enable", });
                                          

                                          ... to make sure the track effect plugins are not bypassed and that the audio & effects reverb tails are added to the bounced in place region(s).

                                          Thanks again for sharing this script it will come in very handy!

                                          Here it is edited script;

                                          var app = sf.ui.app('com.apple.logic10')
                                          
                                          function checkTrackName() {
                                              sf.clipboard.clear();
                                              app.getMenuItem('Track', 'Rename Track').elementClick();
                                              app.getMenuItem('Edit', 'Copy').elementClick();
                                              sf.keyboard.press({ keys: 'escape' })
                                              var trackName = sf.clipboard.waitForText().text;
                                              sf.wait({ intervalMs: 100 })
                                              return trackName
                                          }
                                          
                                          function checkForRegionsOnSelectedTrack() {
                                              app.getMenuItem('Edit', 'Select', 'Deselect All').elementClick();
                                              sf.keyboard.press({ keys: 'right' })
                                              sf.wait({ intervalMs: 500 })
                                              if (app.getMenuItem('Edit', 'Repeat', 'Once').isEnabled)
                                                  return true
                                              else return false
                                          }
                                          
                                          function checkForLastTrack() {
                                              var oldTrackName = checkTrackName()
                                              sf.keyboard.press({ keys: 'down' })
                                              var newTrackName = checkTrackName();
                                              if (oldTrackName == newTrackName)
                                                  return true
                                              else return false
                                          }
                                          
                                          function waitForBounceToComplete() {
                                              while (true) {
                                                  try {
                                                      if (!app.windows.whoseTitle.is('Logic Pro X').first.exists) {
                                                          //We didn't get an error - and the modal popup doesn't exist.
                                                          //Break out, the bounce is complete
                                                          break;
                                                      }
                                                  } catch (err) {
                                                      //We got an error. Logic is still busy. Continue with another loop
                                                  }
                                          
                                                  //Wait a bit before continuing
                                                  sf.wait({ intervalMs: 200 });
                                              }
                                          }
                                          
                                          function bounceRegions() {
                                              sf.keyboard.press({ keys: "alt+shift+n", });
                                              app.getMenuItem('File', 'Bounce', 'Regions in Place…').elementClick();
                                              app.mainWindow.sheets.first.elementWaitFor();
                                              app.mainWindow.sheets.first.checkBoxes.whoseTitle.is('Bypass Effect Plug-ins').first.checkboxSet({ targetValue: "Disable", });
                                              app.mainWindow.sheets.first.checkBoxes.whoseTitle.is('Include Audio Tail in File').first.checkboxSet({ targetValue: "Enable", });
                                              app.mainWindow.sheets.first.checkBoxes.whoseTitle.is('Include Audio Tail in Region').first.checkboxSet({ targetValue: "Enable", });
                                              app.mainWindow.sheets.first.buttons.whoseTitle.is('OK').first.elementClick({
                                                  asyncSwallow: true
                                              });
                                          
                                              //Wait for the progress window to appear
                                              sf.wait({ intervalMs: 2000 });
                                          
                                              //Wait for the progress window to disappear
                                              waitForBounceToComplete();
                                          }
                                          
                                          function main() {
                                              while (true) {
                                                  if (checkForRegionsOnSelectedTrack()) {
                                                      app.getMenuItem('Edit', 'Select', 'All Following of Same Track').elementClick();
                                                      sf.wait({ intervalMs: 100 })
                                                      bounceRegions()
                                                  }
                                                  if (checkForLastTrack()) {
                                                      log('Command Finished', 'Last Track Reached')
                                                      break;
                                                  }
                                              }
                                          }
                                          
                                          main();
                                          
                                          Reply1 LikeSolution
                                          1. Nice, yeah that's a great usage, and to use checkBoxes is a rock solid way.

                                            1. In reply toKitch:
                                              OOscar Fogelstrom @Oscar_Fogelstrom
                                                2020-02-05 05:35:37.154Z

                                                Yes, this works great! Thanks a million! (Had a weird ”hickup” the first time I ran it, but now it seems to run very smoothly!) Will save me hours printing tracks for mix. Thanks!!!

                                                1. In reply toKitch:
                                                  Kitch Membery @Kitch2020-02-05 05:37:04.852Z

                                                  @Oscar_Fogelstrom be sure to use the above script.... It will include plugin effects processing and audio tails into your bounce in place. It will also name your tracks correctly with a suffix of “_bip”.

                                                  1. OOscar Fogelstrom @Oscar_Fogelstrom
                                                      2020-02-05 05:38:23.796Z

                                                      Yup, the above version is what I used. Thanks

                                        2. In reply toJesperA:
                                          OOscar Fogelstrom @Oscar_Fogelstrom
                                            2020-02-03 08:53:28.333Z

                                            I can't seem to get it to work.

                                          • G
                                            Gareth Gwyn @Gareth_Gwyn
                                              2021-11-17 13:07:50.735Z

                                              Is there a way to bounce each track out separately within logic using sound flow?
                                              1, Have sound flow solo a track
                                              2, "Press" Command + B and bounce within location markers
                                              3, Move down 1 track and start again

                                              Thank you!

                                              1. R
                                                Ryan Hayes @Ryan_Hayes
                                                  2021-12-22 18:12:30.461Z2021-12-22 22:39:01.290Z

                                                  Here is a simple one that i made for my stems and it names the bounce and goes through check box values. Change to your liking. This will work for logic 10.7.1. Make sure your tracks are selected and solo'd then run the command. Working on making it into a string to do multiple stems. For now this makes it quicker to sum down parts into stems or new tracks. Hope this helps. Make sure groups arent on or it may not work.

                                                  Ryan

                                                  sf.ui.app('com.apple.logic10').appActivate();
                                                  
                                                  sf.keyboard.press({
                                                      keys: "ctrl+b",
                                                  });
                                                  
                                                  sf.wait({
                                                      intervalMs: 200,
                                                  });
                                                  
                                                  sf.keyboard.press({
                                                      keys: "backspace",
                                                  });
                                                  
                                                  sf.wait({
                                                      intervalMs: 200,
                                                  });
                                                  
                                                  sf.keyboard.type({
                                                      text: "Keys Sum",
                                                  });
                                                  
                                                  sf.wait({
                                                      intervalMs: 100,
                                                  });
                                                  
                                                  sf.ui.app("com.apple.logic10").mainWindow.sheets.first.radioButtons.whoseTitle.is("New Track").first.checkboxSet({
                                                      targetValue: "Enable",
                                                  });
                                                  
                                                  sf.wait({
                                                      intervalMs: 100,
                                                  });
                                                  
                                                  sf.ui.app("com.apple.logic10").mainWindow.sheets.first.checkBoxes.whoseTitle.is("Bypass Effect Plug-ins").first.checkboxSet({
                                                      targetValue: "Disable",
                                                  });
                                                  
                                                  sf.wait({
                                                      intervalMs: 100,
                                                  });
                                                  
                                                  sf.ui.app("com.apple.logic10").mainWindow.sheets.first.radioButtons.whoseTitle.is("Mute").first.checkboxSet({
                                                      targetValue: "Enable",
                                                  });
                                                  
                                                  sf.wait({
                                                      intervalMs: 100,
                                                  });
                                                  
                                                  sf.ui.app("com.apple.logic10").mainWindow.sheets.first.checkBoxes.whoseTitle.is("Include Volume/Pan Automation").first.checkboxSet({
                                                      targetValue: "Enable",
                                                  });
                                                  
                                                  sf.keyboard.press({
                                                      keys: "return",
                                                  });
                                                  
                                                  1. Hey Ryan,

                                                    Thanks for sharing.
                                                    Please check this tutorial for how to quote code in the SoundFlow forum, so that it displays in a readable format:

                                                    1. RRyan Hayes @Ryan_Hayes
                                                        2021-12-22 22:32:43.046Z2021-12-22 22:41:16.779Z

                                                        Ah Thanks was looking for that.