Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

tell/scoping problem

i'm trying to extract schedules from eyetv, storing them in a script object:

script etvProgram
property parent : tvpiProgram
property UID : missing value
end
on getEtvList()
set etvList to {} -- global
tell application "EyeTV"
with timeout of 3 seconds
set etvList to every program whose start time > now or enabled is false
repeat with etvp in etvList
set eid to etvp's unique ID as integer
tell me
display dialog "getEtvList1:" & eid
copy etvProgram to etvSched
copy eid to etvSched's UID
display dialog "getEtvList1b:" & etvSched's UID
set end of etvList to etvSched
end tell
end repeat
end timeout
end tell

repeat with etvSched in etvList
set eid to etvSched's UID
display dialog "getEtvList2:" & eid
end repeat
end getEtvList

and this is what i get:

tell application "EyeTV"
get every program whose start time > date "Thursday, June 24, 2010 3:29:41 PM" or enabled = false
{program id 2.91930666E+8, program id 2.90092509E+8, program id 2.90090782E+8, program id 2.93717284E+8, program id 2.9185951E+8}
get unique ID of program id 2.91930666E+8
2.91930666E+8
end tell
tell current application
display dialog "getEtvList1:291930666"
{button returned:"OK"}
display dialog "getEtvList1b:291930666"
{button returned:"OK"}
end tell
...
others returned ok
...
tell application "EyeTV"
get UID of program id 2.91930666E+8
"EyeTV got an error: Can't get UID of program id 2.91930666E+8."


xkweez me? where did eyetv get told anything about my local uid? obviously i am totally ignorant of a/s's scoping majick:-( any clues would be appreciated

1.66mHz coreduo mini, 1.25gHz aL powerbook, 300,366,466mHz clamshells, Mac OS X (10.6.3), 10.4.11 on ppc

Posted on Jun 24, 2010 1:21 PM

Reply
29 replies

Jun 24, 2010 2:01 PM in response to aidrummer

oops, i was reusing the list of eyetv structs...fixed it:


set etvProgs to every program whose start time > now or enabled is false
repeat with etvp in etvProgs

any everything's just peechee...when run in script editor.

but when i run as a stay-open app, it hangs on storing eyetv info in my script objects:

repeat with etvSched in etvList
tell etvSched
tell application "EyeTV"
with timeout of 3 seconds
tell program id (my UID)
copy its start time to std
copy (((its duration) / minutes) as integer) to dur
copy its enabled to isEnabled
copy its repeats to rpts
copy its channel number to chStr
copy its title to prgrmTitle
copy its description to descr
end tell
end timeout
end tell

Jun 30, 2010 1:24 PM in response to aidrummer

Hello

From presumedly your messages in the mailing-list such as :
http://lists.apple.com/archives/applescript-users/2010/Jun/msg00292.html

I'd surmise that you're saying the code below works :

--SCRIPT1
property tvpi2crontabP : "/DVR/scripts/tvpi2crontab.app"
property tvpi2crontab : (load script POSIX file tvpi2crontabP) -- loaded script object
tvpi2crontab's init()
tvpi2crontab's getEtvList()
--END OF SCRIPT1

whereas the code below fails (i.e., hangs midway) :

--SCRIPT2
property tvpi2crontabP : "/DVR/scripts/tvpi2crontab.app"
property tvpi2crontab : application (POSIX file tvpi2crontabP) -- external stay-open applet
tvpi2crontab's init()
tvpi2crontab's getEtvList()
--END OF SCRIPT2

given the tvpi2crobtab contains code like (partially) :

--SCRIPT SERVER (part)
script etvProgram
property parent : tvpiProgram
property UID : missing value
end script
global etvList
on init()
--omitted
end init
on getEtvList()
set etvList to {} -- global
tell application "EyeTV"
with timeout of 3 seconds
set tempList to every program whose start time > now or enabled is false
repeat with etvp in tempList
set eid to etvp's unique ID as integer
copy etvProgram to etvSched
copy eid to etvSched's UID
set end of etvList to etvSched
end repeat
end timeout
end tell
end getEtvList
--END OF SCRIPT SERVER (part)


---
I recently posted an analysis and possible solutions for similar issue in Numbers forum.
Topic : Why this AppleScript don't work?
http://discussions.apple.com/thread.jspa?threadID=2474924
http://discussions.apple.com/message.jspa?messageID=11768697#11768697
http://discussions.apple.com/message.jspa?messageID=11769489#11769489
http://discussions.apple.com/message.jspa?messageID=11794477#11794477

(The last post of mine contains the most precise notes, I hope.
Some comments in my other posts regarding the cause of the issue are incorrect and should be revised as those in the last one.)

Based on the analysis, your SCRIPT SERVER will eventually become unresponsive when run with 'etvList' not being local. Also it may eventually cause stack overflow when run with 'etvSched not being local.
Solutions would be a) to declare local for these variables, or b) not to copy an existing script object but use constructor to make new script object.

The reason why this problem does not occur in SCRIPT1 using 'load script' command but in SCRIPT2 using stay-open applet would be that :
1) by using 'load script' command, the global context as is defined in the script object which is loaded by the command does not come in global context at run-time (that is global context as is seen in container application running the script); and

2) by using stay-open applet, the global context as is defined in the script in applet becomes the global context at run-time because the container application is the applet itself.

Thus only the applet version is affected by the recursive deep copy of global context at run-time which is included in script object as its closure.

*It is not the issue of whether the code is run in applet or Script Editor, but the issue of whether the code is loaded to container application by 'load script' command or not.
E.g., if you add the following run handler to the above SCRIPT SERVER and run it in Script Editor, it will hang as SCRIPT2 does.

