#!/usr/bin/python -O

HowManyPictures = 13
TimingStep = 4
######
######  to-do
######  * add time sync to camera
######  * pull files from camera into new dir by date & time
######  * 
######
######
######

import os
import time
import datetime
import calendar
from os.path import join, getsize

# gphoto2
#/home/user> gphoto2
#Usage: gphoto2 [-?] [-?] [-?va] [-?va] [-?va] [-?va] [-?valLnPTDR] [-?|--help] [--usage] [--debug]
#        [--debug-logfile=FILENAME] [--quiet] [--hook-script=FILENAME]
#        [--stdout] [--stdout-size] [--auto-detect] [--show-exif=STRING]
#        [--show-info=STRING] [--summary] [--manual] [--about]
#        [--storage-info] [--shell] [-v|--version] [--list-cameras]
#        [--list-ports] [-a|--abilities] [--port=FILENAME] [--speed=SPEED]
#        [--camera=MODEL] [--usbid=USBIDs] [--list-config]
#        [--get-config=STRING] [--set-config=STRING] [--wait-event]
#        [--capture-preview] [-F|--frames COUNT] [-I|--interval SECONDS]
#        [--reset-interval] [--capture-image] [--capture-movie]
#        [--capture-sound] [--capture-tethered] [-l|--list-folders]
#        [-L|--list-files] [-m|--mkdir DIRNAME] [-r|--rmdir DIRNAME]
#        [-n|--num-files] [-p|--get-file RANGE] [-P|--get-all-files]
#        [-t|--get-thumbnail RANGE] [-T|--get-all-thumbnails]
#        [--get-metadata=RANGE] [--get-all-metadata]
#        [--upload-metadata=STRING] [--get-raw-data=RANGE]
#        [--get-all-raw-data] [--get-audio-data=RANGE] [--get-all-audio-data]
#        [-d|--delete-file RANGE] [-D|--delete-all-files]
#        [-u|--upload-file filename] [--filename=FILENAME_PATTERN]
#        [-f|--folder FOLDER] [-R|--recurse] [--no-recurse] [--new]
#        [--force-overwrite]

#  /home/user> gphoto2 --summary
#  Camera summary:
#  Model: D40X
#    device version: V1.00
#    serial number:  6002549
#  Vendor extension ID: 0x00000006
#  Vendor extension description: microsoft.com: 1.0
#  
#  Capture Formats: JPEG Undefined Type
#  Display Formats: JPEG, Undefined Type, Association/Directory, DPOF, Script
#  Supported MTP Object Properties:
#   JPEG/3801: dc01/StorageID dc02/ObjectFormat dc03/ProtectionStatus dc04/ObjectSize dc07/ObjectFileName dc0b/ParentObject dc41/PersistantUniqueObjectIdentifier dc44/Name dc87/Width dc88/Height dcd3/ImageBitDepth dc08/DateCreated dc09/DateModified dc81/RepresentativeSampleFormat dc82/RepresentativeSampleSize dc83/RepresentativeSampleHeight dc84/RepresentativeSampleWidth dc86/RepresentativeSampleData
#   Undefined Type/3000: dc01/StorageID dc02/ObjectFormat dc03/ProtectionStatus dc04/ObjectSize dc07/ObjectFileName dc0b/ParentObject dc41/PersistantUniqueObjectIdentifier dc44/Name dc08/DateCreated dc09/DateModified
#   Association/Directory/3001: dc01/StorageID dc02/ObjectFormat dc03/ProtectionStatus dc04/ObjectSize dc07/ObjectFileName dc0b/ParentObject dc41/PersistantUniqueObjectIdentifier dc44/Name dc08/DateCreated dc09/DateModified
#   DPOF/3006: dc01/StorageID dc02/ObjectFormat dc03/ProtectionStatus dc04/ObjectSize dc07/ObjectFileName dc0b/ParentObject dc41/PersistantUniqueObjectIdentifier dc44/Name dc08/DateCreated dc09/DateModified
#   Script/3002: PTP error a802 on query
#  
#  Device Capabilities:
#   File Download, File Deletion, File Upload
#   Generic Image Capture, No Open Capture, No vendor specific capture

#  Storage Devices Summary:
#  store_00010001:
#   StorageDescription: None
#   VolumeLabel: NIKON D40X
#   Storage Type: Removable RAM (memory card)
#   Filesystemtype: Digital Camera Layout (DCIM)
#   Access Capability: Read Only with Object deletion
#   Maximum Capability: 4108320768 (3918 MB)
#   Free Space (Bytes): 3994484736 (3809 MB)
#   Free Space (Images): 320

