# Python bindings for the 2263 middleware api
# Copyright(c) 2010-2022 Sensoray Co., Inc.


"""
Python bindings for the 2263 middleware api
"""

from ctypes import *
import os

NTSC = 1
PAL = 2

RECMODE_TS = 0
RECMODE_TS_NOAUDIO = 1
RECMODE_H264 = 2
RECMODE_MJPEG = 3
RECMODE_MP4 = 4
RECMODE_MP4_NOAUDIO = 5
RECMODE_AVI = 6
RECMODE_AVI_NOAUDIO = 7
#MID2263_RECMODE_AVI = 6 // AVI with audio
#MID2263_RECMODE_AVI_NOAUDIO = 7 // AVI with no audio
RECMODE_H265 = 8



FORMAT_UYVY = 0
FORMAT_NV12 = 1

BRIGHTNESS = 0
SATURATION = 1
HUE = 2
CONTRAST = 3

DEF_BRIGHTNESS = 128
DEF_CONTRAST = 128
DEF_HUE = 0
DEF_SATURATION = 128


RATEMODE_CBR = 0
RATEMODE_VBR = 1
RATEMODE_FIXEDQP = 2

VIDEO_DVI = 0
VIDEO_COMPOSITE = 1
VIDEO_SVIDEO = 2
VIDEO_COMPONENT = 3
VIDEO_VGA = 4
VIDEO_SDI2 = 5
VIDEO_SDI = 0
VIDEO_AHD1 = 0
VIDEO_AHD2 = 1

AUDIO_MIC = 0
AUDIO_LINE_IN = 1
AUDIO_ANALOG = 1
AUDIO_DIGITAL = 2

H264_BASELINE = 66
H264_MAIN = 77
H264_HIGH = 100

H264_1_0 = 10
H264_1B = 9
H264_1_1 = 11
H264_1_2 = 12
H264_1_3 = 13
H264_2_0 = 20
H264_2_1 = 21
H264_2_2 = 22
H264_3_0 = 30
H264_3_1 = 31
H264_3_2 = 32
H264_4_0 = 40
H264_4_1 = 41
H264_4_2 = 42
H264_5_0 = 50

AUDIO_NONE = 0
AUDIO_AAC = 1
AUDIO_MP3 = 2
AUDIO_PCM = 3

INTERPOLATED = 0
INTERLACED = 1
FIELD_TOP = 2
FIELD_BOTTOM = 3
FIELD_INTERLACED = 4
FIELD_SEQ_TB = 5
FIELD_SEQ_BT = 6
FIELD_ALTERNATE = 7
FIELD_INTERLACED_TB = 8
FIELD_INTERLACED_BT = 9

SLICEMODE_OFF = 0
SLICEMODE_ON = 1

FLIP_V = 1
FLIP_H = 2
ROT_180 = 3
ROT_90 = 4
ROT_270 = 7

ASPECT_NONE = 0
ASPECT_4_3 = 1
ASPECT_16_9= 2

OUTPUT_IDLE = 0
OUTPUT_PASSTHRU = 1
OUTPUT_PASSTHRU_SD = 6
OUTPUT_COLORBARS = 2

OUTPUT_AUTO = 0
OUTPUT_VGA = 4   # 640x480p60
OUTPUT_NTSC = 5  # 720x480i60
OUTPUT_PAL = 6   # 720x576i50
OUTPUT_480P60 = 7  # 720x480p60
OUTPUT_576P50 = 8  # 720x576p50
OUTPUT_720P60 = 9  # 1280x720p60
OUTPUT_720P50 = 10  # 1280x720p50
OUTPUT_720P30 = 11  # 1280x720p30
OUTPUT_1080I60 = 12  # 1920x1080i60
OUTPUT_1080I50 = 13  # 1920x1080i50
OUTPUT_1080P30 = 14  # 1920x1080p30
OUTPUT_1080P25 = 15  # 1920x1080p25
OUTPUT_1080P24 = 16  # 1920x1080p24

OUTPUT_COMPOSITE = 0
OUTPUT_DVI = 2
OUTPUT_SDI = 2

STANDARD_CVBS = 0
STANDARD_AHD = 1
STANDARD_TVI = 2
STANDARD_CVI = 3

FLAG_MP3_AUDIO = 1
FLAG_SDI = 4

