tell app "iTunes" to… [Check for open app; Compiling scripts]

I am having a very weird problem with the tell application command. Admittedly, I am fairly new to applescript and constantly need to look up references and such, but google is being an absolute monster and not helping me. So here is my problem…

I am writing a script that will basically control and poll iTunes for information when run from osascript. The thing is, I ONLY want it to tell app “iTunes” when iTunes is already running, and perform some other action if it isn’t.

However for some reason, even though the “tell application” block is inside an if block, it executes regardless of the if’s condition. At first i thought maybe it was iTunes bug, so i tried it on iPhoto and it did the same thing. So then i considered that maybe tell blocks are always executed regardless of conditionals, despite all the snippets of applescript I have seen everywhere. To test this, i changed the app yet again to Terminal and lo and behold it started behaving correctly. When i changed the app to terminal, it closed the front window if it Terminal was running and returned false if it wasn’t.

It completely stumps me, no amount of fiddling has gotten itunes to STAY closed if it is already closed (since ‘tell application “name” to do something’ always opens the application first, it seems).

Here is the snippets I’ve been working with:


tell application "System Events"
	set myList to (name of every process)
end tell

set shouldRun to (myList contains "iTunes")

-- shouldRun correctly represents whether or not iTunes is active as illustrated by returning it with itunes closed and open:
--return shouldRun

if shouldRun then
	tell application "iTunes" to play
else
	return "closed"
end if

If itunes is open, then it starts playing. If itunes is closed, then it opens and then starts playing. iPhoto behaves similarly, but Terminal obeys the if statement and does not listen to the tell statement if shouldRun is false.

Anyone have any hints?

by the way, i couldn’t find any “if running tell application ‘blah’ to …” equivalent … and i know the way I’ve done it still isn’t the best, but i’ve rearranged it so many times to see if it would make a difference to the itunes segment (originally the if statement wasn’t a variable, it was ‘if (myList containts "iTunes) is true’

If there are any other ways to check itunes is running, feel free to suggest, though that is not the problem i am having. For the life of me, i cannot get itunes to keep its open/quitted state.

thanks,
Bo

Model: iMac Core Duo 20"
AppleScript: 1.10.7
Browser: Safari 419.3
Operating System: Mac OS X (10.4)

Your script seems to work fine for me.

EDIT: What I wrote below is no longer relevant. I think I figured out the problem. It has to do with the way the script is saved (as a compiled script or plain text). I was using TextMate to edit my files, but when I tried in Script Editor it worked. My script needs to execute through osascript (from shell script), and when i ran a plaintext file through osascript it opened itunes, when i ran a compiled script, it worked perfectly.

I can only theorize that the intepreter had to probe the entire file and somehow accidently triggered the tell application line as it was checking the syntax etc before parsing it. Saving it as “script” and not “text” in Script Editor gives the same opposing results. Bug? Feature? i don’t know…

OLD POST:

iTunes 6 or 7?

I tested on my iMac, and Macbook, and my friend tested it on his powerbook and macbook pro … it worked no where.

a condensed test:

set shouldRun to false
if not shouldRun then
	return false -- this should execute
else
	return doAction() -- this should not
end if

on doAction()
	tell application "iTunes" to play
	return true
end doAction

This opens iTunes (does not play however), and returns false!!! which means that the first code block in the if statement is executed. Despite the fact that iTunes is opening, doAction() is not executed, else true would be returned.

Are you positive that iTunes did not open? Even after a few runs. it should NOT open with script above, unless i am missing something ovious. and if you change the value of shouldRun, then it SHOULD open it, and start playing, then return true.

Feedback?

When you first compile a script (or open it in Script Editor), it must open any “told” applications to fetch their dictionary. If you close the application after that, or if you’re running the script from somewhere else (not Script Editor), then the script should have the desired results.

Edit: Just saw your edit.

Edit: Seems you found the cause; osascript has to compile plain text files before their run, which leads to the issue I mentioned above. You’ll probably want to save compiled scripts unless you have a reason to use text (e.g. Not editing with Script Editor, Spotlight searching, etc.).

thanks. read my edit above. i found the opposite. running in script editor works perfectly (except for that first time, which I knew about), but anywhere else did not. But your right, as its plain text script in TextMate, it most likely has to read the dictionary each time its run using osascript (whereas perhaps the compiled version includes the relevant dictionary “definition” in the script directly). I could be sounding like an idiot, i have no idea… but it seems to make sense.

Thanks anyway, I’ll jus tstick to Script Editor

EDIT: while on the topic, though … is there a better way to test if the app is already open?

Now read my edit. :stuck_out_tongue:

Yup, thanks. I have no problem compiling them first. as long as I can run them. I’ll just have to use script editor since, as far as I can tell, TextMate can’t actually compile them :frowning:

Thanks, for your help.

While I am here, i couldn’t find any reference to checking if apps are open. I found the other snippet by accident but it seems more complicated than it needs to be. If you have a quick answer, awesome. otherwise i’ll make another thread

EDIT: OMG with all these edits … .haha >.< headache

No, what you have is the typical way of doing it. You could shorten it a little though:

tell application "System Events"
	set shouldRun to "iTunes" is in (name of every process)
end tell

-- or
tell application "System Events" to set shouldRun to "iTunes" is in (name of every process)

For some background processes (e.g. command-line based), you might have to use this instead:

do shell script "/usr/bin/ps axc"
set shouldRun to "iTunes" is in result

Using exists is better I think, because it doesn’t get the name of every process.


tell application "System Events"
	set itunes_exists to (exists process "iTunes")
end tell
if itunes_exists then tell application "iTunes" to play

Not too much difference though, just for a simple script like this.

gl,

Hi,
One way to get around the tell block calling the app when complie takes place is to use the run script statment.

set itunes_run to "tell application \"iTunes\" to play" -- this puts the command to be used later as a string. 

tell application "System Events"
	set itunes_exists to (exists process "iTunes")
end tell
if itunes_exists then run script itunes_run

This will not open iTunes if it is not running