#!/usr/bin/python

# capture_cam.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--
#       May 25, 2006            bar
#       May 25, 2006            bar     TZKeyReady and idle priority
#       June 2, 2006            bar     'r' key refreshes
#       June 11, 2006           bar     allow only q and ESC to quit
#       June 13, 2006           bar     handle capture failures
#       June 24, 2006           bar     handle write failures
#       October 12, 2007        bar     handle the new video board being in the first slot, more or less (devnum == 1 is the web cam now)
#       November 1, 2007        bar     vidcap needs importing, etc.
#       November 18, 2007       bar     turn on doxygen
#       November 27, 2007       bar     insert boilerplate copyright
#       May 17, 2008            bar     email adr
#       August 23, 2008         bar     error out if not under windows
#       December 22, 2008       bar     make the timestamp red
#       May 25, 2010            bar     tz_os_priority
#       December 11, 2010       bar     kludge for Ubuntu and one camera that works
#       December 12, 2010       bar     reorg
#                                       get time text and color in to linux version
#       December 13, 2010       bar     use smart color logic for linux version
#                                       uh. well, yeah, make it smart
#       November 29, 2011       bar     pyflake cleanup
#       --eodstamps--
##      \file
#
#       Capture a web cam picture every so often to a file
#
#

import  os
import  shutil
import  sys
import  tempfile
import  time


#       http://www.pythonware.com/products/pil/
import  Image, ImageDraw, ImageFont


NO_EXIST_ERROR  = "The device with the specified device number does not exist."

Device  = None
try :
    #       http://videocapture.sourceforge.net/
    from    VideoCapture import Device
    import  vidcap
except ImportError :
    try :
        from    opencv import  highgui
        # import  opencv

        class   vidcap(object) :
            error   = ValueError

        class   Device(object) :

            devs            = {}

            def __init__(me, devnum = 0) :
                me.devnum   = devnum or 0
                me.cam      = me.devs.get(me.devnum, highgui.cvCreateCameraCapture(me.devnum))
                if not me.cam :
                    if  not os.path.exists("/dev/video%d" % me.devnum) :
                        raise vidcap.error(NO_EXIST_ERROR)
                    raise vidcap.error("Can't open video device %d" % me.devnum)
                me.devs[me.devnum]  = me.cam
                highgui.cvSetCaptureProperty(me.cam, highgui.CV_CAP_PROP_FRAME_WIDTH,  324)
                highgui.cvSetCaptureProperty(me.cam, highgui.CV_CAP_PROP_FRAME_HEIGHT, 240);

            def getImage(me, timestamp = None, textcolor = None) :
                t       = time.time()
                ts      = time.asctime(time.localtime(t)).strip()
                img     = None
                frame   = highgui.cvQueryFrame(me.cam)
                if  frame :
                    temp_dir    = tempfile.mkdtemp()
                    fn  = os.path.join(temp_dir, "capture_cam_py_temp.png")
                    highgui.cvSaveImage(fn, frame)
                    img = Image.open(fn)
                    img.load()
                    if  timestamp :
                        ( w, h )    = img.size
                        dr          = ImageDraw.Draw(img)
                        fnt         = ImageFont.load_default()
                        ( tw, th )  = fnt.getsize(ts)
                        if  textcolor == None :
                            ar      = 0
                            ag      = 0
                            ab      = 0
                            for x in xrange(tw) :
                                for y in xrange(th) :
                                    px  = img.getpixel((x, y))
                                    ar += px[0]
                                    ag += px[0]
                                    ab += px[0]
                                pass
                            th      = max(1, th)
                            tw      = max(1, tw)
                            ar     /= (tw * th)
                            ag     /= (tw * th)
                            ab     /= (tw * th)
                            ar      = 0 if ar >= 128 else 255
                            ag      = 0 if ag >= 128 else 255
                            ab      = 0 if ab >= 128 else 255
                            textcolor   = (ar << 16) | (ag << 8) | ab
                        dr.text((2, h - th - 1), ts, fill = textcolor)
                        try         :
                            shutil.rmtree(temp_dir)
                        except ( OSError, IOError ) :
                            pass
                        pass
                    pass

                return(img)

            #   Device
        pass
    except ImportError :
        pass
    pass

import  TZCommandLineAtFile
import  TZKeyReady
import  replace_file
import  tzlib


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

Creates an image file by capturing from the default device.

-d seconds or --delay seconds   Set the delay time between snapshots.

"""



def human_stop(d) :
    k   = None
    t   = time.time()
    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)) :
            return(True)
        print
        print "q - quit"
        pass

    return(False)


def get_image(devnum = 0, timestamp = False, textcolor = None) :
    cam = Device(devnum = devnum)       # do it each time 'cause it takes CPU and such
    if  cam :

        # cam.displayCaptureFilterProperties()
        # cam.displayCapturePinProperties()
        # cam.saveSnapshot("image.jpg", timestamp = 1)

        ii = cam.getImage(timestamp = timestamp, textcolor = textcolor)

        del(cam)

        if  ii :
            # ii = ii.convert("RGB")

            return(ii)

        raise ValueError("No image grabbed from %s" % str(devnum))
    raise ValueError(    "No camera for %s" % str(devnum))




if  __name__ == '__main__' :

    import  tz_os_priority


    if  not Device :
        print "I run only under Windows!"
        sys.exit(101)

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


    delay       = 60 * 5
    ofile_name  = None

    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", "-wd", "-d",  ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        delay  = int(sys.argv.pop(oi))



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


    ofile_name = sys.argv.pop(0)


    tz_os_priority.set_proc_to_idle_priority()

    devnum  = 0
    errok   = False

    while True :
        d   = delay

        ii  = None
        try :
            ii  = get_image(devnum = devnum, timestamp = 1, textcolor = None)
            ( twidth, thite ) = ii.size

            if  not (((twidth <= 352) and (thite <= 288))) : # or ((twidth == 320) and (thite == 240)) or ((twidth == 640) and (thite == 480))) :
                del(ii)
                devnum += 1
                continue

                print "Doesn't appear to be the web cam (dev%u width=%u hite=%u)!" % ( devnum, twidth, thite )

                sys.exit(101)


            ( p, fn )   = os.path.split(os.path.normpath(ofile_name))
            tfile_name  = os.path.join(p, "tmp_" + fn)

            try :
                ii.save(tfile_name)
                replace_file.replace_file(ofile_name, tfile_name, ofile_name + ".bak")
                print "Saved", time.ctime(), "Cam:%u %ux%u" % ( devnum, twidth, thite )
            except IOError :
                d /= 10
                print "Write error - will try again in", d, "seconds."
            pass

        except vidcap.error :
            e   = sys.exc_info()
            if  str(e[1]) == NO_EXIST_ERROR :
                print "Cannot find the video camera on %u!" % ( devnum )
                if  not errok :
                    sys.exit(119)
                if  human_stop(delay) :
                    break
                pass

            print "error on dev " + str(devnum) + " [" + str(e[0]) + "][" + str(e[1]) + "][" + str(e[2]) + "]"
            devnum += 1

        except ValueError :
            d       = delay / 10

        if  ii and (not delay) :
            break

        if  human_stop(d) :
            break

        pass

    pass


#
#
# eof

