
/*------------------------------------------------------------------------------*/
/*    	File :  ICubeEventSample.cpp.c                                          */
/*  					              											*/
/*    	purpose of this this sample:
		show how events can be used with the Icube SDK
*/
/*------------------------------------------------------------------------------*/
/*  					              											*/
/*------------------------------------------------------------------------------*/

/********************************************************************************/

#include "stdafx.h"
#include "NET_ICube_API.h"
#include  <conio.h>

//---------------------------------------------------------------------------
// DEFINES

#define MAX_CAM_NUM	16

// start with software trigger mode
//#define MODE_SW_TRIGGER		

// TRIGGER_TIMEOUT value has to be choosen with with care
// at least, it has to be bigger than the current expsoure time + 
// frame transfer time
// default value is 20000 msec

#define TRIGGER_TIMEOUT_VALUE 2000	// [msec]

//#define CHANGE_PIPE_TIMEOUT_MODE
//---------------------------------------------------------------------------
// GLOBALS

int nGoodFramesCnt[MAX_CAM_NUM]={0};	// statistics
int nBadFramesCnt[MAX_CAM_NUM]={0};		// statistics


#ifdef MODE_SW_TRIGGER
HANDLE  m_hndEvent[MAX_CAM_NUM]={NULL};
#endif
//---------------------------------------------------------------------------
// PROTOTYPES

void PrintError(char* text,int stat,int nInd);

