#pySMX
#Interface library for Sumix cameras
#Originally intended for use with Sumix M73 camera, SMXM7X.DLL ,
# but I think you should be able to substitute any of the Sumix DLL for
# application with another camera.

# Andrew Pullin, 2010
# ap@andrewpullin.org

from ctypes import *

## Helpful parameters, enums
(FREQ_40,FREQ_24,FREQ_20,FREQ_16, \
 FREQ_13,FREQ_12,FREQ_10,FREQ_8, \
 FREQ_6,FREQ_32, FREQ_48) = range(0,11)
MaxFrameSize = (2048*1600)

## Structures
class TFrameParams(Structure):
    _fields_ = [("StartX",c_int), ("StartY",c_int), # start position
                ("Width",c_int), ("Height",c_int),  # size of frame
                ("Decimation",c_int),    # 1,2,4 (,8 for color camera)
                ("ColorDeep", c_int),     # 8 or 24
                ("MirrorV",c_ubyte),   # vertical
                ("MirrorH",c_ubyte)]   # horizontal

class TCameraInfo(Structure):
    _fields_ = [("SensorType",c_int),("MaxWidth",c_int),
                ("MaxHeight",c_int),("DeviceName",c_char * 64)]

class TCameraInfoEx(Structure):
    _fields_ = [("HWModelID",c_ushort),("HWVersion",c_ushort),
                ("HWSerial",c_ulong),("Reserved",c_ubyte * 5)]

class TRgbPix(Structure):
     _fields_ = [("b",c_ubyte),
                 ("g",c_ubyte),
                 ("r",c_ubyte)]
     
