No internet connection
  1. Home
  2. Support

Logic: create send to next unused Bus/Aux

By Matthew Brabender @Matthew_Brabender
    2025-09-03 10:51:05.179Z

    Title

    Logic: create send to next unused Bus/Aux

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

    The script is designed to (on key trigger), on the selected channel strip, create a send for the next unused Bus in Logic. To do this, I create a new aux track, change the input so the bus matches the aux number in it's track name, search for the initial track name and activate a send to a Bus that matches the aux number from the aux track name.

    Steps:

    1. Copy name of current selected track
    2. Save track name from clipboard to a const (targetTrackName)
    3. Create a new Aux track
    4. Create track from selected channel strip
    5. Copy the Aux track name, remove the first 4 characters and save as const (targetAuxName)
    6. Change the input of the selected track to 'Bus+targetAuxName' : e.g. Bus 1
    7. Search for and select the track saved from step 1 (targetTrackName)
      8 Activate next send slot and choose 'Bus+targetAuxName' : e.g Bus 1

    Are you seeing an error?

    Line 70 cannot read property ‘slice’ of null

    Line 84
    Not an error but I cannot figure out how to use const targetAuxName to define bus number for the input

    Line 102
    cannot read property ‘text’ of null

    Line 112
    Not an error but I cannot figure out how to use const targetAuxName to define bus number for the send

    What happens when you run this script?

    Line 70 cannot read property ‘slice’ of null ** The track name copies if I remove the slice function but then I cannot remove the first 4 characters to get the bus number

    Line 84
    Not an error but I cannot figure out how to use const targetAuxName to define bus number for the input
    ** This sets the input of the channel strip to Bus 1. What I want it to do is set the track input to Bus + targetAuxName (the const created at Line 70). So the result would be Bus 10 or Bus 12 depending on what text is copied.

    Line 102
    cannot read property ‘text’ of null
    I'm trying to paste const targetTrackName into Logic's track search function. The search pop-up appears but it does not paste any text

    Line 112
    Not an error but I cannot figure out how to use const targetAuxName to define bus number for the send
    ** This activates a send (after the last used send slot) and selects Bus 1. What I want it to do is set the send to Bus + targetAuxName (const created at Line 70). SO the result would be Bus 10 or Bus 12 depending on what text is copied.

    How were you running this script?

    I used a keyboard shortcut within the target app

    How important is this issue to you?

    4

    Details

    {
        "inputExpected": "The script is designed to (on key trigger), on the selected channel strip, create a send for the next unused Bus in Logic. To do this, I create a new aux track, change the input so the bus matches the aux number in it's track name, search for the initial track name and activate a send to a Bus that matches the aux number from the aux track name.\n\nSteps:\n1. Copy name of current selected track\n2. Save track name from clipboard to a const (targetTrackName)\n3. Create a new Aux track\n4. Create track from selected channel strip\n5. Copy the Aux track name, remove the first 4 characters and save as const (targetAuxName)\n6. Change the input of the selected track to 'Bus+targetAuxName' : e.g. Bus 1\n7. Search for and select the track saved from step 1 (targetTrackName)\n8 Activate next send slot and choose 'Bus+targetAuxName' : e.g Bus 1\n",
        "inputIsError": true,
        "inputError": "Line 70\ncannot read property ‘slice’ of null\n\nLine 84\nNot an error but I cannot figure out how to use const targetAuxName to define bus number for the input\n\nLine 102\ncannot read property ‘text’ of null\n\nLine 112\nNot an error but I cannot figure out how to use const targetAuxName to define bus number for the send",
        "inputWhatHappens": "Line 70\ncannot read property ‘slice’ of null\n** The track name copies if I remove the slice function but then I cannot remove the first 4 characters to get the bus number\n\nLine 84\nNot an error but I cannot figure out how to use const targetAuxName to define bus number for the input\n** This sets the input of the channel strip to Bus 1. What I want it to do is set the track input to Bus + targetAuxName (the const created at Line 70). So the result would be Bus 10 or Bus 12 depending on what text is copied.\n\nLine 102\ncannot read property ‘text’ of null\nI'm trying to paste const targetTrackName into Logic's track search function. The search pop-up appears but it does not paste any text\n\nLine 112\nNot an error but I cannot figure out how to use const targetAuxName to define bus number for the send\n** This activates a send (after the last used send slot) and selects Bus 1. What I want it to do is set the send to Bus + targetAuxName (const created at Line 70). SO the result would be Bus 10 or Bus 12 depending on what text is copied.",
        "inputHowRun": {
            "key": "-Mpfwh4RkPLb2LPwjePT",
            "title": "I used a keyboard shortcut within the target app"
        },
        "inputImportance": 4,
        "inputTitle": "Logic: create send to next unused Bus/Aux"
    }

    Source

    //Select Logic tracks window
    const logic = sf.ui.logic;
    logic.appActivate();
    
    if (!logic.windows.first.title.invalidate().value.includes("- Tracks")) {
        logic.windows.whoseTitle.contains("- Tracks").first.elementRaise();
    }
    // Rename track to copy track name
    //Calling command "Rename Track" from package "Logic Pro" (installed from user/pkg/version "uOwKfD26NbWKAWotin3dmnSne7B3/cli50xtc200015210vyksy31z/cmb732i3200076c105jdwbr7t")
    sf.soundflow.runCommand({
        commandId: 'user:cli50xtc200015210vyksy31z:clik0aumb0018y510wqhabfnv#clik0bt08001ey510jaun4zbx',
        props: {}
    });
    //Calling command "Copy" from package "Logic Pro" (installed from user/pkg/version "uOwKfD26NbWKAWotin3dmnSne7B3/cli50xtc200015210vyksy31z/cmb732i3200076c105jdwbr7t")
    sf.soundflow.runCommand({
        commandId: 'user:cli50xtc200015210vyksy31z:clijh236g00002a10lu6m2wya#clijh3vmo00052a1031r528rb',
        props: {}
    });
    // Save track name for later
    const targetTrackName = sf.clipboard.getText().text;
    // track name is copied, escape so track name is not changed
    sf.keyboard.press({
        keys: "escape",
    });
    // clear the clipboard
    sf.clipboard.clear();
    // Select Logic Mixer window
    const logic = sf.ui.logic;
    logic.appActivate();
    
    if (!logic.windows.first.title.invalidate().value.includes(" - Mixer: ")) {
        logic.windows.whoseTitle.contains(" - Mixer: ").first.elementRaise();
    }
    sf.wait({
        intervalMs: 300,
    });
    // Create new Aux Track
    sf.keyboard.press({
        keys: "ctrl+n",
    });
    sf.wait({
        intervalMs: 300,
    });
    //Create track from selected channel strip
    sf.keyboard.press({
        keys: "ctrl+t",
    });
    //Select Logic tracks window
    const logic = sf.ui.logic;
    logic.appActivate();
    
    if (!logic.windows.first.title.invalidate().value.includes("- Tracks")) {
        logic.windows.whoseTitle.contains("- Tracks").first.elementRaise();
    }
    sf.wait({
        intervalMs: 300,
    });
    //Rename track to copy track name
    //Calling command "Rename Track" from package "Logic Pro" (installed from user/pkg/version "uOwKfD26NbWKAWotin3dmnSne7B3/cli50xtc200015210vyksy31z/cmb732i3200076c105jdwbr7t")
    sf.soundflow.runCommand({
        commandId: 'user:cli50xtc200015210vyksy31z:clik0aumb0018y510wqhabfnv#clik0bt08001ey510jaun4zbx',
        props: {}
    });
    //Calling command "Copy" from package "Logic Pro" (installed from user/pkg/version "uOwKfD26NbWKAWotin3dmnSne7B3/cli50xtc200015210vyksy31z/cmb732i3200076c105jdwbr7t")
    sf.soundflow.runCommand({
        commandId: 'user:cli50xtc200015210vyksy31z:clijh236g00002a10lu6m2wya#clijh3vmo00052a1031r528rb',
        props: {}
    });
    // Remove first 4 characters fom Aux track name and save for line 82
    const targetAuxName = sf.clipboard.getText().text.slice(4);
    // Aux number is copied, escape so Aux track name is not changed
    sf.keyboard.press({
        keys: "escape",
    });
    // clear the clipboard
    sf.clipboard.clear();
    sf.wait({
        intervalMs: 300,
    });
    //Change track input to "Bus targetAuxNumber"
    // **** How do I script setting the input? The command on line 82 doesn't show how it's done
    
    //Calling command "Bus 1" from package "Logic Pro" (installed from user/pkg/version "uOwKfD26NbWKAWotin3dmnSne7B3/cli50xtc200015210vyksy31z/cmb732i3200076c105jdwbr7t")
    sf.soundflow.runCommand({
        commandId: 'user:cli50xtc200015210vyksy31z:clu03689y0009uu10vuhi0j7n#cmf24l6ro0002qa10b3jzlyf3',
        props: {}
    });
    
    sf.wait({
        intervalMs: 500,
    });
    
    // Search for and select targetTrackName
    sf.keyboard.press({
        keys: "alt+shift+s",
    });
    sf.wait({
        intervalMs: 500,
    });
    // **** Logic doesn't paste text below ****
    sf.keyboard.type({
        text: targetTrackName.text,
    });
    sf.keyboard.press({
        keys: "return",
    });
    
    //Activate send after last used spot : send to "Bus targetAuxName"
    // **** How do I script setting the input? The command on line 109 doesn't show how it's done
    
    //Calling command "Send Bus 1 Next Slot" from package "Logic Pro" (installed from user/pkg/version "uOwKfD26NbWKAWotin3dmnSne7B3/cli50xtc200015210vyksy31z/cmb732i3200076c105jdwbr7t")
    sf.soundflow.runCommand({
        commandId: 'user:cli50xtc200015210vyksy31z:clq50eqoa0001nw10nlym6zru#cmf1koz5l0006eq10utijeiz6',
        props: {}
    });
    
    
    

    Links

    User UID: CCVZiNKDLnOhmcBRhT5Jhj9bmi33

    Feedback Key: sffeedback:CCVZiNKDLnOhmcBRhT5Jhj9bmi33:-OZEBtryNsXxZDAAjdqF

    Feedback ZIP: W9pYfW+bAasNIXp+Vc93MLofOsXbtt9BjTelo6avSMPRKf38q/RKJEDgA9R2vNuYEDUSadQ/SaLRppULTSfcGXUgLCeQxerHZwucBJRcJxQD/bYV70ATKmLJxOT4YwV0B3f2muWaQB0VksOtbxmKTlXMDP48/jlVOyrKpRvmg01gW365unBxf8Mhm6B/wz+Uey8U8AWvE0zRRv1pXhp+bim0fFBbHEdCTbjCAJka4D5DcQoS9oICx/i7Q3x6Tb7vEY2nphJ9hZfaZmXTVjrNLRrhlJCFkbWfoLuDgtIBp6XWgjDhtIAeCn5L0z/sFMCeIK95Lwx9ifG3nG0cefsWAx7689iumA9QpXEyGEdukjg=

    Solved in post #8, click to view
    • 11 replies

    There are 11 replies. Estimated reading time: 12 minutes

    1. Chad Wahlbrink @Chad2025-09-03 15:37:55.451Z

      @Kitch, do you want to take a look at this with Matthew?

      1. Kitch Membery @Kitch2025-09-04 01:33:56.542Z

        Hi @Matthew_Brabender

        Can I get you to do a screen recording, walking through the manual steps to create this workflow, so I can get a better understanding of what you are after?

        Thanks in advance. :-)

        1. Matthew Brabender @Matthew_Brabender
            2025-09-04 01:35:02.731Z

            Sure thing Kitch. Many thanks for jumping in :)

          • Matthew Brabender @Matthew_Brabender
              2025-09-04 03:33:34.374Z

              Hi Kitch. I uploaded a screen grab video and tried to explain what I'm trying to do. Open to suggestions and also understand if it's not really possible.
              https://drive.google.com/file/d/1sXguyVfHyfPIfp0iEL7kD7LVPWlp0_pF/view?usp=sharing

              1. Kitch Membery @Kitch2025-09-08 06:42:52.697Z

                This is very Helpful @Matthew_Brabender,

                This workflow is in slightly uncharted territory, so I will see what I can do this week. :-)

                1. Matthew Brabender @Matthew_Brabender
                    2025-09-08 06:45:17.088Z

                    I was wondering if I was trying to do something that's a bit odd-ball hahaha - totally makes sense in my mind ... I've tried templates with pre-setup effects etc but usually end up doing something completely different in each song. That's how I came to chasing this down :)
                    Many thanks Kitch :)

                2. Kitch Membery @Kitch2025-09-09 07:38:31.501Z

                  Hi @Matthew_Brabender

                  Take this version for a spin!

                  const logic = sf.ui.logic;
                  
                  function getFirstSelectedTrack() {
                      const tracksArea = logic.mainWindow.invalidate()
                          .groups.whoseDescription.is('Tracks').first
                          .groups.whoseDescription.is('Tracks');
                  
                      const trackHeaders = tracksArea
                          .allItems[1].splitGroups
                          .first.splitGroups
                          .allItems[1].scrollAreas
                          .first.groups
                          .whoseDescription.is('Tracks header').first;
                  
                      const selectedTrackHeader = trackHeaders.getElements('AXSelectedChildren')[0];
                  
                      return selectedTrackHeader;
                  }
                  
                  function getTrackName(track) {
                      const trackName = track.getString("AXDescription").match(/“(.*)”/)[1];
                      return trackName;
                  }
                  
                  function focusTrack(track) {
                      sf.ui.logic.appActivateMainWindow();
                  
                      const hasFocusBtn = track.radioButtons.first;
                  
                      hasFocusBtn.elementSetAttributeValue({
                          attributeName: "AXFocused",
                          attributeValue: true
                      });
                  
                      hasFocusBtn.elementClick();
                  
                      sf.ui.logic.appActivateMainWindow();
                  }
                  
                  /**
                   * Sets popup menu's menu path and waits for the menu to close before moving on.
                   * @param {Object} args
                   * @param {AxElement} args.popupMenu
                   * @param {String[]} args.menuPath
                   */
                  function popupMenuSelect({ popupMenu, menuPath }) {
                      // Set the target popup menu's menu path if the menu is not already set correctly, based on the last item in the menu path.
                      if (popupMenu.invalidate().value.value !== menuPath[menuPath.length - 1]) {
                          popupMenu.popupMenuSelect({ menuPath });
                      };
                  
                      // Wait for the popup menu to close
                      sf.waitFor({
                          // When a popup menu is open in Logic Pro it's first child element is an AXMenu item.
                          // This callback will wait for the AXMenu to no longer exist, in turn ensuring that the popup menu has closed.
                          callback: () => !popupMenu.invalidate().children.whoseRole.is("AXMenu").first.exists,
                          timeout: 1000,
                      });
                  }
                  
                  function main() {
                      // Focus Logic Pro's main window
                      sf.ui.logic.appActivateMainWindow();
                  
                      const audioTrack = getFirstSelectedTrack();
                      //const audioTrackName = getTrackName(audioTrack);
                  
                      const dockedMixer = sf.ui.logic.mainWindow.invalidate().getFirstWithDescription("Mixer");
                  
                      // Ensure the Docked Mixer is open
                      if (!dockedMixer.exists) {
                          sf.ui.logic.menuClick({ menuPath: ["View"] });
                          sf.ui.logic.menuClick({ menuPath: ["View", "Show Mixer"] });
                  
                          dockedMixer.elementWaitFor();
                      }
                  
                      const optionsMenu = dockedMixer
                          .getFirstWithDescription("Mixer").invalidate()
                          .groups.first
                          .children.whoseRole.is("AXMenuButton")
                          .whoseDescription.is("Options").first;
                  
                      // Create New Auxiliary Channel Strip
                      popupMenuSelect({
                          popupMenu: optionsMenu,
                          menuPath: ["Create New Auxiliary Channel Strip"],
                      });
                  
                      // Create Tracks for Selected Channel Strips
                      popupMenuSelect({
                          popupMenu: optionsMenu,
                          menuPath: ["Create Tracks for Selected Channel Strips"],
                      });
                  
                      // Close the Docked Mixer
                      if (dockedMixer.exists) {
                          sf.ui.logic.menuClick({ menuPath: ["View"] });
                          sf.ui.logic.menuClick({ menuPath: ["View", "Hide Mixer"] });
                  
                          dockedMixer.elementWaitFor();
                      }
                  
                      // Focus Logic Pro's main window
                      sf.ui.logic.appActivateMainWindow();
                  
                      // Get the number from the Aux track name
                      const auxTrack = getFirstSelectedTrack();
                      const auxTrackName = getTrackName(auxTrack);
                      const auxTrackNumber = auxTrackName.match(/\d+$/)[0];
                  
                      // Set input of Aux track
                      // Calling command "Select Track Input" from package "Logic Pro"
                      sf.soundflow.runCommand({
                          commandId: 'user:cli50xtc200015210vyksy31z:clu03689y0009uu10vuhi0j7n',
                          props: {
                              inputPath: ["Bus", `Bus ${auxTrackNumber}`],
                          }
                      });
                  
                      // Reselect the Audio Track
                      focusTrack(audioTrack);
                  
                      // Open send on Audio track
                      // Calling command "Sends Loader" from package "Logic Pro"
                      sf.soundflow.runCommand({
                          commandId: 'user:cli50xtc200015210vyksy31z:clq50eqoa0001nw10nlym6zru',
                          props: {
                              sendPath: ["Bus", `Bus ${auxTrackNumber}`],
                          }
                      });
                  }
                  
                  main();
                  

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

                  ReplySolution
                  1. Matthew Brabender @Matthew_Brabender
                      2025-09-09 09:43:38.195Z

                      Thanks so much Kitch! It works up to line 114 and then errors. It creates and new aux track and then creates a track from that channel strip so that's all good. It's when it gets to setting the input path for the aux channel strip it stops.

                      09.09.2025 19:39:55.63 [Backend]: [AutomationPresetEvaluator] Couldn't find element type definition reference for array property 'inputPath': '' - propertyDef is {"_key":"propertyDefNode1","_type":"PropertyDefNode","props":{"scriptName":{"const":"inputPath"},"title":{"const":"Input Path"},"type":{"type":"String[]"}}}

                      09.09.2025 19:39:55.63 [Backend]: Logic Pro version: 11.2.2

                      09.09.2025 19:39:55.63 [Backend]: Logic Pro version: 11.2.2
                      [NSRunningApplication (static)] Checking for running apps with bundle 'com.apple.logic10'

                      09.09.2025 19:39:55.63 [Backend]: NSArray.ArrayFromHandle count = 1

                      09.09.2025 19:39:55.66 [Backend]: Logic Pro version: 11.2.2
                      [NSRunningApplication (static)] Checking for running apps with bundle 'com.apple.logic10'

                      09.09.2025 19:39:55.66 [Backend]: NSArray.ArrayFromHandle count = 1

                      09.09.2025 19:39:55.68 [Backend]: Logic Pro version: 11.2.2

                      09.09.2025 19:39:55.74 [Backend]: Mouse current pos is: (508.4415283203125, 312.17681884765625)
                      Clicking with mouse here: (70, 30)

                      09.09.2025 19:39:55.74 [Backend]: Moving mouse back to: (508.4415283203125, 312.17681884765625)

                      09.09.2025 19:39:55.75 [Backend]: Position is now: (508.4415283203125, 312.17681884765625)

                      09.09.2025 19:39:55.77 [Backend]: Logic Pro version: 11.2.2

                      09.09.2025 19:39:55.87 [Backend]: Mouse current pos is: (508.4415283203125, 312.17681884765625)
                      Clicking with mouse here: (505.5, 501)

                      09.09.2025 19:39:55.88 [Backend]: Moving back...

                      09.09.2025 19:39:55.88 [Backend]: Position is now: (508.4415283203125, 312.17681884765625)

                      09.09.2025 19:39:58.19 [Backend]: Logging error in action (01) WaitForPopupMenuAction: Popup window was not found after waiting 2000 ms
                      Logging error in action (01) OpenPopupMenuFromElementAction: Popup menu was not found
                      Logging error in action (01) PopupMenuSelectAction: Could not open popup menu

                      09.09.2025 19:39:58.21 [Backend]: Logging unknown error in action (02) RunCommandAction: LogicProModule: Line 531

                      09.09.2025 19:39:58.23 [Backend]: JavaScript error with InnerException: Could not open popup menu (LogicProModule: Line 531)
                      !! Command Error: Unused Bus Send [user:default:cmfc9yrph0000v910l0jlunra]:
                      Error: LogicProModule: Line 531
                      (Unused Bus Send line 114)

                    • Matthew Brabender @Matthew_Brabender
                        2025-09-09 10:38:48.747Z2025-09-09 10:45:51.921Z

                        Actually Kitch, I put in a wait function before the line throwing an error and now it works perfectly. Amazing! Gosh this saves so much mousing around.
                        Many many thanks!! I'm wowed that you figured it out.
                        I've mapped the key command for this to my UF8 controller, so now when I need a new send, hit the button and it's ready to roll.
                        Really really appreciate it Kitch!

                        1. Kitch Membery @Kitch2025-09-09 16:01:41.752Z

                          That's awesome! Glad you got it working!

                          When I have some more time, I'll see if I can improve the script so that the wait function can be removed. :-)

                          1. Matthew Brabender @Matthew_Brabender
                              2025-09-09 20:25:20.293Z

                              Much appreciated Kitch. The wait is set to only 300ms and it works great so all good :D