#  Device Property Summary:
##  Battery Level(0x5001):(read only) (type=0x2) Range [0 - 100, step 1] value: 100
#  Image Size(0x5003):(readwrite) (type=0xffff) Enumeration [   '3872x2592',    '2896x1944',    '1936x1296' ] value: '3872x2592'
#  Compression Setting(0x5004):(readwrite) (type=0x2) Enumeration [0,1,2,3,4] value: 3
#  White Balance(0x5005):(readwrite) (type=0x4) Enumeration [2,4,5,6,7,32784,32785,32787] value: 2
#  F-Number(0x5007):(readwrite) (type=0x4) Enumeration [350,400,450,500,560,630,710,800,900,1000,1100,1300,1400,1600,1800,2000,2200] value: 560
##  Focal Length(0x5008):(read only) (type=0x6) Range [1800 - 20000, step 1] value: 1800
##  Focus Mode(0x500a):(read only) (type=0x4) Enumeration [1,32784,32785,32786] value: 32784
#  Exposure Metering Mode(0x500b):(readwrite) (type=0x4) Enumeration [2,3,4] value: 2
#  Flash Mode(0x500c):(readwrite) (type=0x4) Enumeration [4,32784,32786] value: 32784
#  Exposure Time(0x500d):(readwrite) (type=0x6) Enumeration [2,3,4,5,6,8,10,12,15,20,25,31,40,50,62,80,100,125,166,200,250,333,400,500,666,769,1000,1250,1666,2000,2500,3333,4000,5000,6250,7692,10000,13000,16000,20000,25000,30000,40000,50000,60000,80000,100000,130000,150000,200000,250000,300000,4294967295] value: 20
#  Exposure Program Mode(0x500e):(read only) (type=0x4) Enumeration [1,2,3,4,32784,32792,32785,32786,32791,32788,32787,32789] value: 1
#  Exposure Index (film speed ISO)(0x500f):(readwrite) (type=0x4) Enumeration [100,200,400,800,1600,3200] value: 100
#  Exposure Bias Compensation(0x5010):(readwrite) (type=0x3) Enumeration [-5000,-4666,-4333,-4000,-3666,-3333,-3000,-2666,-2333,-2000,-1666,-1333,-1000,-666,-333,0,333,666,1000,1333,1666,2000,2333,2666,3000,3333,3666,4000,4333,4666,5000] value: 0
#  Date Time(0x5011):(readwrite) (type=0xffff) '20080310T204148'
#  Still Capture Mode(0x5013):(readwrite) (type=0x4) Enumeration [1,2,32785,32787,32788] value: 1
#  Burst Number(0x5018):(readwrite) (type=0x4) Range [1 - 51, step 1] value: 1
#  Focus Metering Mode(0x501c):(readwrite) (type=0x4) Enumeration [2,32784,32785] value: 2
#  Property 0xd406:(readwrite) (type=0xffff) 'Windows/6.0.5330.0 MTPClassDriver/6.0.5330.0'
##  Property 0xd407:(read only) (type=0x6) 1

#--------------------Class---------------------------

class CamValues:
        def __init__(self, Name, CamPath, ParseString, CamValue, NewValue, Option):
                self.Name               = Name
                self.CamPath            = CamPath
                self.ParseString        = ParseString
                self.CamValue           = CamValue
                self.NewValue           = NewValue
                self.Option             = Option
        def __cmp__(self,other):
                return cmp(other.Name, self.Name)

#--------------------Variables-----------------------


CamGet = (("CamTime" ,            "/main/settings/time" ,                     "Date Time" , '','' ),
          ("CamBattery" ,         "/main/settings/battery" ,                  "Battery Level" , '' ,'' ),
          ("CamImgQuality",       "/main/imgsettings/imgquality" ,            "Compression Setting" , '','' ),
          ("CamImgSize",          "/main/imgsettings/imgsize" ,               "Image Size" , '','' ),
          ("CamWhiteBalance",     "/main/imgsettings/whitebalance" ,          "White Balance" , '','' ),
          ("CamFnumber",          "/main/capturesettings/f-number" ,          "F-Number" , '','' ),
          ("CamFocalLength",      "/main/capturesettings/focallength" ,       "Focal Length" , '','' ),
          ("CamFocusMode",        "/main/capturesettings/focusmode" ,         "Focus Mode" , '','' ),
          ("CamIso",              "/main/capturesettings/iso" ,               "Exposure Index" , '','' ),
          ("CamExposureBiasCompensation","/main/capturesettings/exposurebiascompensation" , "Exposure Bias Compensation" , '','' ),
          ("CamExpTime",          "/main/capturesettings/exptime" ,           "Exposure Time" , '','' ),
          ("CamExpProgram",       "/main/capturesettings/expprogram" ,        "Exposure Program Mode" , '','' ),
          ("CamCaptureMode",      "/main/capturesettings/capturemode" ,       "Still Capture Mode" , '','' ),
          ("CamFocusMeterMode",   "/main/capturesettings/focusmetermode" ,    "Focus Metering Mode" , '','' ),
          ("CamExposureMeterMode","/main/capturesettings/exposuremetermode" , "Exposure Metering Mode" , '','' ),
          ("CamFlashMode",        "/main/capturesettings/flashmode" ,         "Flash Mode" , '','' ),
          ("CamBurstNumber",      "/main/capturesettings/burstnumber" ,       "Burst Number" , ''),
          ("CamCaptureTarget",    "/main/settings/capturetarget" ,       	   " " , '')         
          )      
