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:
- Copy name of current selected track
- Save track name from clipboard to a const (targetTrackName)
- Create a new Aux track
- Create track from selected channel strip
- Copy the Aux track name, remove the first 4 characters and save as const (targetAuxName)
- Change the input of the selected track to 'Bus+targetAuxName' : e.g. Bus 1
- 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=
Chad Wahlbrink @Chad2025-09-03 15:37:55.451Z@Kitch, do you want to take a look at this with Matthew?
In reply toMatthew_Brabender⬆:Kitch Membery @Kitch2025-09-04 01:33:56.542ZCan 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. :-)
Matthew Brabender @Matthew_BrabenderSure thing Kitch. Many thanks for jumping in :)
In reply toMatthew_Brabender⬆:Matthew Brabender @Matthew_BrabenderHi 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
Kitch Membery @Kitch2025-09-08 06:42:52.697ZThis is very Helpful @Matthew_Brabender,
This workflow is in slightly uncharted territory, so I will see what I can do this week. :-)
Matthew Brabender @Matthew_BrabenderI 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 :)
In reply toMatthew_Brabender⬆:Kitch Membery @Kitch2025-09-09 07:38:31.501ZTake 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. :-)
Matthew Brabender @Matthew_BrabenderThanks 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 menu09.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)
In reply toMatthew_Brabender⬆:Matthew Brabender @Matthew_BrabenderActually 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!
Kitch Membery @Kitch2025-09-09 16:01:41.752ZThat'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. :-)
Matthew Brabender @Matthew_BrabenderMuch appreciated Kitch. The wait is set to only 300ms and it works great so all good :D