#!/usr/bin/python

# capture_screen.py
#       --copyright--                   Copyright 2007 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       January 27, 2007        bar
#       February 13, 2007       bar     --day_dir option
#       March 2, 2007           bar     catch an error that might happen when monitors are being fooled with
#       March 15, 2007          bar     get help_str up to date
#                                       month_dir
#       November 18, 2007       bar     turn on doxygen
#       November 27, 2007       bar     insert boilerplate copyright
#       May 17, 2008            bar     email adr
#       August 16, 2008         bar     de-windows-able
#       August 23, 2008         bar     --once ('cause cron can run it)
#                                       --quiet
#       October 4, 2009         bar     --year_dir
#       May 25, 2010            bar     tz_os_priority
#       November 29, 2011       bar     pyflake cleanup
#       February 4, 2012        bar     --no_screen_saver
#       --eodstamps--
##      \file
#
#       Capture a the PC screen every so often to a file
#
#       For keyboard and mouse monitoring:
#
#           SetWindowsHookEx(WH_KEYBOARD | WH_MOUSE, xproc, None, wx.Thread.GetCurrentId())
#
#           pyhook is ready to install as soon as the install program can find py 2.4
#
#           http://www.cs.unc.edu/~parente/tech/tr08.shtml
#           http://www.koders.com/csharp/fid5A01E145B2C558597228C7D92CC6CAFAE9CD582E.aspx
#
#
#

import  os
import  sys
import  time

import  wx

import  tzlib


class an_app(wx.App) :


    def OnInit(me) :

        me.SetAppName(__file__)

        return(True)

    # an_app




def get_screen_grab() :
    """
        Grab an image from the whole virtual screen, multiple monitors included.
    """

    app = an_app(0)

    pd  = wx.Display()
    c   = pd.GetCount()

    r   = wx.Rect(0, 0, 0, 0)
    for d in xrange(c) :
        pd  = wx.Display(d)
        r  = r.Union(pd.GetGeometry())


    sdc = wx.ScreenDC()

    bm  = wx.EmptyBitmap(r.width, r.height)
    dc  = wx.MemoryDC(bm)
    dc.Clear()

    dc.Blit(0, 0, r.width, r.height, sdc, r.x, r.y, wx.COPY)

    try :
        im  = bm.ConvertToImage()           # this is what might cause an exception, like when I'm fooling with the monitors
        im.SetOption("quality", "50")
    except :
        im  = None
        pass


    del(dc)
    del(bm)
    del(sdc)
    del(app)

    return(im)





help_str = """
python %s (options) output_file

Creates an image file by capturing from the PC screen.

-d seconds or --delay seconds       Set the delay time between snapshots.
-z w h     or --size width hite     Set the output size.
-t         or --timestamp           Name the image with their times.
-r         or --day_dir             Put the image files in directories by day of month.
-m         or --month_dir           Put the image files in directories by month number.
-s n       or --scale n             Multiply the image width and height by 'n'.
-1         or --once                Do only 1 capture.
                                      (Second --once causes 1 try only.)
--no_screen_saver                   Do not capture while screen saver is running (Gnome only).


"""

if  __name__ == '__main__' :

    import  TZCommandLineAtFile
    import  TZKeyReady
    import  replace_file
    import  tz_os_priority


    program_name    = sys.argv.pop(0)
    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)


    delay       = 60 * 5
    ofile_name  = None
    width       = -1
    hite        = -1
    scale       = 0
    timestamp   = False
    day_dir     = False
    month_dir   = False
    year_dir    = False
    once        = 0
    quiet       = False
    scr_save    = True


    if  tzlib.array_find(sys.argv, [ "--help", "-h", "-H", "-?", "/h", "/H", "/?" ] ) >= 0 :
        print help_str % os.path.basename(program_name)
        sys.exit(254)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--delay", "-d" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        delay  = int(sys.argv.pop(oi))


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--size", "-z" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        width   = int(sys.argv.pop(oi))
        hite    = int(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--scale", "-s" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        scale   = float(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--timestamp", "-t" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        timestamp   = True

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--day_dir", "-r" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        day_dir     = True

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--month_dir", "-m" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        month_dir   = True

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--year_dir", "-y" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        year_dir    = True

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--once", "-1" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        once       += 1

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--quiet", "-q" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        quiet       = True

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--no_screen_saver", "--noscreensaver", "--no-screen-saver", "--no_screen_save", "--noscreensave", "--no-screen-save", ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        scr_save    = False


    if  len(sys.argv) != 1 :
        print "No output file name!"
        sys.exit(101)


    ofile_name = os.path.abspath(sys.argv.pop(0))

    tz_os_priority.set_proc_to_idle_priority()

    while True  :
        d           = delay
        ii          = None
        if  scr_save or (not tzlib.in_screen_saver()) :
            ii      = get_screen_grab()             # gets the whole virtual screen's image
            if  ii is None :
                d   = delay / 10.0
            pass
        elif once   :
            break

        if  ii == None :
            if  once > 1 :
                break
            pass

        else :

            twidth      = ii.Width
            thite       = ii.Height

            if  (width > 0) and (hite > 0) and ((width != twidth) or (hite != thite)) :
                ii      = ii.Scale(width, hite,  wx.IMAGE_QUALITY_HIGH)

            if  scale :
                ii      = ii.Scale(twidth * scale, thite * scale,  wx.IMAGE_QUALITY_HIGH)

            lt          = time.localtime()

            ofname      = ofile_name

            if  year_dir :
                (pt, fn)    = os.path.split(ofname)
                ofname      = os.path.join(pt, "y%04d" % ( lt.tm_year ))
                if  not os.path.isdir(ofname) :
                    os.makedirs(ofname)
                ofname      = os.path.join(ofname, fn)

            if  month_dir :
                (pt, fn)    = os.path.split(ofname)
                ofname      = os.path.join(pt, "m%02d" % ( lt.tm_mon ))
                if  not os.path.isdir(ofname) :
                    os.makedirs(ofname)
                ofname      = os.path.join(ofname, fn)

            if  day_dir :
                (pt, fn)    = os.path.split(ofname)
                ofname      = os.path.join(pt, "d%02d" % ( lt.tm_mday ))
                if  not os.path.isdir(ofname) :
                    os.makedirs(ofname)
                ofname      = os.path.join(ofname, fn)


            ( fn, ext ) = os.path.splitext(os.path.normpath(ofname))

            if  timestamp :
                ss      = ""
                if  delay < 60 :
                    ss  = "_%02d" % lt.tm_sec
                    ms  = "_%02d" % lt.tm_min
                else    :
                    ms  = "_%02d" % int(int(lt.tm_min / int(delay / 60.0)) * delay / 60.0)
                fn      = "%s_%02d_%02d%s%s" % ( fn, lt.tm_mday, lt.tm_hour, ms, ss, )


            rfile_name  = fn + ext
            tfile_name  = fn + "_tmp" + ext

            try :
                ii.SaveFile(tfile_name, wx.BITMAP_TYPE_JPEG)

                replace_file.replace_file(rfile_name, tfile_name, rfile_name + ".bak")
                if  not quiet :
                    print "Saved", time.ctime(), rfile_name
                pass
            except IOError :
                d /= 10
                print "Write error - will try again in", d, "seconds."

            if  once :
                break

            pass


        t   = time.time()
        k   = None
        while time.time() - t < d :
            time.sleep(0.9)

            k   = TZKeyReady.tz_key_ready()
            if  k : break
            pass

        if  k :
            if  (k.lower() == "q") or (k == chr(27)) :
                break
            print
            print "q - quit"
            pass

        pass

    pass


#
#
# eof