OVERLAY_TEXT_DISABLED   = 0
OVERLAY_TEXT_FONT_8x14  = 1
OVERLAY_TEXT_FONT_16x16 = 2
OVERLAY_TEXT_BG_SOLID = (0 << 2)
OVERLAY_TEXT_BG_TRANSPARENT = (1 << 2)
OVERLAY_TEXT_BG_SHADED = (2 << 2)
OVERLAY_TEXT_BG_DARKSHADED = (3 << 2)
OVERLAY_TEXT_DATE_MM_DD_YYYY = (0 << 4)
OVERLAY_TEXT_DATE_DD_MM_YYYY = (1 << 4)
OVERLAY_TEXT_DATE_MM_DD_YY = (2 << 4)
OVERLAY_TEXT_DATE_DD_MM_YY = (3 << 4)
OVERLAY_TEXT_DATE_MMM_DD_YYYY = (4 << 4)
OVERLAY_TEXT_DATE_DD_MMM_YYYY = (5 << 4)
OVERLAY_TEXT_DATE_MMM_DD_YY = (6 << 4)
OVERLAY_TEXT_DATE_DD_MMM_YY = (7 << 4)
OVERLAY_TEXT_DATE_MMM_DDc_YYYY = (8 << 4)
OVERLAY_TEXT_DATE_DDMMMYYYY = (9 << 4)
OVERLAY_TEXT_DATE_MMM_DDc_YY = (10 << 4)
OVERLAY_TEXT_DATE_DDMMMYY = (11 << 4)
OVERLAY_TEXT_DATE_YYYYMMDD = (12 << 4)
OVERLAY_TEXT_DATE_YYYYMMMDD = (13 << 4)
OVERLAY_TEXT_DATE_YYMMDD = (14 << 4)
OVERLAY_TEXT_DATE_YYMMMDD = (15 << 4)
OVERLAY_TEXT_DATE_YYYY_MM_DD = (16 << 4)
OVERLAY_TEXT_DATE_YYYY_MMM_DD = (17 << 4)
OVERLAY_TEXT_DATE_YY_MM_DD = (18 << 4)
OVERLAY_TEXT_DATE_YY_MMM_DD = (19 << 4)

OVERLAY_TEXT_SECONDS_NONE = (0 << 10)
OVERLAY_TEXT_SECONDS_TENTHS = (1 << 10)
OVERLAY_TEXT_SECONDS_HUNDREDTHS = (2 << 10)
OVERLAY_TEXT_SECONDS_THOUSANDTHS = (3 << 10)
OVERLAY_TEXT_HOURS_MINUTES = (4 << 10)
OVERLAY_TEXT_HOURS_MINUTES_AM_PM = (5 << 10)
OVERLAY_TEXT_HOURS_MINUTES_A_P = (6 << 10)


S3364_INTERLACED = 0
S3364_TOP_FIELD = 1
S3364_BOTTOM_FIELD = 2
S3364_FIELD_SEQ_TB = 3

s2263mid = cdll.LoadLibrary("./libs2263.so")

CALLBACKTYPE = CFUNCTYPE(c_int, c_void_p, c_int, c_int, c_int)

def Debug(bOnOff):
	s2263mid.S2263_Debug(c_int(bOnOff))

def GetNumDevices():
	num_devices = c_int(0)
	s2263mid.S2263_GetNumDevices(byref(num_devices))
	return num_devices.value

def AVStreamRename(cardname):
	s2263mid.S2263_AVStreamRename(c_char_p(cardname.encode('utf-8')))


def Err(rc):
	if rc < 0:
		#print("normal Err");
		raise IOError(-rc, os.strerror(-rc))
	return True

def ErrMsg(msg,rc):
	if rc < 0:
		print(msg);
		raise IOError(-rc, os.strerror(-rc))
	return True