on run
init()
getEtvList()
end run


Hope this may be of some help,
H

Jun 30, 2010 2:21 PM in response to Hiroto

Hiroto wrote:
Solutions would be a) to declare local for these variables, or b) not to copy an existing script object but use constructor to make new script object.


thanx, hiroto, i'll give it a try...where is applescript's constructor documented?

btw, i've been using my method, copying a s.o. to a list, for almost 4 years, and this is the 1st time i've run into this problem...

Jun 30, 2010 6:36 PM in response to aidrummer

Hello

Regarding script object constructor, there's brief explanation in AppleScript Language Guide :
http://developer.apple.com/mac/library/documentation/AppleScript/Conceptual/Appl eScriptLangGuide/
ASLG > Script Objects > Initializing Script Objects
p.59 of pdf version

By the way, the second paragraph of that section says :
A top-level script object is initialized each time the script's run handler is executed.

which is not accurate. Precisely :
A script's top-level named script object is initialized each time the script is compiled. A script's top-level un-named script object is initialized each time the script's run handler is called and script object's definition statement in the run handler is executed. A script's non top-level script object, whether named or un-named, is initialized each time the handler which contains the script object is called and the script object's definition statement in the handler is executed. (In fact, a script's top-level un-named script object sematically resides in the script's implicit run handler and therefore is to be categorized into the last kind.)


In your code, it would be implemented like this :

--SCRIPT SERVER (part) REVISED
on mkEtvProgram() -- # constructor to return a new script object
script etvProgram
property parent : tvpiProgram
property UID : missing value
end script
end mkEtvProgram

global etvList

on init()
--omitted
end init

on getEtvList()
set etvList to {} -- global
tell application "EyeTV"
with timeout of 3 seconds
set tempList to every program whose start time > now or enabled is false
repeat with etvp in tempList
set eid to etvp's unique ID as integer

--copy etvProgram to etvSched -- # avoid this deep copy of script object
set etvSched to my mkEtvProgram() -- # use constuctor and set command instead

copy eid to etvSched's UID
set end of etvList to etvSched
end repeat
end timeout
end tell
end getEtvList
--END OF SCRIPT SERVER (part) REVISED


As far as I can tell, if you copy a script object into a list in global context repeatedly, your script will eventually hang due to memory overload. So if you've not run into this problem before, I'd think there has been some condition not met. Perhaps the list may not have been global or list may have had only small number of, e.g., less than 10, copied script objects. Etc.

Good luck,
H

Message was edited by: Hiroto

Jun 30, 2010 7:05 PM in response to aidrummer

i've wrapped my
script etvProgram

with a constructor:
on newETVprogram(eUID)

and built a local list in getEtvList():
set end of etvList to newETVprogram(_eid)

but when i then loop thru that list, populating the fields with data from eyetv, the list is then composed of copies of the same info...

i think it's time to abandon applescript & rewrite it in python/appscript;-}

Jun 30, 2010 7:30 PM in response to aidrummer

to illustrate:

repeat with etvp in tvpi2crontab's getEtvList()
log etvp's toString()
end repeat

produces the following:
...
get title of program id 291930666
"Castle"
...
get title of program id 290090782
"The Simpsons"
...
get title of program id 293717284
"The This Old House Hour"
...
get title of program id 291859510
"V"
...
(*V # # 0 # 10:02PM every Tue # 58mins*)
(*V # # 0 # 10:02PM every Tue # 58mins*)
(*V # # 0 # 10:02PM every Tue # 58mins*)
(*V # # 0 # 10:02PM every Tue # 58mins*)

Jun 30, 2010 9:08 PM in response to aidrummer

Hello

Well, it is because the 'tvpiProgram' as the parent of 'etvProgram' is still shared among the 'etvProgram' objects instantiated by the constructor.

Since you're giving only fragmentary information at a time, we can go forward only by the limited extent at a time...

Now you may define another constructor for tvpiProgram and modify the constructor for etvProgram accordingly. Like this :

--SCRIPT SERVER (part) REVISED 1
on mkTvpiProgram()
script tvpiProgram
property p1 : 0
property p2 : 0
-- etc.
end script
end mkTvpiProgram
on mkEtvProgram(pobj, x)
script etvProgram
property parent : pobj
property UID : x
end script
end mkEtvProgram

global etvList

on init()
--omitted
end init

on getEtvList()
set etvList to {} -- global
tell application "EyeTV"
with timeout of 3 seconds
set tempList to every program whose start time > now or enabled is false
repeat with etvp in tempList
set eid to etvp's unique ID as integer
set end of etvList to my mkEtvProgram(my mkTvpiProgram(), eid) -- # no object sharing
end repeat
end timeout
end tell
end getEtvList
--END OF SCRIPT SERVER (part) REVISED 1


Or if you wish, you may simply go back to the original copy scheme and only avoid copying to global context. Like this :

--SCRIPT SERVER (part) REVISED 2
script etvProgram
property parent : tvpiProgram
property UID : missing value
end script

--global etvList -- # removed
on init()
--omitted
end init

on getEtvList()
local etvList, etvSched -- # added, though redundant if global declaration is not present
set etvList to {} -- # local
tell application "EyeTV"
with timeout of 3 seconds
set tempList to every program whose start time > now or enabled is false
repeat with etvp in tempList
set eid to etvp's unique ID as integer
copy etvProgram to etvSched -- # deep copy s/o to local variable
copy eid to etvSched's UID
set end of etvList to etvSched -- # store copied s/o in local list
end repeat
end timeout
end tell
end getEtvList
--END OF SCRIPT SERVER (part) REVISED 2


Good luck,
H

tell/scoping problem

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.