//---------------------------------------------------------------------
//
// callback which is used for grabbing RAW or RGB24 data from camera.
// (this callback retrieve an also event)
//
long CALLBACK MyCallbackFuncEx(int event_type,BYTE * pBuffer, long lBufferSize,PVOID pContext )
{
	int nCamInd = reinterpret_cast<int>(pContext);	// retrieve camera index (set as callback context parameter)

	switch(event_type)
	{
	case EVENT_NEW_FRAME:

		if (lBufferSize == 0)
			nBadFramesCnt[nCamInd]++;	// a bad frame arrived
		else
			nGoodFramesCnt[nCamInd]++;	// a good frame arrived

		printf("\nCam[%d] Image Ev cb;  GoodFr: %d ,BadFr: %d , Size %d  ",nCamInd,nGoodFramesCnt[nCamInd],nBadFramesCnt[nCamInd],lBufferSize);  
		
		#ifdef MODE_SW_TRIGGER
		SetEvent(m_hndEvent[nCamInd]);	// signal that a frame is arrived
		#endif
		break;
	case EVENT_DEV_DISCONNECTED:
		// lBufferSize returns the disconnection counter value
		printf("\nCam[%d] EVENT_DEV_DISCONNECTED  %d",nCamInd,lBufferSize);  
		break;
	case EVENT_DEV_RECONNECTED:
		// lBufferSize returns the reconnection counter value
		printf("\nCam[%d] EVENT_DEV_RECONNECTED   %d ",nCamInd,lBufferSize);  
		break;
	case EVENT_USB_TRANSFER_FAILED:
		// lBufferSize returns the transfer failed counter value
		printf("\nCam[%d] EVENT_USB_TRANSFER_FAILED  %d ",nCamInd,lBufferSize);  
		break;
	default:
		// just in case
		printf("\nCam[%d] EVENT_UNKNOWN  %d ",nCamInd,event_type);  
		break;
	}

return 42;
}
//---------------------------------------------------------------------
//
// callback which is used for grabbing RAW or RGB24 data from camera.
// (standard callback without events)
//
long CALLBACK MyCallbackFunc(BYTE * pBuffer, long lBufferSize,PVOID pContext )
{
	int nCamInd = reinterpret_cast<int>(pContext);	// retrieve camera index (set as callback context parameter)

	if (lBufferSize == 0)
		nBadFramesCnt[nCamInd]++;	// a bad frame arrived
	else
		nGoodFramesCnt[nCamInd]++;	// a good frame arrived

	printf("\nCam[%d] Image cb;  GoodFr: %d ,BadFr: %d , Size %d  ",nCamInd,nGoodFramesCnt[nCamInd],nBadFramesCnt[nCamInd],lBufferSize);  
	
	#ifdef MODE_SW_TRIGGER
	SetEvent(m_hndEvent[nCamInd]);	// signal that a frame is arrived
	#endif

return 42;
}
//---------------------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
	int stat = 0;

	printf("ICube Event sample (version 1.0.0.0) \n");

	#ifndef LIBFILE
	if ( LoadICubeApi("ICubeSDK.dll") != IC_SUCCESS ){ // link with 32bit dll
		printf("Can not find ICubeSDK.dll \n");
		return 0;
	}
	#endif	

	int numDevices=ICubeSDK_Init ();
	if(numDevices<1){
		printf("No Devices! \n");
		return 0;
	}

	// open ICube interface for all detected devices
	for(int nCamIdx=0;nCamIdx < numDevices;nCamIdx++)
	{
		#ifdef MODE_SW_TRIGGER
		m_hndEvent[nCamIdx] = CreateEvent(NULL, TRUE, FALSE, NULL);
		if(m_hndEvent==NULL){ 
			printf("Error: CreateEvent \n");
			return 0;
		}
		#endif

		stat = ICubeSDK_Open(nCamIdx);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_Open",stat,nCamIdx);
			return 0;
		}

		// check camera name
		char CamName[NETCAM_NAME_LENGTH];
		stat = ICubeSDK_GetName(nCamIdx, CamName);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_GetName",stat,nCamIdx);
			return 0;
		}
		printf("Camera[%d]  model: %s \n",nCamIdx,CamName);
	
		// register callback function 

		int * context = (int*)(nCamIdx);  // set camera index as context parameter for callback

		if(ICubeSDK_SetCallbackEx!= NULL)	
			stat = ICubeSDK_SetCallbackEx(nCamIdx,CALLBACK_RGB,MyCallbackFuncEx,context);
		else{
			printf("This ICubeSDK.dll does not support a event callback \n");
			stat = ICubeSDK_SetCallback(nCamIdx,CALLBACK_RGB,MyCallbackFunc,context);
		}
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_SetCallback",stat,nCamIdx);
			return 0;
		}
		// at this point you can see EVENT_DEV_DISCONNECTED, EVENT_DEV_RECONNECTED events
	}
	system("PAUSE");	
	printf("\nstart aquisition... \n");

	for(int nCamIdx=0;nCamIdx < numDevices;nCamIdx++)
	{
	#ifdef MODE_SW_TRIGGER
		// this lets TRIG_SW_DO return immediatley, if not set TRIG_SW_DO returns on the
		// beginning of frame transfer (useless for superspeed cameras)
		stat = ICubeSDK_SetCamParameter(nCamIdx,REG_SW_TRIG_MODE,IMMEDIATE_TRIGGER_RETURN );
		if(stat != IC_SUCCESS ){
			PrintError("NETUSBCAM_SetCamParameter: REG_SW_TRIG_MODE",stat,nCamIdx);
		}
	#endif

		// badframes can be detected through the callback
		stat = ICubeSDK_SetCamParameter(nCamIdx,REG_CALLBACK_BR_FRAMES,1);
		if(stat != IC_SUCCESS ){
			PrintError("NETUSBCAM_SetCamParameter: REG_CALLBACK_BR_FRAMES",stat,nCamIdx);
		}

	#ifdef CHANGE_PIPE_TIMEOUT_MODE
		stat = ICubeSDK_SetCamParameter(nCamIdx,REG_PIPE_TIMEOUT_MODE,MODE_TIMEOUT_ALL);
		if(stat != IC_SUCCESS ){
			PrintError("NETUSBCAM_SetCamParameter: REG_PIPE_TIMEOUT_MODE",stat,nCamIdx);
		}
	#endif

	#ifdef MODE_SW_TRIGGER

		stat = ICubeSDK_SetCamParameter(nCamIdx,REG_TRIG_TIMEOUT,TRIGGER_TIMEOUT_VALUE);
		if(stat != IC_SUCCESS ){
			PrintError("NETUSBCAM_SetCamParameter: REG_TRIG_TIMEOUT",stat,nCamIdx);
		}

		stat=ICubeSDK_SetTrigger(nCamIdx,TRIG_SW_START);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_SetTrigger: TRIG_SW_START",stat,nCamIdx);
			return 0;
		}
		#endif

		// start frame transfer without preview
		stat = ICubeSDK_Start(nCamIdx,NULL,false,true);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_Start",stat,nCamIdx);
			return 0;
		}
	}
#ifdef MODE_SW_TRIGGER
	
	while(1)	// trigger in a loop unless stopped by user
	{
		for(int nCamIdx=0;nCamIdx < numDevices;nCamIdx++)
		{
			stat = ICubeSDK_SetTrigger(nCamIdx,TRIG_SW_DO);
			if(stat != IC_SUCCESS )
				PrintError("TRIG_SW_DO ",stat,nCamIdx);
		
			// wait for frame (signaled from callback function)
			if (WaitForSingleObject(m_hndEvent[nCamIdx], TRIGGER_TIMEOUT_VALUE) != WAIT_TIMEOUT){
 				ResetEvent(m_hndEvent[nCamIdx]);	
			}
			else	
				printf("\nTimeout waiting for frame! \n"); 
		}
		if(_kbhit())	// stopped by any key
			break;
	}
#else 
	system("PAUSE");	 