## Main class
class pySMX:

    handle = c_void_p()          # handle is initially a NULL pointer
    isOpen = False;
    
    def __init__(self):
        self.camdll = windll.LoadLibrary("SMXM7x.dll")

    def CxOpenDevice(self,camNumber):
        self.handle = self.camdll.CxOpenDevice(int(camNumber))
        if self.handle == -1:
            print "No camera at DeviceID ",camNumer
        if bool(self.handle):
            self.isOpen = True          # camera handle opened succesfully
        else:
            print "Error opening camera device"

    def CxCloseDevice(self):
        self.camdll.CxCloseDevice(self.handle)
        if bool(self.handle):
            self.isOpen = False         # camera handle closed succesfully
        else:
            print "Error closing camera device"

    def CxGetScreenParams(self, params):
        retval = c_int()
        retval = self.camdll.CxGetScreenParams(self.handle,byref(params))
        if retval == 0:
            print "Error retrieving camera parameters"

    def CxSetScreenParams(self, params):
        retval = c_int()
        retval = self.camdll.CxSetScreenParams(self.handle,byref(params))
        if retval == 0:
            print "Error setting camera parameters"

    def CxActivateScreenParams(self):
        retval = c_int()
        retval = self.camdll.CxActivateScreenParams(self.handle)
        if retval == 0:
            print "Error activating camera parameters"

    def CxGetExposure(self):
        exposure = c_int()
        retval = c_int()
        retval = self.camdll.CxGetExposure(self.handle,byref(exposure))
        if retval == 0:
            print "Error getting exposure value"
        else:
            return exposure.value

    def CxSetExposure(self, exposure):
         retval = self.camdll.CxSetExposure(self.handle,byref(c_float(exposure)))
         if retval == 0:
            print "Error setting exposure value"

    def CxGetExposureMs(self):
        exposure = c_float()
        retval = c_int()
        retval = self.camdll.CxGetExposureMs(self.handle,byref(exposure))
        if retval == 0:
            print "Error getting exposure value (in ms)"
        else:
            return exposure.value

    def CxSetExposureMs(self, exposure):
        exposureActual = c_float()
        retval = self.camdll.CxSetExposureMs(self.handle,c_float(exposure),byref(exposureActual))
        if retval == 0:
            print "Error setting exposure value (in ms)"
        else:
            return exposureActual.value

    def CxGetExposureMinMax(self):
        exposureMin = c_int()
        exposureMax = c_int()
        retval = self.camdll.CxGetExposureMinMax(self.handle, \
                                                 byref(exposureMin),byref(exposureMax))
        if retval == 0:
            print "Error getting exposure min/max"
        else:
            return [exposureMin.value,exposureMax.value]
         
    def CxGetExposureMinMaxMs(self):
        exposureMin = c_float()
        exposureMax = c_float()
        retval = self.camdll.CxGetExposureMinMax(self.handle, \
                                                 byref(exposureMin),byref(exposureMax))
        if retval == 0:
            print "Error getting exposure min/max (in ms)"
        else:
            return [exposureMin.value,exposureMax.value]
    
    def CxGetFrequency(self):
        frequency = c_ubyte()
        retval = self.camdll.CxGetFrequency(self.handle,byref(frequency))
        if retval == 0:
            print "Error getting frequency setting"
        else:
            return frequency.value
    
    def CxSetFrequency(self,frequency):
        frequency = c_ubyte(frequency)
        retval = self.camdll.CxSetFrequency(self.handle,frequency)
        if retval == 0:
            print "Error setting frequency setting"
    
    def CxGetStreamMode(self):
        streamMode = c_ubyte()
        retval = self.camdll.CxGetStreamMode(self.handle,byref(streamMode))
        if retval == 0:
            print "Error getting stream mode"
        else:
            return streamMode.value

    def CxSetStreamMode(self,streamMode):
        streamMode = c_ubyte(streamMode)
        retval = self.camdll.CxSetStreamMode(self.handle,streamMode)
        if retval == 0:
            print "Error setting stream mode"
        
    def CxGrabVideoFrame():
        pass
    
    def CxSetGain(self, G1, R, G2, B):  #not working
        G1 = c_int(G1)
        R = c_int(R)
        G2 = c_int(G2)
        B = c_int(B)
        retval = self.camdll.CxSetGain(self.handle,G1,R,G2,B)
        if retval == 0:
            print "Error Setting gains"
          
    def CxGetGain(self):   #not working
        G1 = c_int()
        R = c_int()
        G2 = c_int()
        B = c_int()
        retval = self.camdll.CxSetGain(self.handle,byref(G1),byref(R), \
                                       byref(G2),byref(B))
        if retval == 0:
            print "Error getting gains"
        else:
            print G1
            print R
            print G2
            print B
            return [G1.value,R.value,G2.value,B.value]
    
    def CxSetAllGain(self, gain):   #not working
        gain = c_int(gain)
        retval = self.camdll.CxSetAllGain(self.handle,gain)
        if retval == 0:
            print "Error setting all gains"
    
    def CxSetBrightnessContrastGamma():
        pass
    
    def CxSetConvertionTab():
        pass
    
    def CxGetConvertionTab():
        pass
    
    def CxSetDefaultConvertionTab():
        pass
    
    def CxStartVideo():   # relies on windows API ; will not be implemented
        print "CxStartVideo() is not implemented"
    
    def CxStopVideo():    # relies on windows API ; will not be implemented
        print "CxStopVideo() is not implemented"
    
    def CxSetBayerAlg(self, alg):
        retval = self.camdll.CxSetBayerAlg(self.handle,c_int(alg))
        if retval == 0:
            print "Error setting Bayer algorithm"

    def CxBayerToRgb():
        pass
    
    def CxGetFrameCounter():
        frameCount = c_uint()
        retval = self.camdll.CxGetFrameCounter(self.handle,byref(frameCount))
        if retval == 0:
            print "Error getting frame counter"
        else:
            return frameCount.value
    
    def CxGetCameraInfo(self):
        camInfo = TCameraInfo()
        camInfo_p = pointer(camInfo)
        retval = self.camdll.CxGetCameraInfo(self.handle,camInfo_p)
        if retval == 0:
            print "Error getting camera info"
        else:
            return camInfo
    
    def CxGetCameraInfoEx(self):
        camInfoEx = TCameraInfoEx()
        camInfoEx_p = pointer(camInfoEx)
        retval = self.camdll.CxGetCameraInfoEx(self.handle,camInfoEx_p)
        if retval == 0:
            print "Error getting extended camera info"
        else:
            return camInfoEx
    
    def CxGetFramePtr(self):
        framePtr = c_void_p()
        retval = self.camdll.CxGetFramePtr(self.handle,framePtr)
        if retval == 0:
            print "Error getting frame pointer"
            return c_void_p() # return a null pointer ; maybe return nothing?
        else:
            return framePtr
    
    def CxGetSnapshot():
        pass
    
    def CxCancelSnapshot(self):
        retval = self.camdll.CxCancelSnapshot(self.handle)
        if retval == 0:
            print "Error cancelling hardware snapshot"
    
    def CxSet10BitsOutput(self, mode):
        retval = self.camdll.CxGet10BitsOutput(self.handle,c_ubyte(mode))
        if retval == 0:
            print "Error setting 10bit output mode"
    
    def CxGet10BitsOutput(self):
        tenBit = c_ubyte()
        retval = self.camdll.CxGet10BitsOutput(self.handle,byref(tenBit))
        if retval == 0:
            print "Error getting 10bit output mode"
        elif tenBit.value == 1:
            return True
        else:
            return False
    