Cam   = []
CamOpt = []
CamRead =''

#--------------------Sub-Routiens--------------------

def pSystem( cmd):
#        print cmd
#        print "******************************"
        os.system( cmd)

def pPopen( cmd):
#        print "pPopen: " + cmd
#        print "******************************"
        return os.popen( cmd).readlines()

def UniformTime( ExposureTime ):
	# Convert to string format
    ExpTime = str(" %.3f" % (float(ExposureTime) / 1000))
#    print "ExptTime_4Digit: " + ExpTime + "input" + ExposureTime
    if int(float(ExpTime)) == float(ExpTime):
      ExpTime = str(int(float(ExpTime)))
    return  ExpTime.strip()


def ReadCam( Name):
    print "*******Read Cammera Settings*********"
    for ReadValue in Cam:
#       print "Read:ReadValue=" +  ReadValue.Name + " Name=" + Name
        if ReadValue.Name == Name:
#           print "match Name"
            CamReturn = pPopen("gphoto2 --get-config=" + ReadValue.CamPath)
            for b in CamReturn:
                if not b.find('Current:'):
                    tmp = b.replace( 'Current: ' , '' )
                    tmp = tmp.replace( 'Unknown value ' , '')
                    tmp = tmp.replace( '\n' , '')
#                    print "*** " + tmp
                    return tmp

def InitApp():
        print "*** READ Summary from Cammera ***"
        CamRead = pPopen("gphoto2 --summary")
#        print CamRead
        i = 0
        for Options in CamGet:
#                print "################### - " + CamGet[i][0]
                if CamGet[i][0] is "CamTime":
                    Cam.append( CamValues(CamGet[i][0] , CamGet[i][1], CamGet[i][2], '' , '' , '' ) )
                for LineOptions in CamRead:
                        if not LineOptions.find(CamGet[i][2]):
#                                print LineOptions
                                CamValue = LineOptions.split(':')
                                CamValue = CamValue[-1]
#                                print "\n***** Value: " + CamValue + '\n'
                                if  CamValue.find('('):
                                    CamValue = CamValue.split()
                                    CamValue = CamValue[-1]
#                                    print "if (:" +  CamValue
                                    CamValue = CamValue.replace('(','')                
                                    CamValue = CamValue.replace(')','')                
 #                                   print "Ttralal:" + CamValue
                                for a in LineOptions.split(' '):
#                                        print "\nprint a: " + a
                                        Values = ''
                                        if not a.find("["):
#                                                print "print aa: " +  a
                                                Values = a.replace('[' , '')
                                                Values = Values.replace(']' , '')
#                                                Values = Values.split(",")                               
#                                                print Values
                                                Cam.append( CamValues(CamGet[i][0] , CamGet[i][1], CamGet[i][2], CamValue , '' , str(Values ) ) )

                i = i+ 1

      
def WriteCam( Name, Value):
#    print "*******Write Cammera Settings********* " + Name
    for WriteValue in Cam:
#        print "%%%%  " +  WriteValue.Name + "::" + Name
        if WriteValue.Name == Name:
#            print Name + " == " + Value
            WriteValue.NewValue = Value
            CamReturn = pPopen("gphoto2 --set-config=" + WriteValue.CamPath + "=" + WriteValue.NewValue)

def ShowCamParameters():
    for a in Cam:
            print a.Name + " : " + a.CamValue + " : " + a.NewValue