#endif

	for(int nCamIdx=0;nCamIdx < numDevices;nCamIdx++)
	{
		stat = ICubeSDK_Stop(nCamIdx);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_Stop ",stat,nCamIdx);
		}
		
		#ifdef MODE_SW_TRIGGER
		stat = ICubeSDK_SetTrigger(nCamIdx,TRIG_STOP);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_SetTrigger: TRIG_STOP ",stat,nCamIdx);
			return 0;
		}
		#endif
		
		stat = ICubeSDK_Close(nCamIdx);
		if(stat != IC_SUCCESS ){
			PrintError("ICubeSDK_Close ",stat,nCamIdx);
		}

		#ifdef MODE_SW_TRIGGER
		CloseHandle(m_hndEvent[nCamIdx]);	
		#endif
	}

	#ifndef LIBFILE
	UnloadICubeApi();
	#endif

	return 0;
}
//---------------------------------------------------------------------

void PrintError(char* text,int stat,int nInd)
{
	switch(stat){
		 
		case IC_IF_NOT_OPEN:
			printf("Cam[%d] Error: %s (%d), interface not open or camera not present\n",nInd,text,stat);
			break;
		case IC_WRONG_PARAM:
			printf("Cam[%d] Error: %s (%d), invalid parameter\n",nInd,text,stat);
			break;
		case IC_OUT_OF_MEMORY:
			printf("Cam[%d] Error: %s (%d), out of memory\n",nInd,text,stat);
			break;
		case IC_ALREADY_DONE:
			printf("Cam[%d] Error: %s (%d), ICubeSDK_Open,ICubeSDK_Start,... called again without closing\n",nInd,text,stat);
			break;
		case IC_WRONG_CLOCK_VAL:
			printf("Cam[%d] Error: %s (%d), invalid clock value for this mode\n",nInd,text,stat);
			break;
		case IC_COM_LIB_INIT:
			printf("Cam[%d] Error: %s (%d), dll initialisation\n",nInd,text,stat);
			break;
		case IC_NOT_IF_STARTED:
			printf("Cam[%d] Error: %s (%d), dll preview initialisation\n",nInd,text,stat);
			break;
		case IC_WRONG_ROI_ID: 
			printf("Cam[%d] Error: %s (%d), invalid roi id\n",nInd,text,stat);
			break;
		case IC_IF_NOT_ENABLED:
			printf("Cam[%d] Error: %s (%d), feature is not enabled\n",nInd,text,stat);
			break;
		case IC_COLOR_CAM_ONLY:
			printf("Cam[%d] Error: %s (%d), feature is not supported by color cameras\n",nInd,text,stat);
			break;
		case IC_DRIVER_VERSION:
			printf("Cam[%d] Error: %s (%d), usb driver version mismatch\n",nInd,text,stat);
			break;
		case IC_D3D_INIT:
			printf("Cam[%d] Error: %s (%d), d3d initialisation\n",nInd,text,stat);
			break;
		case IC_BAD_POINTER:
			printf("Cam[%d] Error: %s (%d), bad pointer\n",nInd,text,stat);
			break;
		case IC_ERROR_FILE_SIZE:
			printf("Cam[%d] Error: %s (%d), invalid file size\n",nInd,text,stat);
			break;
		case IC_RECONNECTION_ACTIVE:
			printf("Cam[%d] Error: %s (%d), usb reconnection is active\n",nInd,text,stat);
			break;
		case IC_USB_REQUEST_FAIL:
			printf("Cam[%d] Error: %s (%d), usb request failed\n",nInd,text,stat);
			break;
		case IC_RESOURCE_IN_USE:
			printf("Cam[%d] Error: %s (%d), resource in use by another proccess\n",nInd,text,stat);
			break;
		case IC_DEVICE_GONE:  
			printf("Cam[%d] Error: %s (%d), device is gone\n",nInd,text,stat);
			break;
		case IC_DLL_MISMATCH:
			printf("Cam[%d] Error: %s (%d), dll version mismatch\n",nInd,text,stat);
			break;
		case IC_WRONG_FW_VERSION:
			printf("Cam[%d] Error: %s (%d), feature is not supported by this firmware\n",nInd,text,stat);
			break;
		case IC_NO_RGB_CALLBACK:	
			printf("Cam[%d] Error: %s (%d), feature is not without rgb callback\n",nInd,text,stat);
			break;
		case IC_NO_USB30_CAMERA:	
			printf("Cam[%d] Error: %s (%d), feature is not supported by usb2.0 cameras\n",nInd,text,stat);
			break;
		case IC_ERR_FIX_RELATION:	
			printf("Cam[%d] Error: %s (%d), serial number of fix registered device does not match\n",nInd,text,stat);
			break;
		case IC_CRC_CONFIG_DATA:	
			printf("Cam[%d] Error: %s (%d), crc of configuration data is corrupt\n",nInd,text,stat);
			break;
		case IC_CONFIG_DATA:	
			printf("Cam[%d] Error: %s (%d), configuration data is corrupt\n",nInd,text,stat);
			break;
		default:
			printf("Cam[%d] Error: %s (%d), unspecified error\n",nInd,text,stat);
			break;
	}
}
//---------------------------------------------------------------------
//EOF

