Hello everyone.
I'm trying to allow Andrew's "Free Up Selected Insert" script to run from the Mix Window.
//focus protools
sf.ui.proTools.appActivate();
//Close Focused Floating Window
sf.ui.proTools.viewCloseFocusedFloatingWindow();
//memory original window
let originalWin = sf.ui.proTools.focusedWindow.title.value.split(":").slice(0, 1).join(":")
/**
* @param {array} path - menu full path
* @param {'Enable'|'Disable'} targetValue
*/
function menuClick(path, targetValue) {
sf.ui.proTools.menuClick({ menuPath: path, targetValue: targetValue });
}
/**
* @param {String} menuName - Menu Name
*/
function getMenuItems(menuName) {
// Get path of current enabled && disabled items from menu
let menuItems = sf.ui.proTools.getMenuItem(menuName).popupMenuFetchAllItems().menuItems
let menuEnabled = menuItems.filter(x =>
x.element.isMenuChecked ||
x.element.getString('AXMenuItemMarkChar') === ('-')).map(x => [menuName].concat(x.path.slice()))
let menuDisabled = menuItems.filter(x =>
!x.element.isMenuChecked &&
x.element.getString('AXMenuItemMarkChar') !== ('-')).map(x => [menuName].concat(x.path.slice()))
sf.ui.proTools.appActivateMainWindow()
let menu = {
menuAllEnabled: menuEnabled,
menuAllDisabled: menuDisabled
}
return menu
}
let viewMenu = getMenuItems("View")
////show edit window
function mainWindowStatus() {
if (sf.ui.proTools.getMenuItem('Window', 'Edit').isMenuChecked) {
} else {
sf.ui.proTools.menuClick({
menuPath: ['Window', 'Edit'],
});
}
}
mainWindowStatus();
//Scroll into view
sf.ui.proTools.selectedTrack.trackScrollToView();
//Calling command "Free Up Selected Insert Slot" from package "Free Up Selected Insert" (installed from user/pkg/version "sp8S3ewi4RhTvy8g6wz5cBzljUJ2/cklw7570m0009w810dhpo7beu/cklw9cgrx000iw810j6a04eak")
sf.soundflow.runCommand({
commandId: 'user:1628941673647:cklw75ain000aw810q6rb6wer',
props: {}
});
//show original window
sf.ui.proTools.menuClick({ menuPath: ["Window", originalWin] });
When I run it from the mix window, it switches to the Edit Window, applies the "Track Scroll To View" macro, and returns to the Mix Window when it's done.
One problem is that if I select multiple tracks and then run my script, all but the first selected track will be deselected and I can only run on one track.
Andrew's script, which can be executed on multiple tracks, is in a regrettable state.
Is there any way to apply Track Scroll To View with multiple tracks selected?
- MMasayoshi Sugai @Masayoshi_Sugai
In addition to the previous question, I noticed that the "Close Focused Floating Window" behavior in my script was not intended.
The expected behavior is that the floating window that is active in the foreground, but the script closes all floating windows. The plug-in window with the target button off and memory location window will also be closed at once. This looks like Close All Floating Windows behavior.
As a test, when I make a macro with only Close Focused Floating Window and run it, it works as expected.Am I making a mistake in my script?
samuel henriques @samuel_henriques
Hello Masayoshi Sugai,
for the scroll to view, from what I've learned, every way pro tools scrolls tracks to view, will do it for the first track only, (other than mouse scroll), so we need to follow that behaviour in soundFlow. This is one common way to do it:
// Get all selected tracks const selectedTracks = sf.ui.proTools.selectedTrackNames // Select first tracks sf.ui.proTools.trackSelectByName({ names: [selectedTracks[0]] }); // Scroll first track to view sf.ui.proTools.selectedTrack.trackScrollToView(); // Select original selection sf.ui.proTools.trackSelectByName({ names: selectedTracks });
As for
sf.ui.proTools.viewCloseFocusedFloatingWindow();
is it closing more than one window at once? On my system, it closes the first focused window, but doesn't what window it is. If I run it again, it will close the next window, and so on until there are no more windows.If you want to close only the first plugin window, you can try:
// Close first plug-in window sf.ui.proTools.floatingWindows.whoseTitle.startsWith("Plug-in: ").allItems[0].windowClose()
Let me know if this helped
samuel henriques @samuel_henriques
I noticed you found this
getMenuItems()
function, to set the menus back to original you can use it this way:// set original views menuClick(viewMenu.menuAllEnabled, "Enable") menuClick(viewMenu.menuAllDisabled, "Disable")
- MMasayoshi Sugai @Masayoshi_Sugai
Hi, Samuel.
Thank you for your help!
I was able to run the script with multiple tracks selected!Andrew's "Free Up Selected Insert Slot" script doesn't work unless the desired track is displayed in the Edit Window, so if some of the selected tracks are invisible as a result of Scroll Tracks View, I have to scroll manually. (like the video in the link)
https://www.dropbox.com/s/pwopg7n3nd9e9ya/Free Up Selected Insert Slot%232.mov?dl=0
But anyway, this can do what I want to do! Thank you!!!sf.ui.proTools.viewCloseFocusedFloatingWindow ();
I'm sorry about this, it was my misunderstanding. It seems that Andrew's "Free Up Selected Insert Slot" script already contains a command to close all floating windows. (I can't turn this off, right?)
// set original views menuClick (viewMenu.menuAllEnabled, "Enable") menuClick (viewMenu.menuAllDisabled, "Disable")
Does this mean that it will replace the following part at the end of my script?
// show original window sf.ui.proTools.menuClick ({menuPath: ["Window", originalWin]});
excuse me. I'm still not sure about this, and I tried replacing it with some possible places, but it didn't work.
samuel henriques @samuel_henriques
Hey Masayoshi,
Does Andrew's free up script part fail if you don't show all tracks?, I would guess that it would scroll to view every selected track.
Try this instead, to scroll to top of the screen, you'll still have the same problem if there are more selected tracks than can fit the screen.// Make sure track lis is visible sf.ui.proTools.menuClick({ menuPath: ["View", "Other Displays", "Track List"], targetValue: "Enable" }) // Get all items from track list const trackList = sf.ui.proTools.trackListItems // Get all selected tracks const selectedTracks = sf.ui.proTools.selectedTrackNames // Scroll first track to view const indexOfFirstSelected = trackList.findIndex(x => x.normalizedTrackName == selectedTracks[0]) trackList[indexOfFirstSelected].children.whoseRole.is("AXCell").allItems[1].buttons.first.mouseClickElement({ isControl: true, isShift: true }) // Select original selection sf.ui.proTools.trackSelectByName({ names: selectedTracks });
I don't know if you can prevent closing all floating windows, I'm sure he made that behaviour so no window can be on top of the inserts, as that would prevent the movement of the slots. But you can try asking him if he can adjust it for your needs, there is a forum area for each package, ask him there.
This part on your code is meant to save all the view settings, so when you change them during the script, you can recall them with
menuClick(viewMenu.menuAllEnabled, "Enable")
andmenuClick(viewMenu.menuAllDisabled, "Disable")
, if you are not changing anythig, you don't need any of this code./** * @param {String} menuName - Menu Name */ function getMenuItems(menuName) { // Get path of current enabled && disabled items from menu let menuItems = sf.ui.proTools.getMenuItem(menuName).popupMenuFetchAllItems().menuItems let menuEnabled = menuItems.filter(x => x.element.isMenuChecked || x.element.getString('AXMenuItemMarkChar') === ('-')).map(x => [menuName].concat(x.path.slice())) let menuDisabled = menuItems.filter(x => !x.element.isMenuChecked && x.element.getString('AXMenuItemMarkChar') !== ('-')).map(x => [menuName].concat(x.path.slice())) sf.ui.proTools.appActivateMainWindow() let menu = { menuAllEnabled: menuEnabled, menuAllDisabled: menuDisabled } return menu } let viewMenu = getMenuItems("View")
this you need to move back to mix, or stay in edit if that was your original window.
// show original window sf.ui.proTools.menuClick ({menuPath: ["Window", originalWin]});
- MMasayoshi Sugai @Masayoshi_Sugai
Hello, Samuel!
Now Scroll To Track works perfectly! !! It works completely automatically!
I also understand the code that I don't need. It worked even if I deleted the part that taught me. I'm still in the process of finding and combining scripts that seem to suit my purpose, so I'll study more.
I'd like to ask Andrew about Close All Floating Windows, but this is fine as the current specifications have the fewest malfunctions and I can also recall the meter plugin using Window Configuration.This script is complete! Thank you very much!
- In reply tosamuel_henriques⬆:MMasayoshi Sugai @Masayoshi_Sugai
Hi, Samuel!
Thank you for always supporting me !!
This Track Scroll View (selected all tracks) script is very useful!I recently noticed that this script doesn't work in my environment under certain conditions.
The attached screenshot shows a Pro Tools session with 100 tracks.-When the number of tracks in the session is large, when the scroll bar of the Track List on the left of the Edit Window is at the top, the movement is as expected, but the scroll bar is scrolled below the top. Then "// Scroll first track to view" in the script will not work (Image 1_The position of this scrollbar in the track list causes an error)
-When the number of tracks in a session is large, "// Scroll first track to view" in the script will not work for tracks that do not fit in the list at the bottom of the track list (Image 2_
"Scroll first track to view" does not work for Track76-100)To make the mixing workflow easier, I've been experimenting with scripts like selecting multiple tracks from the Mix Window and creating a new AUX send, and I'd like to be able to make this script work reliably in large mix sessions. Is there any good way to do this?
- MMasayoshi Sugai @Masayoshi_Sugai
samuel henriques @samuel_henriques
It seams to need some invalidating,
I managed to reproduce the error and this fixed it,
sf.ui.proTools.invalidate() // Get all selected tracks const selectedTracks = sf.ui.proTools.selectedTrackNames // Select first tracks sf.ui.proTools.trackSelectByName({ names: [selectedTracks[0]] }); // Scroll first track to view sf.ui.proTools.selectedTrack.trackScrollToView(); // Select original selection sf.ui.proTools.trackSelectByName({ names: selectedTracks });
The other scripts I made for creating aux, already take care of this.
- MMasayoshi Sugai @Masayoshi_Sugai
Thank you for your support many times, Samuel!
Certainly the latest scripts no longer cause errors due to the number of tracks or the position of the scrollbars in the track list!But as in previous posts, the desired behavior was "all selected tracks will be displayed in the Edit Window (as many as possible)".
"Track Scroll To View" with multiple Track selections #post-5For example, the following is the script I'm trying now, is to add features such as Mix Window> Edit Window to the "Create New Track from Send Menu on Selected Tracks Script" created by samuel.
Create New Track from Send Menu on Selected Tracks Script Help #post-6///Close Output Window_First if (sf.ui.proTools.mainTrackOutputWindow.exists) { sf.ui.proTools.mainTrackOutputWindow.windowClose(); } //memory original window let originalWin = sf.ui.proTools.focusedWindow.title.value.split(":").slice(0, 1).join(":") ////show edit window if (sf.ui.proTools.getMenuItem('Window', 'Edit').isMenuChecked) { } else { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Edit'], }); } /** * @param {array} path - menu full path * @param {'Enable'|'Disable'} targetValue */ function menuClick(path, targetValue) { sf.ui.proTools.menuClick({ menuPath: path, targetValue: targetValue }); } sf.ui.proTools.invalidate() // Get all selected tracks const selectedTracks = sf.ui.proTools.selectedTrackNames // Select first tracks sf.ui.proTools.trackSelectByName({ names: [selectedTracks[0]] }); // Scroll first track to view sf.ui.proTools.selectedTrack.trackScrollToView(); // Select original selection sf.ui.proTools.trackSelectByName({ names: selectedTracks }); /** * @param {string} sendAssignment */ function assignToNewTrack(sendAssignment) { const selectedTracks = sf.ui.proTools.selectedTrackNames sf.ui.proTools.trackGetByName({ name: selectedTracks[selectedTracks.length - 1] }).track.groups.whoseTitle.is(getGroup("Sends", sendAssignment)).first.buttons.whoseTitle.is(`Send Assignment ${sendAssignment}`).first.popupMenuSelect({ isShift: true, isOption: true, menuPath: ["new track..."], }); } function moveSendWinOutOfSlots() { sf.ui.proTools.invalidate() const sendWin = sf.ui.proTools.mainTrackOutputWindow.elementWaitFor().element const sendWinPos = sendWin.position.x const sendSlots = sf.ui.proTools.selectedTrack.groups.whoseTitle.is("Inserts A-E").first const sendSlotsPos = sendSlots.position.x if (sendWinPos - sendSlotsPos < 450 && sendSlotsPos - sendWinPos < 170) { sendWin.windowMove({ position: { y: sendWin.position.y, x: sendSlotsPos + 450 } }) } } function getFirstFreeSend() { const selectedTracks = sf.ui.proTools.selectedTrackHeaders const sendLetters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] let sendAssignmentList = [] for (let i = 0; i < selectedTracks.length; i++) { let trackInfo = sf.ui.proTools.trackGetByName({ name: selectedTracks[i].normalizedTrackName }) .track.sendButtons.filter(x => x.value.invalidate().value != "unassigned").map(x => x.title.invalidate().value.split(" ")[2]) sendAssignmentList.push(...trackInfo) } const firstFreeSend = sendLetters.filter(letter => sendAssignmentList.indexOf(letter) === -1)[0] if (firstFreeSend) { return firstFreeSend } else { alert("Must have at least one free send, that is the same for all tracks.") throw 0 }; }; /** * @param {'Insert'|'Send'} slotType * @param {array} [defaultUsedSlots] = [] - If parameter is not used, default is [] */ function getFirstFreeInsertOrSend(slotType, defaultUsedSlots) { let buttons slotType == "Insert" ? buttons = "insertButtons" : buttons = "sendButtons" const selectedTracks = sf.ui.proTools.selectedTrackHeaders const sendLetters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] let sendAssignmentList = defaultUsedSlots || [] try { for (let i = 0; i < selectedTracks.length; i++) { let trackInfo = sf.ui.proTools.trackGetByName({ name: selectedTracks[i].normalizedTrackName }) // .insertButtons or .sendButtons .track[buttons].filter(x => x.value.invalidate().value != "unassigned").map(x => x.title.invalidate().value.split(" ")[2]) sendAssignmentList.push(...trackInfo) } } catch (err) { } const firstFreeSend = sendLetters.filter(letter => sendAssignmentList.indexOf(letter) === -1)[0] if (firstFreeSend) { return firstFreeSend } else { if (slotType == "Insert") { alert(`Must have at least one free ${slotType} slot.`) } else if (slotType == "Send") { alert(`Must have at least one free ${slotType} slot, that is the same for selected tracks.`) } throw 0 }; }; /** * @param {string} sendLetter * @param {'Inserts'|'Sends'} slotType */ function getGroup(slotType, sendLetter) { let group sendLetter.toLowerCase().charCodeAt(0) - 97 <= 4 ? group = `${slotType} A-E` : group = `${slotType} F-J` return group } function newTrackSettings() { const newTrackWin = sf.ui.proTools.windows.whoseTitle.is("New Track").first.elementWaitFor().element const format = newTrackWin.popupButtons.whoseTitle.is("Stereo").first const type = newTrackWin.popupButtons.whoseTitle.is("Aux Input").first const timeBase = newTrackWin.popupButtons.whoseTitle.is("Samples").first if (format.value.invalidate().value != "Stereo") { format.popupMenuSelect({ menuPath: ["Stereo"] }); } if (type.value.invalidate().value != "Aux Input") { type.popupMenuSelect({ menuPath: ["Aux Input"] }); } if (timeBase.value.invalidate().value != "Samples") { timeBase.popupMenuSelect({ menuPath: ["Samples"] }); } newTrackWin.checkBoxes.whoseTitle.is("Create next to current track").first.checkboxSet({ targetValue: "Enable" }); // Wait to name track and press ok newTrackWin.elementWaitFor({ waitType: "Disappear", timeout: -1 }) sf.ui.proTools.invalidate() } /** * @param {'Enable'|'Disable'} targetValue * @param {array} [viewsNames] = [] - If parameter is not used, default is set inside */ function setWindowViews(targetValue, viewsNames) { let views = viewsNames || ["Inserts A-E", "Inserts F-J", "Sends A-E", "Sends F-J"] views.forEach(view => { sf.ui.proTools.menuClick({ menuPath: ["View", "Edit Window Views", view], targetValue: targetValue }) // sf.ui.proTools.menuClick({ menuPath: ["View", "Mix Window Views", view], targetValue: targetValue }) }) } const getSelectedTrackOut = (trackName) => sf.ui.proTools.trackGetByName({ name: trackName }).track.outputPathButton.title.invalidate().value.split('\n')[1].trim(); let insertSlot let firstFreeSend function actions() { const originalSelectedTracks = sf.ui.proTools.selectedTrackNames // Save first selected track output on variable const firstSelectedOut = getSelectedTrackOut(originalSelectedTracks[0]) // Get free sends firstFreeSend = getFirstFreeInsertOrSend("Send") // Assign new send to new track assignToNewTrack(firstFreeSend) // New track setting and wait for track name newTrackSettings() // If new send win is blocking the inserts or sends, move win away moveSendWinOutOfSlots() // Expand created send sf.ui.proTools.menuClick({ menuPath: ["View", "Expanded Sends", `Send ${firstFreeSend}`], targetValue: "Enable" }) // Solo safe new Aux const selectedTracks = sf.ui.proTools.selectedTrackNames const auxTrack = sf.ui.proTools.trackGetByName({ name: selectedTracks[selectedTracks.length - 1] }).track auxTrack.trackSelect() auxTrack.trackScrollToView() auxTrack.buttons.whoseTitle.is("Solo").first.mouseClickElement({ isCommand: true }) //Track Color sf.ui.proTools.colorsSelect({ colorNumber: 20, }); // set new aux output if (getSelectedTrackOut(auxTrack.normalizedTrackName) != firstSelectedOut) { auxTrack.trackOutputSelect({ outputSelector: items => items.filter(item => item.element.title.value.includes(firstSelectedOut))[0] }) } // Get free insert slot after A insertSlot = getFirstFreeInsertOrSend("Insert", ["A"]) // Open search... auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`) .first.popupMenuSelect({ menuPath: ["search..."], }); // Wait to open new plug while (true) { const plugIsOpen = auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`).first .value.invalidate().value != "unassigned" if (!plugIsOpen) { sf.wait({ intervalMs: 1000 }) } else { break; } } sf.ui.proTools.trackSelectByName({ names: originalSelectedTracks }) } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate(); // const isActiveInsGroupFMix = sf.ui.proTools.getMenuItem("View", "Mix Window Views", "Inserts F-J").isMenuChecked const isActiveInsGroupFEdit = sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Inserts F-J").isMenuChecked // const isActiveSendGroupFMix = sf.ui.proTools.getMenuItem("View", "Mix Window Views", "Sends F-J").isMenuChecked const isActiveSendGroupFEdit = sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Sends F-J").isMenuChecked const isEditWin = sf.ui.proTools.focusedWindow.title.value.startsWith("Edit") if (!isEditWin) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"] }) } // Close expand created sends sf.ui.proTools.menuClick({ menuPath: ["View", "Expanded Sends", "None"], targetValue: "Enable" }) setWindowViews("Enable") try { actions() } catch (err) { throw err } finally { // Close Inserts Views if not needed if (insertSlot.toLowerCase().charCodeAt(0) - 97 <= 4 && (/* !isActiveInsGroupFMix || */ !isActiveInsGroupFEdit)) { // if (!isActiveInsGroupFMix) { setWindowViews("Disable", ["Inserts F-J"]) } if (!isActiveInsGroupFEdit) { setWindowViews("Disable", ["Inserts F-J"]) } } // Close Sends F-J if not needed if (firstFreeSend.toLowerCase().charCodeAt(0) - 97 <= 4 && (/* !isActiveSendGroupFMix || */ !isActiveSendGroupFEdit)) { // if (!isActiveSendGroupFMix) { setWindowViews("Disable", ["Sends F-J"]) } if (!isActiveSendGroupFEdit) { setWindowViews("Disable", ["Sends F-J"]) } } } } main() //show original window sf.ui.proTools.menuClick({ menuPath: ["Window", originalWin] }); log("Create New AUX DONE!!!")
With the latest script pasted, the Tracks hidden at the top of the Edit Window can be scrolled to see all, but the Tracks hidden at the bottom of the Edit Window are only visible for the first track. , The command line beyond it will not continue.
For that reason, Samuel made me the previous script.
"Track Scroll To View" with multiple Track selections #post-6Ideally, it would be nice to be able to display all the selected tracks hidden below, as in the previous script. Is this possible?
I'm sorry to have you go out with this troublesome try many times!
thank you!- MMasayoshi Sugai @Masayoshi_Sugai
With the idea I just came up with, I'm not sure if this can be achieved with soundflow, I noticed that the selected tracks fit in the Edit Window regardless of the number of tracks or the display status of the track list when operating in the following order. ..
- Select multiple tracks on the Mix Window(or on the Edit Window)
- Shift + Control + Click the track name of the first selected track
- Switch to Edit Window
I will report it for the time being.
samuel henriques @samuel_henriques
It is possible to do shift+ctrl+track name on the track list and it will scroll to the top of the edit window. I'll try to do it later today.
- MMasayoshi Sugai @Masayoshi_Sugai
Hi, Samuel!
Thank you for your response!
I was wondering if it wouldn't work if there were selected tracks that were out of the track list in a session with a large number of tracks, and I thought it would work if I could directly click the selected track names of the tracks lined up in the Mix Window. (In that case, considering the work flow, I think that the selected track is always visible in the Window (Mix or Edit) being operated.)
But I don't know how to do it. .. When I try to pick up a UI Element on the Mix Window and make it into a script, it's difficult because the session name is involved. I need more study. ..
If Samuel's way of using track lists works, I'd love to know!
samuel henriques @samuel_henriques
So my idea has the same problem when the tracks are not visible on the track list, but this works regardless.
it will scroll to view the first track and then shift+ctrl+click it's name.
Try this and let me know.
sf.ui.proTools.appActivateMainWindow() sf.ui.proTools.invalidate() const selectedTracks = sf.ui.proTools.selectedTrackNames sf.ui.proTools.trackSelectByName({ names: [selectedTracks[0]] }) sf.ui.proTools.selectedTrack.trackScrollToView() sf.ui.proTools.selectedTrack.popupButtons.first.mouseClickElement({ isShift: true, isControl: true }) sf.ui.proTools.trackSelectByName({ names: selectedTracks })
- In reply toMasayoshi_Sugai⬆:Chris Shaw @Chris_Shaw2021-10-05 22:38:31.538Z
Why not use Track > Scroll to Track in the main menu? It works in both the Edit and Mix windows:
(thanks to @raphaelsepulveda )// Get originally selected tracks and first orig selected track const origSelectedTracks = sf.ui.proTools.selectedTrackNames; const firstSelectedTrack = origSelectedTracks[0]; /** * @param {string} trackName * @param {string[]} selectedTracks */ function scrollToTrackNamed(trackName, selectedTracks) { // Open scroll to track dialog and enter track name sf.ui.proTools.menuClick({ menuPath: ['Track', 'Scroll to Track...'] }); var confirmationDialogWin = sf.ui.proTools.confirmationDialog; confirmationDialogWin.elementWaitFor(); confirmationDialogWin.textFields.first.elementSetTextFieldWithAreaValue({ value: trackName }); confirmationDialogWin.buttons.whoseTitle.is('OK').first.elementClick(); confirmationDialogWin.elementWaitFor({ waitType: 'Disappear' }); //Re-select originally selected tracks sf.ui.proTools.trackSelectByName({ names: origSelectedTracks }) }; scrollToTrackNamed(firstSelectedTrack, origSelectedTracks);
- MIn reply toMasayoshi_Sugai⬆:Masayoshi Sugai @Masayoshi_Sugai
Thank you for your help !!!
Now I can do what I want to do perfectly!It's great to be able to run from either the Mix Window or the Wdit Window, and Samuerl's script works perfectly well among the scripts I've already created that contain the command to switch to Mix> Edit Window.
This seems to give me some of the scripts I wanted to make!
Thanks for your great advice!Samuel, I just want to ask one more question.
Is it possible to skip "// Wait to open new plug" and proceed when canceling the plugin search window with the Esc key in the "// Open Search ..." section of the above script? ??
"Track Scroll To View" with multiple Track selections #post-11// Open search... auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`) .first.popupMenuSelect({ menuPath: ["search..."], }); // Wait to open new plug while (true) { const plugIsOpen = auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`).first .value.invalidate().value != "unassigned" if (!plugIsOpen) { sf.wait({ intervalMs: 1000 }) } else { break; } }
Sorry for the question that deviates from the purpose of the thread. When I'm making a script myself, there are cases when I want to cancel the process at some point and stop the soundflow process, or when I want to skip that process and proceed.
I would be grateful if you could teach me how to skip using the previous "// Open Search ..." case of as an example.
samuel henriques @samuel_henriques
here you go,
// Wait while search is open while (true) { const searchWin = sf.ui.proTools.invalidate().windows.whoseTitle.startsWith("Search Inserts").exists if (searchWin) { sf.wait({ intervalMs: 1000 }) } else { break; } }
- MMasayoshi Sugai @Masayoshi_Sugai
Hi, Samuel!
I tried inserting what you told me between "// Open search ..." and "// Wait to open new plug", but it didn't work.
When I press the Esc key to close the plugin search window, the soundflow process doesn't end there, and it doesn't go any further, so I have to manually run the stop all command.sf.ui.proTools.appActivateMainWindow(); ///Close Output Window_First if (sf.ui.proTools.mainTrackOutputWindow.exists) { sf.ui.proTools.mainTrackOutputWindow.windowClose(); } //memory original window let originalWin = sf.ui.proTools.focusedWindow.title.value.split(":").slice(0, 1).join(":") // Get originally selected tracks and first orig selected track const origSelectedTracks = sf.ui.proTools.selectedTrackNames; const firstSelectedTrack = origSelectedTracks[0]; /** * @param {string} trackName * @param {string[]} selectedTracks */ function scrollToTrackNamed(trackName, selectedTracks) { // Open scroll to track dialog and enter track name sf.ui.proTools.menuClick({ menuPath: ['Track', 'Scroll to Track...'] }); var confirmationDialogWin = sf.ui.proTools.confirmationDialog; confirmationDialogWin.elementWaitFor(); confirmationDialogWin.textFields.first.elementSetTextFieldWithAreaValue({ value: trackName }); confirmationDialogWin.buttons.whoseTitle.is('OK').first.elementClick(); confirmationDialogWin.elementWaitFor({ waitType: 'Disappear' }); //Re-select originally selected tracks sf.ui.proTools.trackSelectByName({ names: origSelectedTracks }) }; scrollToTrackNamed(firstSelectedTrack, origSelectedTracks); /** * @param {array} path - menu full path * @param {'Enable'|'Disable'} targetValue */ function menuClick(path, targetValue) { sf.ui.proTools.menuClick({ menuPath: path, targetValue: targetValue }); } /** * @param {string} sendAssignment */ function assignToNewTrack(sendAssignment) { const selectedTracks = sf.ui.proTools.selectedTrackNames sf.ui.proTools.trackGetByName({ name: selectedTracks[selectedTracks.length - 1] }).track.groups.whoseTitle.is(getGroup("Sends", sendAssignment)).first.buttons.whoseTitle.is(`Send Assignment ${sendAssignment}`).first.popupMenuSelect({ isShift: true, isOption: true, menuPath: ["new track..."], }); } function moveSendWinOutOfSlots() { sf.ui.proTools.invalidate() const sendWin = sf.ui.proTools.mainTrackOutputWindow.elementWaitFor().element const sendWinPos = sendWin.position.x const sendSlots = sf.ui.proTools.selectedTrack.groups.whoseTitle.is("Inserts A-E").first const sendSlotsPos = sendSlots.position.x if (sendWinPos - sendSlotsPos < 450 && sendSlotsPos - sendWinPos < 170) { sendWin.windowMove({ position: { y: sendWin.position.y, x: sendSlotsPos + 450 } }) } } function getFirstFreeSend() { const selectedTracks = sf.ui.proTools.selectedTrackHeaders const sendLetters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] let sendAssignmentList = [] for (let i = 0; i < selectedTracks.length; i++) { let trackInfo = sf.ui.proTools.trackGetByName({ name: selectedTracks[i].normalizedTrackName }) .track.sendButtons.filter(x => x.value.invalidate().value != "unassigned").map(x => x.title.invalidate().value.split(" ")[2]) sendAssignmentList.push(...trackInfo) } const firstFreeSend = sendLetters.filter(letter => sendAssignmentList.indexOf(letter) === -1)[0] if (firstFreeSend) { return firstFreeSend } else { alert("Must have at least one free send, that is the same for all tracks.") throw 0 }; }; /** * @param {'Insert'|'Send'} slotType * @param {array} [defaultUsedSlots] = [] - If parameter is not used, default is [] */ function getFirstFreeInsertOrSend(slotType, defaultUsedSlots) { let buttons slotType == "Insert" ? buttons = "insertButtons" : buttons = "sendButtons" const selectedTracks = sf.ui.proTools.selectedTrackHeaders const sendLetters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] let sendAssignmentList = defaultUsedSlots || [] try { for (let i = 0; i < selectedTracks.length; i++) { let trackInfo = sf.ui.proTools.trackGetByName({ name: selectedTracks[i].normalizedTrackName }) // .insertButtons or .sendButtons .track[buttons].filter(x => x.value.invalidate().value != "unassigned").map(x => x.title.invalidate().value.split(" ")[2]) sendAssignmentList.push(...trackInfo) } } catch (err) { } const firstFreeSend = sendLetters.filter(letter => sendAssignmentList.indexOf(letter) === -1)[0] if (firstFreeSend) { return firstFreeSend } else { if (slotType == "Insert") { alert(`Must have at least one free ${slotType} slot.`) } else if (slotType == "Send") { alert(`Must have at least one free ${slotType} slot, that is the same for selected tracks.`) } throw 0 }; }; /** * @param {string} sendLetter * @param {'Inserts'|'Sends'} slotType */ function getGroup(slotType, sendLetter) { let group sendLetter.toLowerCase().charCodeAt(0) - 97 <= 4 ? group = `${slotType} A-E` : group = `${slotType} F-J` return group } function newTrackSettings() { const newTrackWin = sf.ui.proTools.windows.whoseTitle.is("New Track").first.elementWaitFor().element const format = newTrackWin.popupButtons.whoseTitle.is("Stereo").first const type = newTrackWin.popupButtons.whoseTitle.is("Aux Input").first const timeBase = newTrackWin.popupButtons.whoseTitle.is("Samples").first if (format.value.invalidate().value != "Stereo") { format.popupMenuSelect({ menuPath: ["Stereo"] }); } if (type.value.invalidate().value != "Aux Input") { type.popupMenuSelect({ menuPath: ["Aux Input"] }); } if (timeBase.value.invalidate().value != "Samples") { timeBase.popupMenuSelect({ menuPath: ["Samples"] }); } newTrackWin.checkBoxes.whoseTitle.is("Create next to current track").first.checkboxSet({ targetValue: "Enable" }); // Wait to name track and press ok newTrackWin.elementWaitFor({ waitType: "Disappear", timeout: -1 }) sf.ui.proTools.invalidate() } /** * @param {'Enable'|'Disable'} targetValue * @param {array} [viewsNames] = [] - If parameter is not used, default is set inside */ function setWindowViews(targetValue, viewsNames) { let views = viewsNames || ["Inserts A-E", "Inserts F-J", "Sends A-E", "Sends F-J"] views.forEach(view => { sf.ui.proTools.menuClick({ menuPath: ["View", "Edit Window Views", view], targetValue: targetValue }) // sf.ui.proTools.menuClick({ menuPath: ["View", "Mix Window Views", view], targetValue: targetValue }) }) } const getSelectedTrackOut = (trackName) => sf.ui.proTools.trackGetByName({ name: trackName }).track.outputPathButton.title.invalidate().value.split('\n')[1].trim(); let insertSlot let firstFreeSend function actions() { const originalSelectedTracks = sf.ui.proTools.selectedTrackNames // Save first selected track output on variable const firstSelectedOut = getSelectedTrackOut(originalSelectedTracks[0]) // Get free sends firstFreeSend = getFirstFreeInsertOrSend("Send") // Assign new send to new track assignToNewTrack(firstFreeSend) // New track setting and wait for track name newTrackSettings() // If new send win is blocking the inserts or sends, move win away moveSendWinOutOfSlots() // Expand created send sf.ui.proTools.menuClick({ menuPath: ["View", "Expanded Sends", `Send ${firstFreeSend}`], targetValue: "Enable" }) // Solo safe new Aux const selectedTracks = sf.ui.proTools.selectedTrackNames const auxTrack = sf.ui.proTools.trackGetByName({ name: selectedTracks[selectedTracks.length - 1] }).track auxTrack.trackSelect() auxTrack.trackScrollToView() auxTrack.buttons.whoseTitle.is("Solo").first.mouseClickElement({ isCommand: true }) //Track Color sf.ui.proTools.colorsSelect({ colorNumber: 20, }); // set new aux output if (getSelectedTrackOut(auxTrack.normalizedTrackName) != firstSelectedOut) { auxTrack.trackOutputSelect({ outputSelector: items => items.filter(item => item.element.title.value.includes(firstSelectedOut))[0] }) } // Get free insert slot after A insertSlot = getFirstFreeInsertOrSend("Insert", ["A"]) // Open search... auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`) .first.popupMenuSelect({ menuPath: ["search..."], }); // Wait while search is open while (true) { const searchWin = sf.ui.proTools.invalidate().windows.whoseTitle.startsWith("Search Inserts").exists if (searchWin) { sf.wait({ intervalMs: 1000 }) } else { break; } } // Wait to open new plug while (true) { const plugIsOpen = auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`).first .value.invalidate().value != "unassigned" if (!plugIsOpen) { sf.wait({ intervalMs: 1000 }) } else { break; } } sf.ui.proTools.trackSelectByName({ names: originalSelectedTracks }) } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate(); // const isActiveInsGroupFMix = sf.ui.proTools.getMenuItem("View", "Mix Window Views", "Inserts F-J").isMenuChecked const isActiveInsGroupFEdit = sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Inserts F-J").isMenuChecked // const isActiveSendGroupFMix = sf.ui.proTools.getMenuItem("View", "Mix Window Views", "Sends F-J").isMenuChecked const isActiveSendGroupFEdit = sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Sends F-J").isMenuChecked const isEditWin = sf.ui.proTools.focusedWindow.title.value.startsWith("Edit") if (!isEditWin) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"] }) } // Close expand created sends sf.ui.proTools.menuClick({ menuPath: ["View", "Expanded Sends", "None"], targetValue: "Enable" }) setWindowViews("Enable") try { actions() } catch (err) { throw err } finally { // Close Inserts Views if not needed if (insertSlot.toLowerCase().charCodeAt(0) - 97 <= 4 && (/* !isActiveInsGroupFMix || */ !isActiveInsGroupFEdit)) { // if (!isActiveInsGroupFMix) { setWindowViews("Disable", ["Inserts F-J"]) } if (!isActiveInsGroupFEdit) { setWindowViews("Disable", ["Inserts F-J"]) } } // Close Sends F-J if not needed if (firstFreeSend.toLowerCase().charCodeAt(0) - 97 <= 4 && (/* !isActiveSendGroupFMix || */ !isActiveSendGroupFEdit)) { // if (!isActiveSendGroupFMix) { setWindowViews("Disable", ["Sends F-J"]) } if (!isActiveSendGroupFEdit) { setWindowViews("Disable", ["Sends F-J"]) } } } } main() //show original window sf.ui.proTools.menuClick({ menuPath: ["Window", originalWin] }); log("Create New AUX DONE!!!")
I want to do either of the following.
(a). Pressing the Esc key while the plug-in search window is displayed cancels the script
or
(b). Press the Esc key while the plug-in search window is displayed to skip the plug-in insert and proceed to "function main ()"Maybe this script will wait for the plugin window to appear even if it goes through the plugin search window, so I'm trying various things to add the command "press Esc to exit the script". (I didn't know how to jump to a different location in the script like (b)...)
While researching Java, I thought that something like the following would suit my purpose, but it seems that something is wrong, doesn't work as expected. (the plugin search window closes automatically, or immediately stops after launching the plugin from the plugin search window. )
if (sf.keyboard.press({ keys: "escape", })) { log('Cancelled'); throw 0; }
or
while (true) { const searchWin = sf.ui.proTools.invalidate().windows.whoseTitle.startsWith("Search Inserts").exists if (searchWin) { sf.wait({ intervalMs: 1000 }) } else if (sf.keyboard.press({ keys: "escape", })) { log('Cancelled'); throw 0; } else { break; } }
Can you point out some mistakes or give me some advice?
samuel henriques @samuel_henriques
If you cancel here, it won't go to the mix window (if thats where you were)
You need to delete the rest of the old wait,
delete all this,
// Wait to open new plug while (true) { const plugIsOpen = auxTrack.groups.whoseTitle.is(getGroup("Inserts", insertSlot)).first .buttons.whoseTitle.is(`Insert Assignment ${insertSlot}`).first .value.invalidate().value != "unassigned" if (!plugIsOpen) { sf.wait({ intervalMs: 1000 }) } else { break; } }
- MMasayoshi Sugai @Masayoshi_Sugai
I'm sorry, I misunderstood.
I removed the old wait and it worked perfectly!
thank you so much! !! !!