class Board(object):
	def __init__(self, brd_idx):
		self.Open(brd_idx)

	def Open(self, brd_idx):
		self.devid = c_int(brd_idx)
		Err(s2263mid.S2263_Open(self.devid))

	def Close(self):
		s2263mid.S2263_Close(self.devid)
		self.devid = c_int(-1)


	def StartRecord(self, filename, strmidx):
		Err(s2263mid.S2263_StartRecord(c_char_p(filename.encode('utf-8')), self.devid, c_int(strmidx)))

	def StopRecord(self, strmidx):
		Err(s2263mid.S2263_StopRecord(self.devid, c_int(strmidx)))

	def StartPreview(self, strmidx):
		Err(s2263mid.S2263_StartPreview(self.devid, c_int(strmidx)))

	def StopPreview(self, strmidx):
		Err(s2263mid.S2263_StopPreview(self.devid, c_int(strmidx)))

	def StartAudioPreview(self):
		Err(s2263mid.S2263_StartAudioPreview(self.devid))

	def StopAudioPreview(self):
		Err(s2263mid.S2263_StopAudioPreview(self.devid))

	def GetSerialNumber(self):
		serial = c_int(0)
		Err(s2263mid.S2263_GetSerialNumber(byref(serial), self.devid))
		return serial.value

	def GetModelNumber(self):
		model = c_int(0)
		Err(s2263mid.S2263_GetModelNumber(byref(model), self.devid))
		return model.value

	def GetFirmwareVersion(self):
		firmware = c_int(0)
		Err(s2263mid.S2263_GetFirmwareVersion(byref(firmware), self.devid))
		return firmware.value
		
	def GetAPIVersion(self):
		return s2263mid.S2263_GetAPIVersion()

	def GetFeatureFlags(self):
		flags = c_int(0)
		Err(s2263mid.S2263_GetFeatureFlags(byref(flags), self.devid))
		return flags.value

	def SetImageSize(self, width, height, strmidx):
		Err(s2263mid.S2263_SetImageSize(c_int(width), c_int(height), self.devid, c_int(strmidx)))

	def GetImageSize(self, strmidx):
		width = c_int(0)
		height = c_int(0)
		Err(s2263mid.S2263_GetImageSize(byref(width), byref(height), self.devid, c_int(strmidx)))
		return (width.value, height.value)

	def SetImageFormat(self, fmt, width, height, strmidx):
		Err(s2263mid.S2263_SetImageFormat(c_int(fmt), c_int(width), c_int(height), self.devid, c_int(strmidx)))

	def GetImageFormat(self, strmidx):
		fmt = c_int(0)
		width = c_int(0)
		height = c_int(0)
		Err(s2263mid.S2263_GetImageFormat(byref(fmt), byref(width), byref(height), self.devid, c_int(strmidx)))
		return (fmt.value, width.value, height.value)

	def SetInput(self, idx):
		Err(s2263mid.S2263_SetInput(c_int(idx), self.devid))

	def GetInput(self):
		idx = c_int(0)
		#removing error check.  Get input return -EIO
		#on 3364, but everything is working
		rc = s2263mid.S2263_GetInput(byref(idx), self.devid)
		if rc < 0:
			print("failed to get input")
		return idx.value

	def GetNumInputs(self):
		idx = c_int(0)
		Err(s2263mid.S2263_GetNumInputs(byref(idx), self.devid))
		return idx.value

	def SetAudioInput(self, idx):
		Err(s2263mid.S2263_SetAudioInput(c_int(idx), self.devid))

	def GetAudioInput(self):
		idx = c_int(0)
		Err(s2263mid.S2263_GetAudioInput(byref(idx), self.devid))
		return idx.value

	def SetAudioGain(self, agc, gain):
		Err(s2263mid.S2263_SetAudioGain(c_int(agc), c_int(gain), self.devid))

	def GetAudioGain(self):
		agc = c_int(0)
		gain = c_int(0)
		Err(s2263mid.S2263_GetAudioGain(byref(agc), byref(gain), self.devid))
		return (agc.value, gain.value)

	def SetLevel(self, idx, val):
		s2263mid.S2263_SetLevel(c_int(idx), c_int(val), self.devid)

	def GetLevel(self, idx):
		val = c_int(0)
		Err(s2263mid.S2263_GetLevel(c_int(idx), byref(val), self.devid))
		return val.value

	def SetBitrate(self, val, strmidx):
		Err(s2263mid.S2263_SetBitrate(c_int(val), self.devid, c_int(strmidx)))

	def GetBitrate(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetBitrate(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetGOPSize(self, val, strmidx):
		Err(s2263mid.S2263_SetGOPSize(c_int(val), self.devid, c_int(strmidx)))

	def GetGOPSize(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetGOPSize(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetRateMode(self, val, strmidx):
		Err(s2263mid.S2263_SetRateMode(c_int(val), self.devid, c_int(strmidx)))

	def GetRateMode(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetRateMode(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetAudioBitrate(self, val):
		Err(s2263mid.S2263_SetAudioBitrate(c_int(val), self.devid))

	def GetAudioBitrate(self):
		val = c_int(0)
		Err(s2263mid.S2263_GetAudioBitrate(byref(val), self.devid))
		return val.value

	def SetAudioMode(self, val):
		Err(s2263mid.S2263_SetAudioMode(c_int(val), self.devid))

	def GetAudioMode(self):
		val = c_int(0)
		Err(s2263mid.S2263_GetAudioMode(byref(val), self.devid))
		return val.value

	def SetInterlaceMode(self, val, strmidx):
		Err(s2263mid.S2263_SetInterlaceMode(c_int(val), self.devid, c_int(strmidx)))

	def GetInterlaceMode(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetInterlaceMode(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetAspectRatio(self, val, strmidx):
		Err(s2263mid.S2263_SetAspectRatio(c_int(val), self.devid, c_int(strmidx)))

	def GetAspectRatio(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetAspectRatio(byref(val), self.devid, c_int(strmidx)))
		return val.value


	def SetRecordMode(self, val, strmidx):
		Err(s2263mid.S2263_SetRecordMode(c_int(val), self.devid, c_int(strmidx)))

	def GetRecordMode(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetRecordMode(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetFrameSkip(self, val, strmidx):
		Err(s2263mid.S2263_SetFrameSkip(c_int(val), self.devid, c_int(strmidx)))

	def GetFrameSkip(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetFrameSkip(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetFrameCount(self, val, strmidx):
		Err(s2263mid.S2263_SetFrameCount(c_int(val), self.devid, c_int(strmidx)))

	def GetFrameCount(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetFrameCount(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetSliceMode(self, val, strmidx):
		Err(s2263mid.S2263_SetSliceMode(c_int(val), self.devid, c_int(strmidx)))

	def GetSliceMode(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetSliceMode(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetFlip(self, val, strmidx):
		Err(s2263mid.S2263_SetFlip(c_int(val), self.devid, c_int(strmidx)))

	def GetFlip(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetFlip(byref(val), self.devid, c_int(strmidx)))
		return val.value
		
	def SetJPEGQuality(self, val, strmidx):
		Err(s2263mid.S2263_SetJPEGQuality(c_int(val), self.devid, c_int(strmidx)))

	def GetJPEGQuality(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetJPEGQuality(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetH264Profile(self, val, strmidx):
		Err(s2263mid.S2263_SetH264Profile(c_int(val), self.devid, c_int(strmidx)))

	def GetH264Profile(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetH264Profile(byref(val), self.devid, c_int(strmidx)))
		return val.value

	def SetH264Level(self, val, strmidx):
		Err(s2263mid.S2263_SetH264Level(c_int(val), self.devid, c_int(strmidx)))

	def GetH264Level(self, strmidx):
		val = c_int(0)
		Err(s2263mid.S2263_GetH264Level(byref(val), self.devid, c_int(strmidx)))
		return val.value


	def GetVideoInfo(self):
		width = c_int(0)
		height = c_int(0)
		framerate = c_int(0)
		interlaced = c_int(0)
		ErrMsg("GetVideoInfo",s2263mid.S2263_GetVideoInfo(byref(width), byref(height), byref(framerate), 
			byref(interlaced), self.devid))
		return {'width':width.value,
			'height':height.value,
			'framerate':framerate.value,
			'interlaced':interlaced.value != 0}

	def GetVideoLock(self):
		lock = c_int(0)
		Err(s2263mid.S2263_GetVideoLock(byref(lock), self.devid))
		return lock.value != 0

	def GetAnalogHDStandard(self):
		standard = c_int(0)
		ErrMsg("GetAnalogHDStandard",s2263mid.S2263_GetAnalogHDStandard(byref(standard), self.devid))
		return standard.value

	def StartLog(self):
		Err(s2263mid.S2263_StartLog(self.devid))

	def FirmwareUpdate(self):
		Err(s2263mid.S2263_FirmwareUpdate(self.devid))

	def RegisterCallback(self, callback, strmidx):
		if callback:
			cb = CALLBACKTYPE(callback)
		else:
			cb = None
		Err(s2263mid.S2263_RegisterCallback(cb, self.devid, strmidx))
		return cb

	def StartCallback(self, strmidx):
		Err(s2263mid.S2263_StartCallback(self.devid, strmidx))

	def SetMP4FastStart(self, maxminutes, intervalseconds, strmidx):
		Err(s2263mid.S2263_SetMP4FastStart(c_int(maxminutes), c_int(intervalseconds), self.devid, c_int(strmidx)))

	def SetOutputMode(self, val):
		Err(s2263mid.S2263_SetOutputMode(c_int(val), self.devid))

	def GetOutputMode(self):
		val = c_int(0)
		Err(s2263mid.S2263_GetOutputMode(byref(val), self.devid))
		return val.value

	def SetOutputStd(self, val):
		Err(s2263mid.S2263_SetOutputStd(c_int(val), self.devid))

	def GetOutputStd(self):
		val = c_int(0)
		Err(s2263mid.S2263_GetOutputStd(byref(val), self.devid))
		return val.value

	def SetOutput(self, val):
		Err(s2263mid.S2263_SetOutput(c_int(val), self.devid))

	def GetOutput(self):
		val = c_int(0)
		Err(s2263mid.S2263_GetOutput(byref(val), self.devid))
		return val.value

	def SetGPO(self, val):
		Err(s2263mid.S2263_SetGPO(c_int(val), self.devid))

	def GetGPI(self):
		val = c_int(0)
		Err(s2263mid.S2263_GetGPI(byref(val), self.devid))
		return val.value

	def Snapshot(self, filename, strmidx):
		ErrMsg("snapshot",s2263mid.S2263_Snapshot(c_char_p(filename.encode('utf-8')), self.devid, c_int(strmidx)))


	def OverlayText(self, text, mode, x, y, strmidx):
		Err(s2263mid.S2263_OverlayText(c_char_p(text.encode('utf-8')), 
			c_int(mode), c_int(x), c_int(y), self.devid, c_int(strmidx)))
	def SetClock(self):
		Err(s2263mid.S2263_SetClock(c_void_p(0), self.devid))

	def ReadTempSensor(self):
		val = c_float(0)
		Err(s2263mid.S2263_ReadTempSensor(byref(val), self.devid))
		return val.value

	def SetTemperatureRobustness(self):
		Err(s2263mid.S2263_SetTemperatureRobustness(self.devid))

	def GetDeintMode(self):
		en = c_int(0)
		ch = c_int(0)
		thrlow = c_int(0)
		thrhigh = c_int(0)
		exclst = c_int(0)
		exclct = c_int(0)
		ErrMsg("GetDeintMode",s2263mid.S2263_GetDeintMode(byref(en), byref(ch), byref(thrlow), 
			byref(thrhigh), byref(exclst), byref(exclct), self.devid))
		return {'enable':en.value,
			'channel':ch.value,
			'threshold_low':thrlow.value,
			'threshold_high':thrhigh.value,
			'exclude_start':exclst.value,
			'exclude_count':exclct.value}
        
	def SetDeintMode(self, en, ch, thrlow, thrhigh, exclst, exclct):
		Err(s2263mid.S2263_SetDeintMode(c_int(en), c_int(ch),
			c_int(thrlow), c_int(thrhigh), c_int(exclst), c_int(exclct),
			self.devid))

	def Is3364(self):
		serial = c_int(0)
		rc = s2263mid.S3364_GetSerialNumberMfg(byref(serial), self.devid)
		if rc == 0:
			return 1
		return 0
	def Get3364BoardType(self):
		val = c_int(0)
		Err(s2263mid.S3364_GetBoardType(byref(val), self.devid))
		return val.value

	def Get3364UsbSpeed(self):
		val = c_int(0)
		s2263mid.S3364_GetUsbSpeed(byref(val), self.devid)
		return val.value

	def Get3364UsbSpeed(self):
		val = c_int(0)
		s2263mid.S3364_GetUsbSpeed(byref(val), self.devid)
		return val.value


	def Get3364UserData(self, data):
		Err(s2263mid.S3364_GetUserData(byref(data), self.devid))

	def Set3364UserData(self, data):
		val = Err(s2263mid.S3364_SetUserData(byref(data), self.devid))
		return val

	def Set3364VideoFormat(self, interlaced, width, height):
		#print interlaced, width, height
		val_rc = Err(s2263mid.S3364_SetVideoInterlaced(c_int(interlaced), self.devid))
		val_rc = Err(s2263mid.S3364_SetVideoSize(c_int(width), c_int(height), self.devid))

		return val_rc

	def Start3364FullSizePreview(self):
		Err(s2263mid.S3364_StartFullSizePreview(self.devid))

	def Stop3364FullSizePreview(self):
		Err(s2263mid.S3364_StopFullSizePreview(self.devid))

	def Set3364HDPreviewMode(self, val):
		Err(s2263mid.S3364_SetPreviewInterlaceMode(c_int(val), self.devid))

	def Get3364HDPreviewMode(self):
		val = c_int(0)
		Err(s2263mid.S3364_GetPreviewInterlaceMode(byref(val), self.devid))
		return val.value

