Title
Popupsearch disappears
What do you expect to happen when you run the script/macro?
Script (written by Kitch), should take the output paths from a selected track and present them in the popupsearch
Everything appears to work except the popupsearch window disappears as soon as it is opened, preventing selection of an 'outputPath'.
Have tried invalidating in numerous spots but can't seem to get the popupsearch window to stay visible.
Are you seeing an error?
What happens when you run this script?
popupsearch window should allow for selection of an output
instead popupwindow appears momentarily (looks like it is displaying the stored outputs), but disappears before menu selection is possible
How were you running this script?
I clicked the "Run Script" or "Run Macro" button in SoundFlow
How important is this issue to you?
5
Details
{ "inputExpected": "Script (written by Kitch), should take the output paths from a selected track and present them in the popupsearch\n\nEverything appears to work except the popupsearch window disappears as soon as it is opened, preventing selection of an 'outputPath'.\n\nHave tried invalidating in numerous spots but can't seem to get the popupsearch window to stay visible.", "inputIsError": false, "inputWhatHappens": "popupsearch window should allow for selection of an output\n\ninstead popupwindow appears momentarily (looks like it is displaying the stored outputs), but disappears before menu selection is possible", "inputHowRun": { "key": "-MpfwYA4I6GGlXgvp5j1", "title": "I clicked the \"Run Script\" or \"Run Macro\" button in SoundFlow" }, "inputImportance": 5, "inputTitle": "Popupsearch disappears" }
Source
sf.ui.proTools.appActivateMainWindow();
sf.ui.proTools.mainWindow.invalidate();
const menuItems = sf.ui.proTools.selectedTrack.outputPathButton.popupMenuFetchAllItems({ dismissMenu: true, }).menuItems
const outputPaths = menuItems
.filter(outputs => outputs.path[0] === "bus" || outputs.path[0] === "output")
.map(output => ({
name: output.path.join(" → "),
path: output.path,
}));
const selectedOutputPath = sf.interaction.popupSearch({
title: "Which Output would you like to add to?",
items: outputPaths,
}).item.path;
log(selectedOutputPath);
Links
User UID: sKu19XXNXHYSdEMmZtHz8CozbdS2
Feedback Key: sffeedback:sKu19XXNXHYSdEMmZtHz8CozbdS2:-NfKf2DouZ5tIiLYVY4L
Feedback ZIP: oGsS7wjWTjTeaRjWZR12IUcyW0+a5nqy7PuDqIqRjXz0S5YuHuNCTINS5YfTl0zSaifYdk8tftmoI0id72IAFRKQgSBE4szB/pDScrfueQhUVpoTiZdItlNsM5x5g6IUMUKgj4+yRp+UQg+fkh1cxSLCKjztmOYnK/wUfuf1m+rWv1w9mkfakohFc94tdU42v4Ym3DaWVRN3CBw/TVcuVdx8I1Ix8rgJhClj9y2pmlrfaC7RNb9K8EDfv2LwUvbwNAgfOrR6MRvfMYctIKtGdszl9EbvspcEpgd0SYTYUvWWo+TGTlCx5QuyIK4RP/8v3XmFtZgG2nfBc6/6P/EFrcrpUl4nLeeE6wTx7ufFhTo=
Linked from:
- Chad Wahlbrink @Chad2023-09-27 13:08:17.494Z2023-09-27 21:53:49.310Z
Hey @Forrester_Savell!
The script you provided does not seem to include the step of selecting the output from the output path button. Try this script:sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); const menuItems = sf.ui.proTools.selectedTrack.outputPathButton.popupMenuFetchAllItems().menuItems const outputPaths = menuItems .filter(outputs => outputs.path[0] === "bus" || outputs.path[0] === "output") .map(output => ({ name: output.path.join(" → "), path: output.path, })); const selectedOutputPath = sf.interaction.popupSearch({ title: "Which Output would you like to add to?", items: outputPaths, }).item.path; //Get focus back sf.wait({ intervalMs: 50 }); sf.ui.proTools.appActivate(); sf.wait({ intervalMs: 50 }); sf.ui.proTools.selectedTrack.trackOutputSelect({ outputPath: selectedOutputPath, selectForAllSelectedTracks: true });
- In reply toForrester_Savell⬆:Chad Wahlbrink @Chad2023-09-27 13:11:53.897Z
Also, I'd be curious if you can get the intended result from the built-in SoundFlow Action under Pro Tools > Track Input, Output & Pan > Select Track Output (Search)
- FIn reply toForrester_Savell⬆:Forrester Savell @Forrester_Savell
Hi @Chad
Thanks for looking into this.
Still getting the same issue with your script, the popup window disappears straight away. I was calling theselectedOutputPath
in a larger script, this was just running as a function.The Pro Tools > Track Input, Output & Pan > Select Track Output (Search) macro works great, except it includes a bunch of information I don't want, like 'track'. The window does stay visible though.
Is there a way to truncate the results of
trackOutputSearch()
, like I was doing in my first script?Forrester
Chad Wahlbrink @Chad2023-09-27 20:28:44.264Z
@Forrester_Savell, I'm having trouble replicating this on my system. To clarify, the SF interaction popup is the one disappearing straight away? Or is the popup from the output selector disappearing?
A few other things – can we have you update SoundFlow to 5.4.8 here: https://my.soundflow.org/install
Then, can you try running this shorter snippet:sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); const menuItems = sf.ui.proTools.selectedTrack.outputPathButton.popupMenuFetchAllItems({ dismissMenu: true, }).menuItems const outputPaths = menuItems .filter(outputs => outputs.path[0] === "bus" || outputs.path[0] === "output") .map(output => ({ name: output.path.join(" → "), path: output.path, })); log(outputPaths);
Does this appear to log your outputs as an array of objects? That may help us troubleshoot why the interaction popup may be failing.
To access the full log, you can click "open log" here:- FForrester Savell @Forrester_Savell
Hey @Chad
So I was making a video to show you exactly what was happening and I've found the window disappearing issue is related to mouse position or possibly mouse movement. If I run the command and move the mouse around over where the menu appears, I can get the window to stay visible.
We're talking about the SF interaction popup window, you'll see in the video. The video shows me experimenting with where I place the mouse. On subsequent tries, there doesn't seem to be a specific mouse position, just that it is actively moving over the window menu allows it to stay open.
Video also shows the array of objects as expected, plus the full selection of outputs display correctly when the window remains open.
https://forrestersavell.filemail.com/d/xmkzgkbkldqdhak
Let me know if you need any info from the full log. I see this written a bit, not sure if relevant
"28.09.2023 07:18:01.64 [Backend]: Throwing error from cancellation in action (00) PopupAction
Throwing error from cancellation in action (00) PopupSearchAction28.09.2023 07:18:01.64 [Application]: this.popupWindow.on(hide)"
- FForrester Savell @Forrester_Savell
I've updated to SF 5.4.8 and the behaviour is the same.
- In reply toForrester_Savell⬆:
Chad Wahlbrink @Chad2023-09-27 21:53:07.147Z
Hey @Forrester_Savell,
I'm sorry you are seeing this issue persist! I'm curious to try this other version of the script. This is the one that I have used personally for the last couple of years. Just a slight tweak on the approach overall:if (!sf.ui.proTools.isRunning) throw `Pro Tools is not running`; sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); function outputSearch() { let outputPathButton = sf.ui.proTools.selectedTrack.outputPathButton; // Fetch all menu items let items = outputPathButton.popupMenuFetchAllItems().menuItems.map(function (item) { return { name: item.names.join(' > '), path: item.names }; }); let filteredResults = items.filter(function (str) { return !str.name.includes('track'); }); // Search let chosenPath = sf.interaction.popupSearch({ items: filteredResults, title: 'Search for a Track Output', }).item.path; //Get focus back sf.wait({ intervalMs: 100 }); sf.ui.proTools.appActivate(); sf.wait({ intervalMs: 50 }); // Select Chosen Path sf.ui.proTools.selectedTrack.trackOutputSelect({ outputPath: chosenPath, selectForAllSelectedTracks: true }); sf.ui.proTools.invalidate(); } outputSearch();
- FForrester Savell @Forrester_Savell
Hi @Chad
Can you help me understand how to remove the 'path' from the list of outputs that this script creates (i.e. remove the 'bus -> bus menu 1-128 ->' part). I would like the list to display the final output or bus names with the (Mono) or (Stereo), but without the path cluttering the list.
When I go back to basics and just to either remove the name or the path, I get errors in the popupSearch.
if (!sf.ui.proTools.isRunning) throw `Pro Tools is not running`; sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); function outputSearch() { let outputPathButton = sf.ui.proTools.selectedTrack.outputPathButton; // Fetch all menu items let items = outputPathButton.popupMenuFetchAllItems().menuItems.map(item => item.path) //.map(function (item) { /* return { name: item.names.join(' > '), path: item.names }; }); */ log (items) //let filteredResults = items.filter(function (str) { return !str.path.includes('track'); }); // Search let chosenPath = sf.interaction.popupSearch({ items: items, title: 'Search for a Track Output', }).item.path; //Get focus back sf.wait({ intervalMs: 100 }); sf.ui.proTools.appActivate(); sf.wait({ intervalMs: 50 }); // Select Chosen Path sf.ui.proTools.selectedTrack.trackOutputSelect({ outputPath: chosenPath, selectForAllSelectedTracks: true }); sf.ui.proTools.invalidate(); } outputSearch();
Chad Wahlbrink @Chad2024-06-17 14:39:55.967Z
Hey @Forrester_Savell!
The reason you are seeing errors is that thesf.interaction.popupSearch()
command is set up to search an object with a property calledname
. In your version of the script above, when you are mapping.map(item => item.path)
, you are taking an array of objects (the output of.popupMenuFetchAllItems().menuItems
is an array of objects) and converting it to an array of arrays. This is because thepath
property of themenuItems
object you get from.popupMenuFetchAllItems().menuItems
is an array.
The original code maps the array ofmenuItems
objects to a new array of objects with two properties,name
andpath
. The critical part of mapping an array for a SoundFlow popupsearch is having aname
property. If thesf.interaction.popupSearch()
command is called on an array of objects that do not have thename
property, it will fail and error out. This is just how that specific function was setup in SoundFlow, but it does explain why you would see errors if you are attempting to feedsf.interaction.popupSearch()
an array of arrays, instead of an array of objects with thename
property.
I hope that makes sense! If you are interested in learning more about array and object data types, I'd suggest watching some of Steve Griffith's Javascript videos on YouTube:- In reply toForrester_Savell⬆:
Chad Wahlbrink @Chad2024-06-17 14:41:40.913Z
@Forrester_Savell, here's a script that should work as you are expecting:
if (!sf.ui.proTools.isRunning) throw `Pro Tools is not running`; sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); function outputSearch() { let outputPathButton = sf.ui.proTools.selectedTrack.outputPathButton; // Fetch all menu items let items = outputPathButton.popupMenuFetchAllItems().menuItems.map(function (item) { return { name: item.names[item.names.length - 1], path: item.path }; }); let filteredResults = items.filter(function (str) { return !str.path.includes('track'); }); // Search let chosenPath = sf.interaction.popupSearch({ items: filteredResults, title: 'Search for a Track Output', }).item.path; //Get focus back sf.wait({ intervalMs: 100 }); sf.ui.proTools.appActivate(); sf.wait({ intervalMs: 50 }); // Select Chosen Path sf.ui.proTools.selectedTrack.trackOutputSelect({ outputPath: chosenPath, selectForAllSelectedTracks: true }); sf.ui.proTools.invalidate(); } outputSearch();
Chad Wahlbrink @Chad2024-06-17 14:51:02.397Z
The part that filters the name to just the actual output name is line 12.
item.names[item.names.length - 1]
The output of
popupMenuFetchAllItems().menuItems
is an array of objects with the propertiesPath
,Names
,Delimiter
, andElement
. When I run:log(sf.ui.proTools.selectedTrack.outputPathButton.popupMenuFetchAllItems().menuItems)
I get an array like this:
[{ "Path": [ "output", "A VIRTUAL 1-2 (Stereo) -> VIRTUAL 1-2" ], "Names": [ "output", "A VIRTUAL 1-2 (Stereo) -> VIRTUAL 1-2" ], "Delimiter": " -> ", "Element": "{\"title\":\"A VIRTUAL 1-2 (Stereo) -> VIRTUAL 1-2\",\"role\":\"AXMenuItem\",\"fullRole\":\"AXMenuItem\"}" }, { "Path": [ "output", " A VIRTUAL 1 (Mono)" ], "Names": [ "output", " A VIRTUAL 1 (Mono)" ], "Delimiter": " -> ", "Element": "{\"title\":\" A VIRTUAL 1 (Mono)\",\"role\":\"AXMenuItem\",\"fullRole\":\"AXMenuItem\"}" }, ... ... ... ... ]
So when I map this array of objects with 4 properties to a new array of objects with just two properties,
name
andpath
, I'm usingitem.names[item.names.length - 1]
to assign the last slot of each array of "names" to the name prop and then leave the path intact so that I can call it later in line 23 when I've selected the object I want to route to.
This kind of manipulation gets slightly muddied by using the output of an array of objects with thenames
prop to create a new array of objects with aname
prop, but they are referencing different things in this instance.
I hope that helps!- FForrester Savell @Forrester_Savell
@Chad thanks so much. Appreciate you going into the details on this and helping me understand. Definitely makes sense now that the
sf.interaction.popupSearch()
needs to see a name property.The only part that I'm still a little fuzzy on is line 23.
Does thesf.interaction.popupSearch()
propertyitems
that is referencing thefilteredItems
array of objects, only display thename
property?
How does it use thepath
property? Is it assigning thename
for eachpath
in the array, therefore that's why it needs thepath
property? Following this thought, why does it need thepath
at all? I did some experimenting and this script works where its simply referencing thename
property. Is there a reason why you wouldn't use just thename
property such as below:if (!sf.ui.proTools.isRunning) throw `Pro Tools is not running`; sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); function outputSearch() { let outputPathButton = sf.ui.proTools.selectedTrack.outputPathButton; // Fetch all menu items let items = outputPathButton.popupMenuFetchAllItems().menuItems.map(function (item) { return { name: item.names[item.names.length - 1], //path: item.path }; }); let filteredResults = items.filter(function (str) { return !str.name.includes('track'); }); // Search let chosenPath = sf.interaction.popupSearch({ items: filteredResults, title: 'Search for a Track Output', }).item.name; //Get focus back sf.wait({ intervalMs: 100 }); sf.ui.proTools.appActivate(); sf.wait({ intervalMs: 50 }); // Select Chosen Path sf.ui.proTools.selectedTrack.trackOutputSelect({ outputPath: chosenPath, selectForAllSelectedTracks: true }); sf.ui.proTools.invalidate(); } outputSearch();
I think this script is what I thought I was doing in my first attempt. I felt that having both
name
andpath
is redundant, as they seem to be referencing much the same information, at least as far as the names of the bus/outputs is concerned.Thanks for your time!!
Chad Wahlbrink @Chad2024-06-18 03:33:54.283Z
Hey @Forrester_Savell!
Let's see if we can clear up the fuzziness. It may help to start with the premise that the ultimate goal of this particular script is to callsf.ui.proTools.selectedTrack.trackOutputSelect()
at the end. When we callsf.ui.proTools.selectedTrack.trackOutputSelect()
, that method looks for anoutputPath
property of the array type. Therefore, our ultimate goal is to end up with an array by the end of the script.
Then, starting from the top, we first calloutputPathButton.popupMenuFetchAllItems().menuItems
, which gives us the array of objects with the propertiesPath
,Names
,Delimiter
, andElement
. In this instance, thePath
property and theNames
property are equivalent.
It does make sense thatPath
andNames
are somewhat redundant in the resulting mapped object from that part of the script, however, there's an important change happening here.
sf.interaction.popupSearch()
needs an array to search, and specifically, it expects an array of objects that contain aname
property, as we discovered earlier. The other piece to this puzzle, though, is thatsf.interaction.popupSearch()
expects that name to be a String, not an array. This means if we were to call something like this:let items = outputPathButton.popupMenuFetchAllItems().menuItems.map(function (item) { return { name: item.names, }; });
Yes, we could potentially get away with using the
item.names
as an array to feedsf.ui.proTools.selectedTrack.trackOutputSelect()
at the end of the script, but if we feed this version of theitems
object tosf.interaction.popupSearch()
, it will fail because we have just givensf.interaction.popupSearch()
an array of objects withname
props holding arrays and not strings.
Therefore to keep the flow of the script moving we are using calls like:item.names.join(' > ')
or
item.names[item.names.length - 1]
These convert the array from the
names
prop outputted fromoutputPathButton.popupMenuFetchAllItems().menuItems
into strings that can be used bysf.interaction.popupSearch()
.
Because we need an array of objects with aname
prop of type string to feedsf.interaction.popupSearch()
and then we inevitably also need an array to givesf.ui.proTools.selectedTrack.trackOutputSelect()
at the end of the script, we will need to have an array of objects with both aname
and apath
property. Like this:let items = outputPathButton.popupMenuFetchAllItems().menuItems.map(function (item) { return { name: item.names[item.names.length - 1], path: item.path }; });
Maybe the simplest way of thinking about it is that we can use the
name
prop as a "searchable" string, but that string can also be linked to a more complicated array, which we will need to feedsf.ui.proTools.selectedTrack.trackOutputSelect()
in the end.
- In reply toForrester_Savell⬆:
Chad Wahlbrink @Chad2023-09-27 21:55:15.592Z
We can also try the script from this post again:
I tweaked it slightly to remove the
{ dismissMenu: true, }
bit from line 4- FForrester Savell @Forrester_Savell
Legendary @Chad
Both those options work now. I think the key is the removal of
{ dismissMenu: true, }
in both scripts that are working.Interestingly, the original script with that line included works fine on my laptop running Ventura & PT 2023.9. My main mix rig is Catalina & PT2023.6 which is where it wasn't working.
Either way, all solved now so thanks for all the insight and help!!!!Chad Wahlbrink @Chad2023-09-28 00:55:53.475Z
Glad to hear, @Forrester_Savell! Yes, I think that breaking must be something Catalina-specific. I'm running Monterey and couldn't break it with or without the
dismissMenu: true
, but glad it's working on your end now!