Previous 1 2 Next 29 Replies Latest reply: Jul 6, 2010 7:07 PM by Hiroto
aidrummer Level 1 Level 1 (35 points)
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
  • aidrummer Level 1 Level 1 (35 points)
    how do i store etv's unique ID as integer, independently of eyetv?
  • aidrummer Level 1 Level 1 (35 points)
    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
  • red_menace Level 6 Level 6 (14,785 points)
    I don't see where you are using any script objects (other than the top level one) - are you referring to properties or variables?

    From the AppleScript Language Guide: the copy command only copies AppleScript values, not application-defined objects. You might try using set instead.
  • Hiroto Level 5 Level 5 (5,745 points)
    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
  • aidrummer Level 1 Level 1 (35 points)
    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...
  • red_menace Level 6 Level 6 (14,785 points)
    Script objects have always been a little bit tricky, but you might just be getting caught up in some of Snow Leopard's changes. AppleScript is a bit fussier now (i.e. not as forgiving), since the script runners are now operating within the new frameworks.
  • aidrummer Level 1 Level 1 (35 points)
    thanx, but while i run on s.l., i develop on tiger, & get the same failure on both.
  • Hiroto Level 5 Level 5 (5,745 points)
    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
  • aidrummer Level 1 Level 1 (35 points)
    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;-}
  • aidrummer Level 1 Level 1 (35 points)
    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*)
  • Hiroto Level 5 Level 5 (5,745 points)
    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
  • aidrummer Level 1 Level 1 (35 points)
    yes, i awoke this morning with that realization;-) stupid "applescript is for non-programmers, nevermind what's going on behind the curtain";-}

    i'll try your multiple constructors suggestion, thanx:-)
  • aidrummer Level 1 Level 1 (35 points)
    the local list trick worked! thanx u, hiroto!
  • Hiroto Level 5 Level 5 (5,745 points)
    Hello

    My pleasure. Glad to hear you realized a simple solution.;}

    All the best,
    H
Previous 1 2 Next