AXShowMenu

I am trying to get this button to let me select an object from the menu that pops up when you click it ordinarily, I have tried passing a click to it, tried acessing it as one would a menu button, tried acessing the menu below it all to no avail. I realize that this is probably an easy to answer question but I can’t find the answer and I have been browsing documentation at apple’s site for about half an hour and found nothing. Any help anyone can provide would be much appreciated and any more information I can give I will.

Thanks

Cliff

Can you post the script yu have trouble with. Try to find the UIElementInspector application. It will tell you the exact location of it.

UI scripting can be both tremendously rewarding and excruciatingly frustrating, Cliff. As with using AppleScript generally, each application may present its own individual eccentricities and anomalies. Sometimes, methods that work successfully elsewhere can fail spectacularly in a given situation.

That’s why bonedoc has rightly suggested that you try giving us a few more details about what you’re specifically trying to do. If you don’t feel ready yet to share your scripting efforts so far, perhaps you could just name the application involved and describe where the target button is located.

There are many competent scripters around here who will gladly help you in whatever way they can. All they usually need is some specific information - so they can home in on your aim more accurately. :slight_smile:

The app I am working with is AirFoil.


activate application "Airfoil"
tell application "System Events"
	tell process "Airfoil"
		tell window "Airfoil"
			tell button "iTunes"
				click
				tell menu 1
					select menu item "VLC"
				end tell
			end tell
		end tell
	end tell
end tell

is what I have so far. it gives a NSRecieverEvaluationScriptError: 4 at the select menu item line
I was getting that earlier when I had the name of a menu item wrong(in a different section of the app) the other problem is that the button changes names(fun, fun) but I want to get it working with a given name first.
I also tried the above without he click, and with tell menu button click then the rest, the former give the same error, at the same line, the latter gives an expected end of line, seeing identifier(or something).
the Acessability inspector shows this for the button

and this for the menu item once the button has been clicked:

Thanks, makes it alot easier, is there a way to get a list of media apps on a system?

Hello again, Cliff.

Thanks for your detailed explanation of what you’re trying to do. Makes it a lot easier to come up with possible suggestions. :slight_smile:

In a way, this case exemplifies everything I said earlier about the vagaries of UI scripting. You’ve already done a sterling job in identifying the UI elements that you’re after. Nevertheless, I fear that Accessibility Inspector - while normally extremely helpful in these situations - may be innocently leading us up the old garden path on this one. To demonstrate what I mean (and to hopefully offer you a few pointers on UI scripting along the way), let’s explore a few of the issues involved in this approach - before I suggest my preferred alternative.

Firstly, how do we get AirFoil to present the menu that we’re trying to access?

As you’ve already correctly observed, the target button offers a couple of action options: “AXShowMenu” (show menu) and “AXPress” (press - or, more accurately, click). We also know that clicking doesn’t have the desired effect here - so let’s try the alternative, “AXShowMenu”:

tell application "System Events" to tell window "Airfoil" of process "Airfoil" to perform action "AXShowMenu" of button -1

(Note that I referred to the target button by index, button -1, rather than by name, button “iTunes” - since, as you rightly point out, the name is likely to change.)

Hopefully, that should show the menu - and I can leave you to continue from there, right? :slight_smile:

Wrong. :frowning:

As you say, Accessibility Inspector tells us that our target button now contains a menu which, in turn, contains a list of menu items - from which we should be able to select our current choice. Fine. But due to what I believe is an unfortunate bug, we simply can’t access that menu. Any attempt to access via scripting (which normally works in other situations) tells us that the button contains no further UI elements (even though we can actually see them on-screen):

tell application "System Events" to tell button -1 of window "Airfoil" of process "Airfoil"
	perform action "AXShowMenu"
	delay 0.5 (* give the menu time to appear *)
	UI elements
end tell
--> {}

The returned empty list simply confirms that any attempt to access the button’s elements (which we know to exist) will fail.

Bummer. :confused:

So what do we do now?

No worries. Given that we know the position of a menu item, we can always resort to a little keystroke subterfuge to access it:

set menu_item to 3 (* position of required app in pop-up menu *)
tell application "System Events" to tell process "Airfoil"
	tell window "Airfoil"
		tell button -1 to perform action "AXShowMenu"
		delay 0.5 (* give the menu time to appear *)
		repeat menu_item times
			key code 125 (* down arrow *)
		end repeat
		keystroke return (* confirm choice of menu item *)
	end tell
end tell

That should select the required menu item. Great. So now you can take it from there, right? :slight_smile:

Wrong. :frowning:

Run that last script a few times and watch what happens to the menu. The order of menu items changes. The most recently selected item is promoted to pole position - while those items that previously came before it move down a slot to accommodate it. And, since we can’t read the menu (because the script can’t access it), we can’t check the latest sequence of menu items within it. So we can’t determine the current position of our target menu item…

(Incidentally, ever read Catch-22?) :wink:

With this approach, the only possible way to select a menu item by name is to iterate through each menu item, select it - and then re-check the button name. For this, you’d need to know in advance the total number of application options available. Way too clunky to consider seriously…

Given the abundance of constraints, caveats and curiosities in all this, you may by now be wondering if it’s really worth pursuing at all. But take heart. There’s usually more than one way to approach such things. And, since Airfoil has its own AppleScript implementation and dictionary, I reckon the best method is to script it directly:

tell application "Airfoil" to set current audio source to application source "VLC"

PS: I see that, while I was typing this, Jacques beat me to my conclusion. (That’ll teach me to embark on long-winded replies.) All the same, I hope you still find the general stuff about UI scripting of some use for other situations…
:slight_smile:

wow, found the applescript stuff for airfoil, really surprised nobody’s done what I’m trying to do before. Thanks for all your help, I’ll be back if I get to bashing my head against a wall again. Can anyone recommend a good book of general information on this stuff?

Sure thing, Cliff.

Being rather more a botcher than a bookworm, I can’t speak from personal experience - although I’ve heard excellent reports about AppleScript: The Definitive Guide, by Matt Neuburg. (Others around here may add their own personal favourites.)

For a basic grounding in AppleScript, you could take a look at Getting Started With AppleScript and the venerable AppleScript Language Guide (aged - but highly informative, nonetheless).

I think you’ll find that this site in particular is a truly amazing resource. For example, check out the range of books listed in the Resources/Books section. If Craig (our resident “librarian” and all-round helpful guy) stumbles upon this thread, he may also throw in a pointer or two.