def SetDefaultCamValue():
    print "*** Start Write Default Settings"
    WriteCam("CamImgQuality","3")
    WriteCam("CamImgSize","0")
    WriteCam("CamWhiteBalance","0")
    WriteCam("CamFocusMode","2")
    WriteCam("CamIso","0")
    WriteCam("CamExposureBiasCompensation","0")
    WriteCam("CamExpProgram","0")
    WriteCam("CamCaptureMode","0")
    WriteCam("CamFocusMeterMode","0")
    WriteCam("CamExposureMeterMode","1")
    WriteCam("CamFlashMode","1")
    WriteCam("CamBurstNumber","1")
    pPopen("gphoto2 --set-config=/main/settings/capturetarget=1" )
    print "*** Finished Write Default Settings"

def TakePicture( ExposureTime ):
#    ExposureTime = ExposureTime.strip
#    WriteCam("CmExpTime" , UniformTime(ExposureTime) )
    pPopen("gphoto2 --set-config=/main/capturesettings/exptime=" + UniformTime(ExposureTime) )
#    ReadNow = ReadCam("CamExpTime")
#    print "ReadFromCam: " + ReadNow
#    time.sleep(int(ExposureTime))
#    if UniformTime(ExposureTime) == ReadNow:
#    ShowCamParameters()
    CamReturn = pPopen("gphoto2 --capture-image")
  #      for b in CamReturn:
  #          if not b.find('XXXXXXX'):
  #              tmp = b.replace( 'Current: ' , '' )
  #              tmp = tmp.replace( 'Unknown value ' , '')
  #              tmp = tmp.replace( '\n' , '')
#                print "*** " + tmp
   #             return tmp
#    else:
 #       print "Can not take take image, setting is wrong: Expusure: " + ExposureTime + " and readvalue: " + ReadNow
    

def TakeSeries( HowMany , CenterTime , Step ):
    i = 0
    for q in ExpOption:
#        print q ,  CenterTime
        if int(q) == int(CenterTime):
#            print "match " + str(q) + " pos:" + str(i)
            MinTime = i - (( HowMany - 1 ) /2 * Step )
            MaxTime = i + (( HowMany - 1 ) /2 * Step ) + 1
            if MinTime < 0:
                MinTime = 0
                MaxTime = HowMany * Step
            if MaxTime > 52:
                MaxTime = 52
                MinTime = 52 - ( HowMany  * Step )
            for a in range(MinTime,MaxTime,Step):
#                print MinTime, MaxTime, a
#                ExpTime = " %.3f" % (float(ExpOption[a]) / 1000)
#                print "ExptTime_4Digit: " + ExpTime
#                if int(float(ExpTime)) == float(ExpTime):
#                     ExpTime = str(int(float(ExpTime)))
#                ExpTime = ExpTime.strip()
#                print "ExpTime =:" + ExpTime + ":="
                print "Take picture with " + str( float(UniformTime( str(ExpOption[a]) ) ) * 100) + "ms Exposure Time"
                TakePicture( str(ExpOption[a]) )
        i = i + 1
    print "All pictures have been taken"
        
def SetCamTime():
 #  print time.strftime("%Y%m%dT")
 #   tmp = ReadCam("CamTime")
#    print "System Time: " +  str(int(time.time()))
    WriteCam("CamTime" , str(int(time.time())) )

def GetThumb(Path):
    CurrentPath = str(pPopen("pwd"))
    CurrentPath = CurrentPath.replace('\\n','')
    CurrentPath = CurrentPath.replace('[','')
    CurrentPath = CurrentPath.replace(']','')
    pPopen( " cd "+ Path + " ; gphoto2 -T --force-overwrite ; cd " + str(CurrentPath) + " ; ")

### -------------------- MAIN --------------------------- ####

InitApp()
#ShowCamParameters()
SetDefaultCamValue()
SetCamTime()
	
for o in Cam:
        if (o.Name is 'CamExpTime'):
#                print o.Name , o.CamValue
                ExpOption = o.Option
                ExpOption = ExpOption.split(',')
#                print ExpOption
        

i=0
for b in Cam:
    if (b.Name is 'CamExpTime'):
#        print "CenterTime: " + b.CamValue
        print "Current ExpTime is " + str(int(float(b.CamValue)/10)) + "ms Taking " + str(HowManyPictures)  + "  pictures with " + str(TimingStep) + " steps"
        TakeSeries( HowManyPictures , b.CamValue , TimingStep )      
## ------------------Save  --------
        print "-------restore start setting:" + UniformTime(b.CamValue)
        WriteCam( b.Name, UniformTime( str( float( b.CamValue) ) ) )
    i= i + 1

#GetThumb("/home/user/thumb")
