Sequoia Popup Menu Challenges
Hi ya'll!
I just purchased a new M4 Macbook Pro preinstalled with sequoia and off the bat I'm running into issues with some of my scripts not playing nice with popup menu selections. I noticed there was one or two other forum posts pertaining to this, but curious what's the move here?
Sometimes it works, sometimes it doesn't, but it is inconsistent - any help would be amazing. I'll keep digging in the meantime.
Thanks!
Linked from:
- SSoundFlow Bot @soundflowbot
Thanks for contacting SoundFlow support.
Please note, that the best way to get help with a script, macro or other content installed from the Store or content that you've made yourself, is to select the script/macro, then click the red Need help button, and then click "Get help with this script or macro".
By using this method, we will get access to more information and so should be able to help you quicker.
You can read more about how this works here: bit.ly/sfscripthelpIf you're seeing an error that isn't related to scripts or macros, and you think this is a bug in SoundFlow, please file a Help/Issue bug report.
You can see how to do this by going to bit.ly/sfhelpissue - In reply toTristan⬆:Kitch Membery @Kitch2024-11-19 21:50:03.340Z
Hi @Tristan,
Due to changes that Apple made in Sonoma OS, popup menu calls are no longer synchronous.
This will only really be a problem when directly sequencing... (menu -> popup menu) or (popup menu -> popup menu) ...type actions with no other wait in between.
Therefore you'll now need to add implementation to ensure menus close before moving on.
It's important to note that when working with asynchronous tasks the fix should never be to insert an arbitrary wait (sf.wait()) time, it's better to wait for a specific condition to be true rather than use arbitrary delays which might be unreliable or inefficient.
So for these situations, you'd need to implement a
waitFor()
method with a callback to ensure that each popup menu closes before moving on.This approach will make your script robust and more precise, avoiding unnecessary waits or premature actions.
Can you provide me with a simple example of a sequence of menus that is causing you a problem? That way I'll be able to provide you a solution you can use to update your scripts.
Thanks in advance.
- TTristan Hoogland @Tristan
Thanks @Kitch !
Got it. I'm going deeper into some of my scripts today to see where I need to implement the
waitFor()
method.Here's an example snippet from one function that's failing currently.
//Set "Mix Source" - Popup Menu if (bounceDlg.popupButtons.allItems[1].value.invalidate().value !== outputPath[outputPath.length - 1]) { bounceDlg.popupButtons.allItems[1].popupMenuSelect({ menuPath: [outputPath[0], outputPath[outputPath.length - 1]], }); }
Thanks!
Kitch Membery @Kitch2024-11-20 23:45:46.444Z
Here's how I would do it.
The
popupMenuSelectAndWait
function waits for the popup menu to close before moving on./** * @param {Object} args * @param {AxElement} args.popupButton * @param {String[]} args.menuPath */ function popupMenuSelectAndWait({ popupButton, menuPath }) { // Wait for the Popup Button popupButton.elementWaitFor(); // Click the Popu Putton to display and get the Popup Menu const popupMenu = popupButton.popupMenuOpenFromElement({ anchor: "TopLeft", // Required to account for possible menu panel overlaps. relativePosition: { x: 5, y: 5 }, // Required to make sure the menu is not being picked from the Popup Button's frame boundaries. }).popupMenu; // Select the Menu Path popupMenu.menuClickPopupMenu({ menuPath }, () => { sf.ui.frontmostApp.appActivateMainWindow(); // If the menu selection fails, activate the app's main window before throwing an error. throw `Failed selecting menu path: ${JSON.stringify(menuPath)}`; }); // Wait for the Popup Menu to no-longer have children in turn confirming that the menu has closed. sf.waitFor({ callback: () => !popupMenu.invalidate().children.first.exists, timeout: 2000, }); } const outputPath = ["physical output", "Mac Studio Speakers 1-2 (Stereo)"]; sf.ui.proTools.appActivateMainWindow(); const bounceDlg = sf.ui.proTools.windows.whoseTitle.is("Bounce Mix").first; //Set "Mix Source" - Popup Menu if (bounceDlg.popupButtons.allItems[1].value.invalidate().value !== outputPath[outputPath.length - 1]) { popupMenuSelectAndWait({ popupButton: bounceDlg.popupButtons.allItems[1], menuPath: outputPath }); }
- TTristan Hoogland @Tristan
Thanks so much mate! And for today on the zoom too. Gonna start implementing this now, will fire back with results in the next few days!
- In reply toKitch⬆:TTristan Hoogland @Tristan
Hey @Kitch
Things are working great so far for most of the menus I'm tackling. Do you have any advice on a script moving too quickly through save as dialogs/sheets appearing? So far unless I put this 1000ms wait between the sheet appearing and the rest of the script it speeds right through:
let dlg = sf.ui.proTools.windows.invalidate().whoseTitle.is('Save').first //TEMP WAIT sf.wait({ intervalMs: 1000 }); //Enter the new name dlg.textFields.first.value.value = newName; //Click Save dlg.buttons.whoseTitle.is('Save').first.elementClick();
Without the small wait, it speeds right through this part and doesn't even get to the textfields/newName and Click Save part.
I've tried using callbacks on the save dialog, but it ain't working. Thanks in advance!
Kitch Membery @Kitch2024-11-22 00:20:52.743Z
Not exactly sure where it's failing, but this should deal with all scenarios that I can see.
let newName = "Test Session Name" // Activate Pro Tools sf.ui.proTools.appActivate(); // Open the "Save" window sf.ui.proTools.menuClick({ menuPath: ["File", "Save Session As..."] }); const saveSessionDialog = sf.ui.proTools.windows.invalidate().whoseTitle.is('Save').first; // Wait for "Save" window saveSessionDialog.elementWaitFor(); log(`The "Save" window appeared.`); // For demonstration purposes only. const saveAsTextField = saveSessionDialog.textFields.first; // Set "Save as" text field to newName saveAsTextField.value.value = newName; sf.waitFor({ callback: () => saveAsTextField.value.invalidate().value === newName, timeout: 2000, }, `Could not set the "Save as" text field to ${newName}`); log(`"Save as" text field value sucessfully set to ${newName}`); // For demonstration purposes only. //Click Save saveSessionDialog.buttons.whoseTitle.is('Save').first.elementClick(); // Wait for the "Save" dialog to disappear saveSessionDialog.elementWaitFor({ waitForNoElement: true }); log(`The "Save" window closed.`); // For demonstration purposes only.
- TTristan Hoogland @Tristan
Ugh, @Kitch obvious now - it was simply this line that was omitted from my script:
saveSessionDialog.elementWaitFor();
Thanks!