Преглед на файлове

#IQRV #comment [ScannerSet]高拍仪同步Windows

gifur преди 3 години
родител
ревизия
0d0e3ef9d3

+ 119 - 109
Module/mod_ScannerSet/CameraImpl.cpp

@@ -22,15 +22,18 @@ static int Bin2Str(unsigned char *x, int xlen, char *str, int str_size)
 
 int GetCameraInfors(CAMERA_BUCKET& vtCameraList)
 {
+	LOG_FUNCTION();
+
 	DestoryCamereBuckets(vtCameraList);
-	ICreateDevEnum *pDevEnum = NULL;
-	IEnumMoniker *pEnum = NULL;
+
+	SmartPtr<ICreateDevEnum> pDevEnum = NULL;
 	int deviceCounter = 0;
 	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
 		CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
 		reinterpret_cast<void**>(&pDevEnum));
 	if (SUCCEEDED(hr)) {
 		// Create an enumerator for the video capture category.
+		IEnumMoniker *pEnum = NULL;
 		hr = pDevEnum->CreateClassEnumerator(
 			CLSID_VideoInputDeviceCategory,
 			&pEnum, 0);
@@ -41,82 +44,80 @@ int GetCameraInfors(CAMERA_BUCKET& vtCameraList)
 				IPropertyBag *pPropBag;
 				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
 				if (FAILED(hr)) {
-
-					pMoniker->Release();
+					SAFE_RELEASE_IDEV(pPropBag);
+					SAFE_RELEASE_IDEV(pMoniker);
 					continue;  // Skip this one, maybe the next one will work.
 				}
 				PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
 				if(item != NULL) {
 					item->Cleanup();
 					// Find the description or friendly name.
+					
 					VARIANT varName;
 					VariantInit(&varName);
-					hr = pPropBag->Read(L"Description", &varName, 0);
-					if (FAILED(hr)) {
-						hr = pPropBag->Read(L"FriendlyName", &varName, 0);
-					}
+					hr = pPropBag->Read(L"FriendlyName", &varName, 0);
 					if (SUCCEEDED(hr)) {
-
-						hr = pPropBag->Read(L"FriendlyName", &varName, 0);
 						int maxLen = sizeof(item->szDevName) - 2;
 						int nLen = WrapW2A(varName, &(item->szDevName[0]), maxLen);
-						VariantClear(&varName);
 					}
+					VariantClear(&varName);
+					
 					VARIANT varCLSID;
 					VariantInit(&varCLSID);
 					hr = pPropBag->Read(L"CLSID", &varCLSID, 0);
 					if (SUCCEEDED(hr)) {
 						int maxLen = sizeof(item->szCLSID) - 2;
 						int nLen = WrapW2A(varCLSID, &(item->szCLSID[0]), maxLen);
-						VariantClear(&varCLSID);
 					}
+					VariantClear(&varCLSID);
+
 					VARIANT varDevPath;
 					VariantInit(&varDevPath);
 					hr = pPropBag->Read(L"DevicePath", &varDevPath, 0);
 					if (SUCCEEDED(hr)) {
 						int maxLen = sizeof(item->szDevPath) - 2;
 						int nLen = WrapW2A(varDevPath, &(item->szDevPath[0]), maxLen);
-						VariantClear(&varDevPath);
 					}
+					VariantClear(&varDevPath);
+
 					VARIANT varWaveID;
 					VariantInit(&varWaveID);
 					hr = pPropBag->Read(L"WaveInID", &varWaveID, 0);
 					if (SUCCEEDED(hr)) {
 						item->uWaveInID = varWaveID.lVal;
-						VariantClear(&varWaveID);
 					}
+					VariantClear(&varWaveID);
+
 					vtCameraList.push_back(item);
 				}
-				pPropBag->Release();
-				pPropBag = NULL;
-
-				pMoniker->Release();
-				pMoniker = NULL;
+				SAFE_RELEASE_IDEV(pPropBag);
+				SAFE_RELEASE_IDEV(pMoniker);
 
 				deviceCounter++;
 			}
-			pDevEnum->Release();
-			pDevEnum = NULL;
 
-			pEnum->Release();
-			pEnum = NULL;
+
+			SAFE_RELEASE_IDEV(pMoniker);
 		}
+
+		SAFE_RELEASE_IDEV(pEnum);
 	}
 	else {
-		Dbg("CoCreateInstance failed, hr=%u", hr); 
+		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CoCreateInstance failed, hr=%d(0x%x)", hr, hr); 
 	}
+
 	return deviceCounter;
 }
 
 int GetCameraCount()
 {
 	ICreateDevEnum *pDevEnum = NULL;
-	IEnumMoniker *pEnum = NULL;
 	int deviceCounter = 0;
 	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
 		CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
 		reinterpret_cast<void**>(&pDevEnum));
 	if (SUCCEEDED(hr)) {
+		IEnumMoniker *pEnum = NULL;
 		hr = pDevEnum->CreateClassEnumerator(
 			CLSID_VideoInputDeviceCategory,
 			&pEnum, 0);
@@ -126,24 +127,22 @@ int GetCameraCount()
 				IPropertyBag *pPropBag;
 				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
 					(void**)(&pPropBag));
+
+				SAFE_RELEASE_IDEV(pPropBag);
+				SAFE_RELEASE_IDEV(pMoniker);
+
 				if (FAILED(hr)){
-					pMoniker->Release();
 					continue;  // Skip this one, maybe the next one will work.
 				}
-				pPropBag->Release();
-				pPropBag = NULL;
-
-				pMoniker->Release();
-				pMoniker = NULL;
-
 				deviceCounter++;
 			}
-			pEnum->Release();
-			pEnum = NULL;
 		}
-		pDevEnum->Release();
-		pDevEnum = NULL;
+
+		SAFE_RELEASE_IDEV(pEnum);
 	}
+
+	SAFE_RELEASE_IDEV(pDevEnum);
+
 	return deviceCounter;
 }
 
@@ -151,63 +150,59 @@ int GetCameraCount()
 int IsDeviceBusy(const char* lpcszDeviceName)
 {
 	LOG_FUNCTION();
+	return 0;
+
 	int nRet = -2;
 	ICreateDevEnum *pDevEnum = NULL;
 	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
 		CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum);
+
 	IEnumMoniker *pEnum = NULL;
 	hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
+	
 	if (SUCCEEDED(hr)) {
 		// Create an enumerator for the video capture category.
 		IMoniker *pMoniker = NULL;
 		nRet = -1;
 		while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+
 			IPropertyBag *pPropBag = NULL;
 			hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
-			if (FAILED(hr)) {
-				SAFE_RELEASE_IDEV(pPropBag);
-				SAFE_RELEASE_IDEV(pMoniker);
-				continue;  // Skip this one, maybe the next one will work.
-			}
-			VARIANT varName;
-			VariantInit(&varName);
-			hr = pPropBag->Read(L"Description", &varName, 0);
-			if (FAILED(hr)) {
-				hr = pPropBag->Read(L"FriendlyName", &varName, 0);
-			}
-			if (SUCCEEDED(hr)) {
+			if(SUCCEEDED(hr)) {
+
+				VARIANT varName;
+				varName.vt = VT_BSTR;
+
 				hr = pPropBag->Read(L"FriendlyName", &varName, 0);
-				int count = 0;
-				char tmp[255] = {0};
-				while (varName.bstrVal[count] != 0x00 && count < 255) {
-					tmp[count] = (char)varName.bstrVal[count];
-					count++;
-				}
-				if(SUCCEEDED(hr)) {
+				if (SUCCEEDED(hr)) {
+					int count = 0;
+					char tmp[256] = {0};
+					WrapW2A(varName, tmp, 255);
+					SysFreeString(varName.bstrVal);
+
 					if(!strcmp(lpcszDeviceName, tmp)) {
 						//Deal the specific device
 						nRet = 0;
 						LPBC* pbc = NULL;
-						IBaseFilter *P_VCamTrans = NULL;
-						IBaseFilter *pCap = NULL;
 						CreateBindCtx(0, pbc);
-						hr = pMoniker->BindToObject((IBindCtx *)pbc, 0, IID_IBaseFilter,(void **)&pCap); 
+
+						SmartPtr<IBaseFilter> pCap = NULL;
+						hr = pMoniker->BindToObject((IBindCtx*)pbc, 0, IID_IBaseFilter,(void **)&pCap); 
 
 						IGraphBuilder *m_pGB = NULL;   
-						IMediaControl *m_pMC = NULL;   
-						IVideoWindow   *m_pVW = NULL;
-						IMediaEventEx *m_pME = NULL;
 						hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
 							CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
+
 						if (FAILED(hr)) {
 							nRet = -2;
 							SAFE_RELEASE_IDEV(m_pGB);
-							SAFE_RELEASE_IDEV(pCap);
 							SAFE_RELEASE_IDEV(pPropBag);
 							SAFE_RELEASE_IDEV(pMoniker);
 							goto PEnd;  
 						}
+
 						m_pGB->AddFilter(pCap, NULL);
+
 						ICaptureGraphBuilder2 *m_pCapGB = NULL;
 						hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
 							CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);  
@@ -215,29 +210,60 @@ int IsDeviceBusy(const char* lpcszDeviceName)
 							nRet = -2;
 							SAFE_RELEASE_IDEV(m_pCapGB);
 							SAFE_RELEASE_IDEV(m_pGB);
-							SAFE_RELEASE_IDEV(pCap);
 							SAFE_RELEASE_IDEV(pPropBag);
 							SAFE_RELEASE_IDEV(pMoniker);
 							goto PEnd;  
-						}  
+						}
+
 						m_pCapGB->SetFiltergraph(m_pGB);
+
 						IAMCrossbar *pXBar1 = NULL;
 						hr = m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pCap, 
 							IID_IAMCrossbar,(void **)&pXBar1);
+
 						if (SUCCEEDED(hr)) {
+
 							long OutputPinCount;
 							long InputPinCount;
-							//long PinIndexRelated;
-							//long PhysicalType;
+							long PinIndexRelated;
+							long PhysicalType;
 							long inPort = 0;
 							long outPort = 0;
 
 							pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
 							int videoBusy = 1;
 							for (int i=0; i<InputPinCount; i++) {
+
+								pXBar1->get_CrossbarPinInfo(TRUE, i, &PinIndexRelated, &PhysicalType);
+								if(PhysConn_Video_Composite == PhysicalType) {
+									inPort = i;
+									break;
+								}
+							}
+							for (int j=0; j<OutputPinCount; j++) {
+
+								pXBar1->get_CrossbarPinInfo(FALSE, j, &PinIndexRelated, &PhysicalType);
+								if(PhysConn_Video_Composite == PhysicalType) {
+									outPort = j;
+									break;
+								}
+	
+							}
+
+							for (int i=0; i<InputPinCount; i++) {
+
 								for (int j=0; j<OutputPinCount; j++) {
-									if(S_OK == pXBar1->CanRoute(j, i)) {
+
+									hr = pXBar1->CanRoute(j, i);
+
+									if(S_OK == hr) {
+
 										pXBar1->Route(j,i);
+
+										IMediaControl *m_pMC = NULL;   
+										IVideoWindow   *m_pVW = NULL;
+										IBaseFilter *P_VCamTrans = NULL;
+
 										m_pGB->AddFilter(pCap, L"Capture Filter");
 										hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
 										hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
@@ -246,32 +272,39 @@ int IsDeviceBusy(const char* lpcszDeviceName)
 										hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
 										hr = m_pVW->put_Visible(OAFALSE);   
 										hr = m_pVW->put_AutoShow(OAFALSE);
+
 										HRESULT innhr = m_pMC->StopWhenReady();
-										if (SUCCEEDED(innhr))
-										{
+										if (SUCCEEDED(innhr)){
 											videoBusy = 0;
-										}
-										else {
-											Dbg("It works ? %d, %d", i, j);
+										} else {
+											LogWarn(Severity_Low, Error_DevCommFailed, DETECT_CAMERA_BUSY_ONE,
+												CSimpleStringA::Format("%s stop failed: 0x%08X", lpcszDeviceName, innhr));
 										}
 										SAFE_RELEASE_IDEV(m_pVW);
 										SAFE_RELEASE_IDEV(m_pMC);
 										SAFE_RELEASE_IDEV(P_VCamTrans);
 									}
+									else {
+										DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CanRoute failed: 0x%08X", hr);
+									}
+
 								}
 							}
+
 							if (videoBusy == 1)
 							{
-								Dbg("Test 1");
 								nRet = 1; //视频设备占用
 							}
 							SAFE_RELEASE_IDEV(pXBar1);
 						}
 						else //pXBar1
 						{
+							IMediaControl *m_pMC = NULL;   
+							IVideoWindow   *m_pVW = NULL;
+							IBaseFilter *P_VCamTrans = NULL;
+
 							m_pGB->AddFilter(pCap, L"Capture Filter");
 							m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
-							hr = m_pGB->QueryInterface(IID_IMediaEventEx, (void**)&m_pME);
 							hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
 							hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
 
@@ -283,65 +316,43 @@ int IsDeviceBusy(const char* lpcszDeviceName)
 							HRESULT innhr = m_pMC->StopWhenReady();
 							if (FAILED(innhr))
 							{
-								Dbg("Test 2");
+								LogWarn(Severity_Low, Error_DevCommFailed, DETECT_CAMERA_BUSY_TWO,
+									CSimpleStringA::Format("%s stop failed: 0x%08X", lpcszDeviceName, innhr));
 								nRet = 1;  //视频设备占用
 							}
 							SAFE_RELEASE_IDEV(m_pVW);
 							SAFE_RELEASE_IDEV(m_pMC);
 							SAFE_RELEASE_IDEV(P_VCamTrans);
 						}
+
+						SAFE_RELEASE_IDEV(pXBar1);
 						SAFE_RELEASE_IDEV(m_pCapGB);
 						SAFE_RELEASE_IDEV(m_pGB);
-						SAFE_RELEASE_IDEV(pCap);
+
 						break;
 					}
 				}
+				VariantClear(&varName);
+
 			}
+
 			SAFE_RELEASE_IDEV(pPropBag);
 			SAFE_RELEASE_IDEV(pMoniker);
 		}
+		SAFE_RELEASE_IDEV(pMoniker);
 	}
 
 PEnd:
-	SAFE_RELEASE_IDEV(pDevEnum);
+
 	SAFE_RELEASE_IDEV(pEnum);
-	Dbg("IsDeviceBusy(%s) returned %d", lpcszDeviceName, nRet);
+	SAFE_RELEASE_IDEV(pDevEnum);
+	
 	if(nRet != 1) {
 		nRet = 0;
 	}
 	return nRet;
 }
 
-
-//int GetVideoDeviceID(LPCTSTR lpDevCombinedName)
-//{
-//		int i, n;
-//		n = videocap_get_device_count();
-//		for (i = 0; i < n; ++i) {
-//			WCHAR tmp[256];
-//			char t[256];
-//			WCHAR tmp1[256];
-//			char t1[256];
-//			videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
-//			WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
-//			videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
-//			WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
-//			{
-//				unsigned char x[MD5_DIGESTSIZE];
-//				md5_ctx_t ctx;
-//				md5_init(&ctx);
-//				md5(x, t1, strlen(t1));
-//				Bin2Str(x, sizeof(x), t1, sizeof(t1));
-//			}
-//			strcat(t, ";");
-//			strcat(t, t1);
-//			if (strcmp(lpDevCombinedName, t) == 0) {
-//				return i;
-//			}
-//		}
-//		return -1;
-//}
-
 int UpdateCameraInfors(CAMERA_BUCKET& vtCameraList)
 {
 	LOG_FUNCTION();
@@ -397,7 +408,6 @@ int ExclusiveCameraBuckes(const CAMERA_BUCKET& lhs, const CAMERA_BUCKET& rhs, CA
 
 void DisplayCameraInfos(const CAMERA_BUCKET& vtCameraList)
 {
-	Dbg("Cameralist:(%d)", vtCameraList.size());
 	for(CAMERA_BUCKET_CITER it=vtCameraList.cbegin(); it!=vtCameraList.cend(); ++it) {
 		if(*it) {
 			(*it)->Display();

+ 18 - 5
Module/mod_ScannerSet/CameraImpl.h

@@ -8,6 +8,8 @@
 #include <vector>
 #include <algorithm>
 
+#define DETECT_CAMERA_BUSY_ONE 0x21800001
+#define DETECT_CAMERA_BUSY_TWO 0x21800002
 #define SAFE_RELEASE_IDEV(hd)	\
 	do {	\
 	if(hd != NULL) {	\
@@ -37,18 +39,29 @@ typedef struct _CAMERA_INFOR_ITEM
 		}
 	}
 	void Display() {
-		Dbg("[%ld]%s(%s)",uWaveInID, szDevName, szDevPath);
-		Dbg("CLSID:%s", szCLSID);
+		DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("[%ld]%s(%s)",uWaveInID, szDevName, szDevPath);
+		DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("CLSID:%s", szCLSID);
 	}
 
 } CAMERA_INFOR_ITEM, *PCAMERA_INFOR_ITEM;
 
 static int WrapW2A(VARIANT& varirant, char* szDst, const size_t maxLen) {
+
 	int count = 0;
-	while (varirant.bstrVal[count] != 0x00 && count < maxLen) {
-		szDst[count] = (char)varirant.bstrVal[count];
-		count++;
+	WCHAR tmp[256];
+	tmp[0] = 0;
+	memset(szDst, '\0', sizeof(char)*maxLen);
+	HRESULT hr = StringCchCopyW(tmp, 256, varirant.bstrVal);
+	if(hr == S_OK) {
+		count = WideCharToMultiByte(CP_ACP, 0, tmp, -1, szDst, maxLen, 0, NULL);
+	} else {
+		while (varirant.bstrVal[count] != 0x00 && count < maxLen) {
+			szDst[count] = (char)varirant.bstrVal[count];
+			count++;
+		}
 	}
+
+
 	return count;
 	/*
 	USES_CONVERSION;

+ 403 - 0
Module/mod_ScannerSet/CameraOccupySysVar.hpp

@@ -0,0 +1,403 @@
+ /***********************************//**
+ * @file CameraOccupySysVar.hpp
+ * @author Gifur
+ * @email guifaliao@gmail.com
+ * @version 1.0.0.0
+ * @date 2021-06-21
+ * @copyright China Merchants Bank Co.,Ltd All rights reserved
+ *
+ * @brief 
+ * @details 
+ **************************************/
+
+#include "SpBase.h"
+
+#define CMAERA_OCCUPY_SPLIT_MASK '$'
+#define CMAERA_OCCUPY_SPLIT_MASK_STR "$"
+
+struct OccpyCameraStruct 
+{
+	CSimpleStringA strCameraName;
+	CSimpleStringA strOccupier;
+
+	OccpyCameraStruct():strCameraName(true),strOccupier(true) {
+	}
+
+	OccpyCameraStruct(const char* camera, const char* occpuier)
+		:strCameraName(camera),strOccupier(occpuier) {
+	}
+
+	OccpyCameraStruct(const OccpyCameraStruct& rhs)
+		:strCameraName(rhs.strCameraName),strOccupier(rhs.strOccupier) {
+	}
+
+	OccpyCameraStruct(const char* value):strCameraName(true),strOccupier(true) {
+		CSimpleStringA strValue(value);
+		if(!strValue.IsNullOrEmpty()) {
+			FromSysVarString(strValue);
+		}
+	}
+
+	bool operator==(const OccpyCameraStruct& rhs)
+	{
+		return (strCameraName == rhs.strCameraName && strOccupier == rhs.strOccupier);
+	}
+
+	bool Match(const OccpyCameraStruct& rhs) {
+		if(strCameraName == rhs.strCameraName && strOccupier == rhs.strOccupier)
+			return true;
+		if(rhs.strCameraName.Compare("*") == 0 && rhs.strOccupier.Compare("*") == 0)
+			return true;
+		if(rhs.strCameraName.Compare("*") == 0 && strOccupier == rhs.strOccupier)
+			return true;
+		if(rhs.strOccupier.Compare("*") == 0 && strCameraName == rhs.strCameraName)
+			return true;
+
+		return false;
+	}
+
+	bool IsValid() {
+		return (!strCameraName.IsNullOrEmpty() && !strOccupier.IsNullOrEmpty());
+	}
+
+	bool IsValid() const {
+		return (!strCameraName.IsNullOrEmpty() && !strOccupier.IsNullOrEmpty());
+	}
+
+	CSimpleStringA toSysVarString() const {
+		CSimpleStringA result(strCameraName);
+		result.Append("=");
+		result.Append(strOccupier);
+		return result;
+	}
+
+	bool FromSysVarString(CSimpleStringA& value) {
+		CAutoArray<CSimpleStringA> infos = value.Split('=');
+		if(infos.GetCount() != 2) {return false;}
+		strCameraName = infos[0];
+		strOccupier = infos[1];
+		return true;
+	}
+};
+
+ /*!
+ * @brief 实时获取当前被占用的摄像头的名称和对应的实体
+ * @param[in]  pFunc 框架接口,inFilter 过滤器,通过实体名称或者摄像头名称对要获取的内容进行过滤
+ * @param[out] outOccupiedCamres 数组类型
+ * @return : 
+ */
+static inline ErrorCodeEnum GetOccupiedCameres(CAutoArray<OccpyCameraStruct>& outOccupiedCamres,
+	CSmartPointer<IEntityFunction> pFunc,
+	const OccpyCameraStruct* inFilter = NULL)
+{
+	CSimpleStringA devicList;
+	ErrorCodeEnum result = pFunc->GetSysVar("CameraOccupyingStatus", devicList);
+
+	outOccupiedCamres.Clear();
+
+	if(result == Error_Succeed && !devicList.IsNullOrEmpty()) {
+		CSimpleStringA newValue;
+		bool needToReplace = false;
+		CAutoArray<CSimpleStringA> devItems = devicList.Split(CMAERA_OCCUPY_SPLIT_MASK);
+		if(devItems.GetCount() > 0) {
+			int counts = devItems.GetCount();
+			if(inFilter != NULL) {
+				counts = 0;
+				for(int i=0; i<devItems.GetCount(); ++i) {
+					OccpyCameraStruct item(devItems[i]);
+					if(item.Match(*inFilter)) {
+						counts++;
+					}
+				}
+			}
+
+			if(counts > 0) {
+				outOccupiedCamres.Init(counts);
+				int j=0;
+				for(int i=0; i<devItems.GetCount(); ++i) {
+					/*{deviceName1}={EntityName1}${deviceName2}={EntityName2}*/
+					OccpyCameraStruct item(devItems[i]);
+					if(inFilter == NULL || item.Match(*inFilter)) {
+						outOccupiedCamres[j++] = item;
+					}
+				}
+			}
+		}
+	}
+
+	return result;
+}
+
+ /*!
+ * @brief 添加到指定摄像头信息到系统变量
+ * @param[in]  newItem,新插入的摄像头名称和实体名称,见 OccpyCameraStruct
+ * @return : 
+ * 如果摄像头和所占用的实体名称完全吻合,返回 Error_AlreadyExist
+ * 如果摄像头已在但实体名称是其他实体,则返回 Error_Duplication
+ * 成功添加返回 Error_Succeed
+ */
+static inline ErrorCodeEnum AppendOccpuiedCamera(
+	const OccpyCameraStruct& newItem, CSmartPointer<IEntityFunction> pFunc)
+{
+	CAutoArray<OccpyCameraStruct> existedList;
+	ErrorCodeEnum result = GetOccupiedCameres(existedList, pFunc);
+	CSimpleStringA newValue;
+	if(existedList.GetCount() > 0) {
+		for (int i=0; i<existedList.GetCount(); ++i)
+		{
+			OccpyCameraStruct& item = existedList[i];
+			if(item == newItem) {
+				result = Error_AlreadyExist;
+				break;
+			} else if(newItem.strCameraName == item.strCameraName) {
+				result = Error_Duplication;
+				break;
+			}
+
+			if(!newValue.IsNullOrEmpty()) newValue.Append(CMAERA_OCCUPY_SPLIT_MASK_STR);
+			newValue.Append(item.toSysVarString());
+		}
+	}
+
+	if(result == Error_Succeed) {
+
+		if(!newValue.IsNullOrEmpty()) newValue.Append(CMAERA_OCCUPY_SPLIT_MASK_STR);
+		newValue.Append(newItem.toSysVarString());
+		result = pFunc->SetSysVar("CameraOccupyingStatus", newValue);
+	}
+
+	return result;
+}
+
+ /*!
+ * @brief 从系统变量中移除占用摄像头信息
+ * @param[in]  existedItem 需要移除的摄像头和实体信息,支持将存储值为*,意为忽略此项的比较
+ */
+static inline void RemoveOccpuiedCamera(const OccpyCameraStruct& existedItem, CSmartPointer<IEntityFunction> pFunc)
+{
+	if(!existedItem.IsValid() || pFunc == NULL)
+		return;
+
+	CAutoArray<OccpyCameraStruct> existedList;
+	ErrorCodeEnum result = GetOccupiedCameres(existedList, pFunc);
+	bool needToUpdate = false;
+	CSimpleStringA newValue(true);
+	if(existedList.GetCount() > 0) {
+		for (int i=0; i<existedList.GetCount(); ++i)
+		{
+			OccpyCameraStruct& item = existedList[i];
+			if(item.Match(existedItem)) {
+				needToUpdate = true;
+				continue;
+			}
+
+			if(!newValue.IsNullOrEmpty()) newValue.Append(CMAERA_OCCUPY_SPLIT_MASK_STR);
+			newValue.Append(item.toSysVarString());
+		}
+	}
+
+	if(needToUpdate) {
+		result = pFunc->SetSysVar("CameraOccupyingStatus", newValue);
+	}
+	return;
+}
+
+static inline ErrorCodeEnum GetCameraOccpuiedStatus(CEntityBase *pEntity,
+	const char* lpsczDevName, CSimpleStringA& owner)
+{
+	OccpyCameraStruct filter(lpsczDevName, "*");
+	CAutoArray<OccpyCameraStruct> existedList;
+	owner.Clear();
+	ErrorCodeEnum result = GetOccupiedCameres(existedList, pEntity->GetFunction(), &filter);
+	if(existedList.GetCount() == 0) {
+		result = Error_NotExist;
+	}
+	else if(existedList.GetCount() == 1) {
+		owner = existedList[0].strOccupier;
+	} else if(existedList.GetCount() > 0){
+		result = Error_Duplication;
+	}
+	return result;
+}
+
+
+/*实体启动时调用一次,防止上次异常退出没有处理残留信息,导致出现摄像头被占用的假象*/
+static void ResetOwnCameraOccupiedStatus(CEntityBase* pEntity)
+{
+	OccpyCameraStruct item("*", pEntity->GetEntityName());
+	RemoveOccpuiedCamera(item, pEntity->GetFunction());
+}
+
+/*标明摄像头lpcszDevName被当前实体占用*/
+static inline ErrorCodeEnum SetCameraOccpuied(const char* lpcszDevName, CEntityBase* pEntity)
+{
+	CSimpleStringA strTest(lpcszDevName);
+	if(lpcszDevName == NULL || strTest.IsNullOrEmpty()
+		|| strTest[0] == '*' 
+		|| -1 != strTest.IndexOf(CMAERA_OCCUPY_SPLIT_MASK_STR) ||  -1 != strTest.IndexOf("=")) {
+			return Error_Param;
+	}
+
+	OccpyCameraStruct item(lpcszDevName, pEntity->GetEntityName());
+	ErrorCodeEnum result = AppendOccpuiedCamera(item, pEntity->GetFunction());
+	if(result == Error_AlreadyExist)
+		result = Error_Succeed;
+
+	return result;
+}
+
+/*取消摄像头lpcszDevName被当前实体占用的标识*/
+static inline void SetCameraUnoccpuied(const char* lpcszDevName, CEntityBase* pEntity)
+{
+	if(lpcszDevName == NULL || strlen(lpcszDevName) == 0) {
+		return;
+	}
+
+	OccpyCameraStruct item(lpcszDevName, pEntity->GetEntityName());
+	RemoveOccpuiedCamera(item, pEntity->GetFunction());
+}
+
+ /*!
+ * @brief 通过系统变量判断摄像头是否在被其他实体占用
+ * @param[in]  inOutCameraInfo.strCameraName 摄像头名称
+ * @param[out] inOutCameraInfo.strOccupier 占用该摄像头的实体名称
+ * @return : true: 被其他实体占用且该实体处于正常状态,不包括被当前实体占用
+ */
+static bool IsCameraOccupiedByOther(const char* lpcszDevName, CEntityBase* pEntity)
+{
+	OccpyCameraStruct filter(lpcszDevName, "*");
+	CAutoArray<OccpyCameraStruct> existedList;
+	ErrorCodeEnum result = GetOccupiedCameres(existedList, pEntity->GetFunction(), &filter);
+	if(existedList.GetCount() > 0) {
+		for(int i=0; i<existedList.GetCount(); ++i) {
+			if(existedList[i].strOccupier.Compare(pEntity->GetEntityName()) != 0) {
+				CEntityRunInfo info;
+				result = pEntity->GetFunction()->GetEntityRunInfo(existedList[i].strOccupier, info);
+				if(result == Error_Succeed
+					&& (info.eState == EntityState_Idle || info.eState == EntityState_Busy 
+					|| info.eState == EntityState_Pause
+					 || info.eState == EntityState_UnLoading)) {
+						 return true;
+				}
+			}
+		}
+	}
+	return false;
+}
+
+
+#ifdef TWINKLE_LOCAL_DEBUG
+
+/*测试案例*/
+static int UniTest(CEntityBase* pEntity)
+{
+	OccpyCameraStruct camera0("*", "*");
+	OccpyCameraStruct camera("FirstCamera", pEntity->GetEntityName());
+	OccpyCameraStruct camera2("SecondCamera", "GUIConsole");
+	OccpyCameraStruct camera3("SecondCamera", pEntity->GetEntityName());
+	OccpyCameraStruct camera4("ThirdCamera", pEntity->GetEntityName());
+	OccpyCameraStruct camera5("*", pEntity->GetEntityName());
+
+	ResetOwnCameraOccupiedStatus(pEntity);
+	//RemoveOccpuiedCamera(camera0, pEntity->GetFunction());
+
+	CAutoArray<OccpyCameraStruct> existedList;
+	ErrorCodeEnum result = GetOccupiedCameres(existedList, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__;
+	}
+	if(existedList.GetCount() != 0) {
+		return __LINE__;
+	}
+
+	result = AppendOccpuiedCamera(camera, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__; 
+	}
+
+	if(IsCameraOccupiedByOther("FirstCamera", pEntity)) {
+		return __LINE__; 
+	}
+	if(IsCameraOccupiedByOther("SecondCamera", pEntity)) {
+		return __LINE__; 
+	}
+
+	result = AppendOccpuiedCamera(camera, pEntity->GetFunction());
+	if(result != Error_AlreadyExist) {
+		return __LINE__; 
+	}
+
+	result = AppendOccpuiedCamera(camera2, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__; 
+	}
+	if(!IsCameraOccupiedByOther("SecondCamera", pEntity)) {
+		return __LINE__; 
+	}
+
+	result = AppendOccpuiedCamera(camera3, pEntity->GetFunction());
+	if(result != Error_Duplication) {
+		return __LINE__; 
+	}
+
+	result = GetOccupiedCameres(existedList, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__;
+	}
+	if(existedList.GetCount() != 2) {
+		return __LINE__;
+	}
+
+	result = GetOccupiedCameres(existedList, pEntity->GetFunction(), &camera);
+	if(existedList.GetCount() != 1) {
+		return __LINE__;
+	}
+
+	if(!(existedList[0] == camera)) {
+		return __LINE__;
+	}
+
+	result = AppendOccpuiedCamera(camera4, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__; 
+	}
+	result = GetOccupiedCameres(existedList, pEntity->GetFunction(), &camera5);
+	if(existedList.GetCount() != 2) {
+		return __LINE__;
+	}
+
+	result = GetOccupiedCameres(existedList, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__;
+	}
+	if(existedList.GetCount() != 3) {
+		return __LINE__;
+	}
+
+	RemoveOccpuiedCamera(camera5, pEntity->GetFunction());
+	result = GetOccupiedCameres(existedList, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__;
+	}
+	if(existedList.GetCount() != 1) {
+		return __LINE__;
+	}
+
+	if(!(existedList[0] == camera2)) {
+		return __LINE__;
+	}
+
+	RemoveOccpuiedCamera(camera2, pEntity->GetFunction());
+	if(result != Error_Succeed) {
+		return __LINE__;
+	}
+
+	//RemoveOccpuiedCamera(camera0, pEntity->GetFunction());
+
+	AppendOccpuiedCamera(camera, pEntity->GetFunction());
+	AppendOccpuiedCamera(camera3, pEntity->GetFunction());
+
+	return 0;
+}
+
+#endif //TWINKLE_LOCAL_DEBUG

+ 8 - 0
Module/mod_ScannerSet/ChangeLog.md

@@ -0,0 +1,8 @@
+## version 1.0.0.3
+
+* 去除对摄像头占用的检测,所有接口返回未占用(廖桂发,2021年4月12日)
+
+## version 1.0.0.2
+
+* 添加对低柜一体机的支持(Gifur,2020-8-18)
+

+ 3 - 5
Module/mod_ScannerSet/EventRevWnd.cpp

@@ -53,7 +53,6 @@ ATOM RegisterWndClass(HINSTANCE hInstance)
 
 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-	//Dbg("WndProc: %d %d", message, (int)lParam);
 	switch(message)
 	{
 	case WM_CREATE:
@@ -85,7 +84,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 			while(pME->GetEvent(&event, &l1, &l2, 0) == S_OK)
 			{
 				pME->FreeEventParams(event, l1, l2);
-				Dbg("GetEvent %d, %d, %d", event, l1, l2);
+				DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetEvent %d, %d, %d", event, l1, l2);
 				if(event == EC_ERRORABORT)
 				{
 					bAbort = TRUE;
@@ -107,17 +106,16 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 							{
 								pf->Release();
 								bAbort = FALSE;
-								Dbg("Stopping Capture (Device Lost). Select New Capture Device\0");
 								break;
 							}
-							//pf->Release();
+							pf->Release();
 						}
 					}
 				}
 			} // end while
 			if(bAbort)
 			{
-				Dbg("ERROR during capture, error code=%08x\0", hrAbort);
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("ERROR during capture, error code=0x%08X", hrAbort);
 			}
 		}
 		break;

Файловите разлики са ограничени, защото са твърде много
+ 207 - 174
Module/mod_ScannerSet/ScannerSetFSM.cpp


+ 162 - 26
Module/mod_ScannerSet/ScannerSetFSM.h

@@ -15,7 +15,7 @@ using namespace ScannerSet;
 #include "HSPScanner_client_g.h"
 #include "PortableScanner_client_g.h"
 #include "HeartBeat_client_g.h"
-
+#include "MediaController_client_g.h"
 using namespace HSPScanner;
 using namespace PortableScanner;
 
@@ -23,6 +23,9 @@ using namespace PortableScanner;
 #include "CameraImpl.h"
 #endif //RVC_OS_WIN
 #include "DeviceCrossHelper.h"
+#include "EventCode.h"
+#include "ScannerSet_UserErrorCode.h"
+#include "CameraOccupySysVar.hpp"
 
 #define ISSUCCEEDED(hr) ((hr) == Error_Succeed)
 #define FAILURED(hr) (!(ISSUCCEEDED(hr)))
@@ -44,11 +47,6 @@ public:
 	{
 
 	}
-
-	~CHSPSInnerClient()
-	{
-		Dbg("to delete %s", __FUNCTION__);
-	}
 };
 
 class CPortableScannerClient : public PortableScannerService_ClientBase
@@ -71,6 +69,16 @@ public:
 	}
 };
 
+class CMediaCtrlClient : public MediaController::MediaService_ClientBase
+{
+public:
+	CMediaCtrlClient(CEntityBase *pEntity)
+		:MediaController::MediaService_ClientBase(pEntity)
+	{
+
+	}
+};
+
 template<typename TEntity>
 struct AvailableEntityCheck {
 	typedef TEntity Type;
@@ -152,9 +160,9 @@ public:
 	SpReqAnsContext<ScannerService_StartPreview_Req, ScannerService_StartPreview_Ans>::Pointer m_ctx;
 	virtual void OnUnhandled()
 	{
-		if(m_ctx != NULL)
+		if(m_ctx != NULL) 
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -170,7 +178,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -186,7 +194,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -210,7 +218,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -226,7 +234,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -242,7 +250,8 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("set winpos unhandle!");
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -258,7 +267,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -274,7 +283,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -290,7 +299,7 @@ public:
 	{
 		if(m_ctx != NULL)
 		{
-			m_ctx->Answer(Error_InvalidState);
+			m_ctx->Answer(Error_InvalidState, LOG_WARN_FSM_INVALID);
 		}
 	}
 };
@@ -318,7 +327,7 @@ public:
 
 	BEGIN_FSM_STATE(CScannerFSM)
 		FSM_STATE_ENTRY(s0, "Idle", s0_on_entry, s0_on_exit, s0_on_event)
-		FSM_STATE_ENTRY(s1, "Estimate", s1_on_entry, s1_on_exit, s1_on_event)
+		FSM_STATE_ENTRY(s1, "Estimate", s1_on_entry, s1_on_exit, s1_on_event) //no used now!!!
 		FSM_STATE_ENTRY(s2, "Operating", s2_on_entry, s2_on_exit, s2_on_event)
 		FSM_STATE_ENTRY(s3, "Failed", s3_on_entry, s3_on_exit, s3_on_event)
 		FSM_STATE_ENTRY(s4, "Invalid", s4_on_entry, s4_on_exit, s4_on_event)
@@ -331,7 +340,7 @@ public:
 		FSM_RULE_ENTRY_ANY(s4, s0, USER_EVT_DEV_RECOVER)
 
 		FSM_RULE_ENTRY_ANY(s0, s2, USER_EVT_OPERATING)
-
+		/*S2 中所有处理结果都返回1,见 s2_on_event 实现*/
 		FSM_RULE_ENTRY(s2, s0, USER_EVT_STARTPREVIEW_FINISHED, 1)
 		FSM_RULE_ENTRY(s2, s0, USER_EVT_STOPPREVIEW_FINISHED, 1)
 		FSM_RULE_ENTRY(s2, s0, USER_EVT_SCANIMAGEFINISHED, 1)
@@ -391,20 +400,33 @@ public:
 	int GetOnlineDevices(SpReqAnsContext<ScannerService_GetOnlineCameras_Req,
 		ScannerService_GetOnlineCameras_Ans>::Pointer ctx);
 
-	ErrorCodeEnum DropOffPortScannerDevice();
+	ErrorCodeEnum DropOffPortScannerDevice(bool skipToCheck = true);
 
 	void InitializeMehodQueue();
 	void DestoryMethodQueue();
-	void DealWithCrossTermCall(SpReqAnsContext<ScannerService_CrossTermCall_Req,
-		ScannerService_CrossTermCall_Ans>::Pointer ctx);
 
 	ErrorCodeEnum OnDevExit();
 	ErrorCodeEnum AttachCheck();
+	ErrorCodeEnum AttachReleaseIfNecessary();
 
 	bool IsAgent() const {
 		return m_bJBMachine;
 	}
 
+	bool IsWorking() {
+		return (GetCurrState()->id == s2);
+	}
+
+	const char* GetChildEntityName() {
+		if(m_bUsePortableScanner) {
+			return "PortableScanner";
+		} else {
+			return "HSPSCanner";
+		}
+	}
+
+	void OnChildEntityStateChange(const EntityStateEnum& oldState, const EntityStateEnum& curState);
+
 private:
 
 	CSimpleStringA m_csMachineType;
@@ -419,6 +441,7 @@ private:
 	CHSPSInnerClient* m_pHSPSClient;
 	CPortableScannerClient* m_pPortableClient;
 	CHeartBeatClient* m_pHeartBeatClient;
+	CMediaCtrlClient* m_pMediaControlClient;
 
 	ErrorCodeEnum m_ecSelfTest;
 	DWORD m_dwErroCode;
@@ -432,6 +455,7 @@ private:
 
 #if defined(RVC_OS_WIN)
     CAMERA_BUCKET m_cameralist;
+	CRITICAL_SECTION cs_devEvt;
 #endif //RVC_OS_WIN
 	std::mutex mMtx;
 
@@ -454,6 +478,10 @@ public:
 
 public:
 
+	bool IsHSPSConnectSessionOK();
+	bool IsPortableConnectSessionOK();
+	bool IsHeartbeatConnectSessionOK();
+
 	ErrorCodeEnum CheckHSPSConnectStatus();
 	ErrorCodeEnum ConnectToHSPScanner();
 	void FreeHSPScannerClient()
@@ -475,14 +503,41 @@ public:
 			m_pPortableClient = NULL;
 		}
 	}
+
+	bool IsNoralEntityState(const EntityStateEnum& state) {
+		if(state == EntityState_Idle || state == EntityState_Busy 
+			|| state == EntityState_Pause
+			|| state == EntityState_UnLoading) {
+				return true;
+		}
+		return false;
+
+	}
+
 	ErrorCodeEnum GetPortableScannerInfo() {
 		EntityStateEnum state = EntityState_NoStart;
 		ErrorCodeEnum rc = GetEntityCurState(state, "PortableScanner");
-		Dbg("PortableScanner entity state: %d(%s)", state, SpStrError(rc));
+		LogWarn(Severity_Low,Error_Debug,LOG_ERR_SCANNERSET_PORTABLESCANNER_STATE,
+			CSimpleStringA::Format("PortableScanner entity state: %d(%u)", state, rc));
+		if(rc == Error_Succeed && IsNoralEntityState(state)) {
+				//let it empty.	
+		} else if(IsPortScanHoldEnvCameraFromSysVar()){
+			HandleCamereAccessPriviledge(false, CAMTYPE_ENV, m_fixedCamera[CAMTYPE_ENV-1].strDevName);
+			ClearPortScanHoldLimitedDevice(CAMTYPE_MAX);
+		}
 		return rc;
 	}
+
 	ErrorCodeEnum IsPortScanHoldDevice(ScannerDeviceInfo* pInfo, int& curState);
 	ErrorCodeEnum IsPortScanHoldDevice(bool& hasHolden, int& DevID, CSimpleStringA& strDevName, bool& bBusy);
+	bool IsPortScanHoldLimitedDevice(CapTypeEnum& devType);
+	bool IsPortScanHoldEnvCameraFromSysVar()
+	{
+		CapTypeEnum devType(CAMTYPE_UNKNOWN);
+		return (IsPortScanHoldLimitedDevice(devType) && devType == CAMTYPE_ENV);
+	}
+	void ClearPortScanHoldLimitedDevice(const CapTypeEnum& devType, const char* lpcszDevName = NULL);
+	
 	ErrorCodeEnum TryBindPSDevice(int nDevID, LPCTSTR lpcszDevName);
 	ErrorCodeEnum BindPSDevice(int nDevID, LPCTSTR lpcszDevName);
 	int GetAdvancedScannerDevice(ScannerDeviceInfo* pDevInfo);
@@ -490,6 +545,7 @@ public:
 		const CAutoArray<CSimpleStringA>& caForbitDeviceNames);
 
 	void SendBroadcastAbout();
+	void WaitPortableReleaseCamera(int nCameraType, DWORD dwTimeoutMilSec = 3000);
 
 	ErrorCodeEnum CheckHeartbeatConnectStatus();
 	ErrorCodeEnum ConnectToHeartbeat();
@@ -500,6 +556,26 @@ public:
 		}
 	}
 
+	ErrorCodeEnum ConnectToMediaController();
+	void FreeMediaControllerClient()
+	{
+		if(m_pMediaControlClient) {
+			m_pMediaControlClient->GetFunction()->CloseSession();
+			m_pMediaControlClient = NULL;
+		}
+	}
+	ErrorCodeEnum GetMediaControllerInfo(EntityStateEnum& curState) {
+		EntityStateEnum state = EntityState_NoStart;
+		ErrorCodeEnum rc = GetEntityCurState(state, "MediaController");
+		DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("MediaController entity state: %d(%u)", state, rc);
+		curState = state;
+		return rc;
+	}
+
+	ErrorCodeEnum AccessCamerePriviledge(bool fWinOver, int nCameraType);
+	ErrorCodeEnum HandleCamereAccessPriviledge(bool fWinOver, int nCameraType, const char* lpcszDevName);
+
+
 	bool GetAttachedTerminal(CSimpleStringA &csTerm);
 	//Desperate
 	//ErrorCodeEnum SendRequest2Heatbeat(DWORD dwMethodSig, const CAutoBuffer& Req, CAutoBuffer& Ans);
@@ -510,9 +586,15 @@ public:
 	ErrorCodeEnum ReceiveAnswer5Heartbeat(SpOnewayCallContext<ScannerService_CrossTermInvokeInfo_Info>::Pointer ctx);
 	ErrorCodeEnum ReceiveRequest5Heartbeat(const ScannerService_CrossTermCall_Req& req, 
 		ScannerService_CrossTermCall_Ans& ans);
+
+
+	UINT UnitTest();
+	void AfterInit();
+
 private:
 
-	ErrorCodeEnum GetEntityCurState(EntityStateEnum& state, LPCTSTR lpcszEntityName) {
+	ErrorCodeEnum GetEntityCurState(EntityStateEnum& state, LPCTSTR lpcszEntityName) 
+	{
 		CSmartPointer<IEntityFunction> pFunc = GetEntityBase()->GetFunction();
 		CSmartPointer<IEntityFunctionPrivilege> pFuncPrivilege =
 			pFunc.ConvertCase<IEntityFunctionPrivilege>();
@@ -524,7 +606,8 @@ private:
 		return ecInfo;
 	}
 
-	bool IsSuitableEntityAvailable() {
+	bool IsSuitableEntityAvailable() 
+	{
 		if((m_bStand2SMachine && ISSUCCEEDED(ConnectToHSPScanner()))
 			|| ( (m_bUsePortableScanner) && ISSUCCEEDED(ConnectToPortableScanner()))
 			|| (m_bJBMachine  && ISSUCCEEDED(ConnectToHeartbeat()))) {
@@ -532,7 +615,9 @@ private:
 		}
 		return false;
 	}
-	void ReleaseSuitableEntity() {
+
+	void ReleaseSuitableEntity() 
+	{
 		if(m_bStand2SMachine) {
 			FreeHSPScannerClient();
 		}else if(m_bUsePortableScanner) {
@@ -567,6 +652,10 @@ private:
 		return (PVOID)ctx.GetRawPointer();
 		//return reinterpret_cast<PVOID>(ctx.GetRawPointer());
 	}
+
+	bool ShouldUsePortableScanner() const {
+		return (m_bPadMachine || m_bDesk2SMachine || m_bDesk1SMachine);
+	}
 };
 
 struct StartPreviewTask : public ITaskSp
@@ -581,7 +670,7 @@ struct StartPreviewTask : public ITaskSp
 		if(ISSUCCEEDED(rc)) {
 			pEvt->param1 = m_fsm->StartPreview(m_ctx);
 		}else {
-			m_ctx->Answer(Error_DevNotAvailable);
+			m_ctx->Answer(rc, LOG_WARN_ATTACH_FAILED);
 			pEvt->param1 = 10;
 		}
 		m_fsm->PostEventFIFO(pEvt);
@@ -605,7 +694,11 @@ struct StopPreviewTask : public ITaskSp
 	void Process()
 	{
 		FSMEvent* pEvt = new FSMEvent(USER_EVT_STOPPREVIEW_FINISHED);
+		const bool bOnlyHide = m_ctx->Req.reserved1 == 0 ? false : true;
 		pEvt->param1 = m_fsm->StopPreview(m_ctx);
+		if(!bOnlyHide) {
+			m_fsm->AttachReleaseIfNecessary();
+		}
 		m_fsm->PostEventFIFO(pEvt);
 		return;
 	}
@@ -684,6 +777,49 @@ struct ShowPropertyTask : public ITaskSp
 	}
 };
 
+
+struct PendingTask : public ITaskSp
+{
+	CScannerFSM* m_fsm;
+	SpReqAnsContext<ScannerService_SetWindowPos_Req, 
+		ScannerService_SetWindowPos_Ans>::Pointer m_ctx;
+	PendingTask(CScannerFSM* fsm): m_fsm(fsm){}
+	void Process()
+	{
+		LOG_FUNCTION();
+		WaitingFSMForIdle();
+		SetWinPosEvent* pEvent = new SetWinPosEvent();
+		pEvent->m_ctx = m_ctx;
+		m_fsm->PostEventFIFO(pEvent);
+		return;
+	}
+	void SetContext(
+		SpReqAnsContext<ScannerService_SetWindowPos_Req, 
+		ScannerService_SetWindowPos_Ans>::Pointer ctx)
+	{
+		m_ctx = ctx;
+		return;
+	}
+
+private:
+
+	void WaitingFSMForIdle() 
+	{
+		static const int waitTimes = 30;
+		static const int waitEachTimeout = 300;
+		int waitCurrTimes = 0;
+
+		while(m_fsm->IsWorking() && (++waitCurrTimes <= waitTimes)) {
+			Sleep(waitEachTimeout);
+		}
+
+		if(waitCurrTimes > waitTimes) {
+			LogWarn(Severity_Low, Error_TimeOut, 
+				LOG_EVT_SCANNERSET_HSPSCNT_TASK_TIMEOUT, "Waiting FSM to Idle timeout!");
+		}
+	}
+};
+
 struct SetWinPosTask : public ITaskSp
 {
 	CScannerFSM* m_fsm;

+ 34 - 0
Module/mod_ScannerSet/ScannerSet_UserErrorCode.h

@@ -0,0 +1,34 @@
+#ifndef _SCANNERSET_USER_ERRORCODE_H
+#define _SCANNERSET_USER_ERRORCODE_H
+#pragma once
+
+#define LOG_EVT_SCANNERSET_HSPSCNT_FAILED 0x21800001
+#define LOG_EVT_SCANNERSET_HSPSCNT_TASK_TIMEOUT 0x21800002
+#define LOG_ERR_SCANNERSET_HSPSCNT_ACCESS_ENV_FAILED 0x21800003
+#define LOG_ERR_SCANNERSET_CONNECT_MEDIACONTRLLER_FAILED 0x21800004
+#define LOG_ERR_SCANNERSET_MEDIACONTROLLER_MANIPULATE_FAILED 0x21800005
+#define LOG_ERR_SCANNERSET_PORTABLESCANNER_STATE 0x21800006
+#define LOG_ERR_SCANNERSET_CONFIGURE_CAMERA 0x21800007
+#define LOG_ERR_SCANNERSET_BIND_CAMERA 0x21800008
+#define LOG_ERR_SCANNERSET_NO_AVAILABLE_CAMERA 0x21800009
+#define LOG_WARN_CONNECT_PORTABLESCANNER_FAILED 0x2180000A
+#define LOG_WARN_DUPLICATE_SETWINPOS 0x2180000B
+#define LOG_WARN_INVALID_SETWINPOS 0x2180000C
+#define LOG_WARN_MODULE_INVALID 0x2180000D
+#define LOG_WARN_FSM_INVALID 0x2180000E
+#define LOG_WARN_ATTACH_FAILED 0x2180000F
+
+#define LOG_ERR_SCANNERSET_API_INVOKE_START 0x218F0000
+#define LOG_ERR_SCANNERSET_API_INVOKE_BindCameraDevice 0x218F0001
+#define LOG_ERR_SCANNERSET_API_INVOKE_StartPreview 0x218F0002
+#define LOG_ERR_SCANNERSET_API_INVOKE_CancelPreview 0x218F0003
+#define LOG_ERR_SCANNERSET_API_INVOKE_GetDevStatus 0x218F0004
+#define LOG_ERR_SCANNERSET_API_INVOKE_ScanImage 0x218F0005
+#define LOG_ERR_SCANNERSET_API_INVOKE_ScanImageEx 0x218F0006
+#define LOG_ERR_SCANNERSET_API_INVOKE_SetProperty 0x218F0007
+#define LOG_ERR_SCANNERSET_API_INVOKE_ShowProperty 0x218F0008
+#define LOG_ERR_SCANNERSET_API_INVOKE_SetWinPos 0x218F0009
+#define LOG_ERR_SCANNERSET_API_INVOKE_GetDevInfo 0x218F000A
+
+
+#endif //_SCANNERSET_USER_ERRORCODE_H

+ 3 - 3
Module/mod_ScannerSet/ScannerSet_def_g.h

@@ -32,11 +32,11 @@ namespace ScannerSet {
 #define ScannerService_MethodSignature_SetProperty -712141050
 #define ScannerService_MethodSignature_ShowProperty -2138273708
 #define ScannerService_MethodSignature_GetDevStatus 1693345709
-#define ScannerService_MethodSignature_GetOnlineCameras -1966467273
-#define ScannerService_MethodSignature_GetDevInfo 825740532
 #define ScannerService_MethodSignature_Exit -1158854104
-#define ScannerService_MethodSignature_CrossTermCall 74706330
+#define ScannerService_MethodSignature_GetOnlineCameras -1966467273
 #define ScannerService_MethodSignature_CrossTermInvokeInfo 931240070
+#define ScannerService_MethodSignature_CrossTermCall 74706330
+#define ScannerService_MethodSignature_GetDevInfo 825740532
 
 struct ScannerService_StartPreview_Req
 {

+ 103 - 19
Module/mod_ScannerSet/mod_ScannerSet.h

@@ -8,7 +8,7 @@
 
 #include "ScannerSetFSM.h"
 #include "EventCode.h"
-
+#include "ScannerSet_UserErrorCode.h"
 
 
 #include "HSPScanner_client_g.h"
@@ -75,11 +75,18 @@ public:
 	PortableScannerClient(CScannerEntity *pEntity);
 };
 
-class CScannerEntity : public CEntityBase, public ILogListener
+class CScannerEntity : public CEntityBase, public ILogListener, public IEntityStateListener
 {
 public:
 	CScannerEntity() {}
-	virtual ~CScannerEntity() {}
+	virtual ~CScannerEntity() 
+	{
+		if(GetFunction()->HasPrivilege()) {
+			CSmartPointer<IEntityFunction> pFunc = GetFunction();
+			CSmartPointer<IEntityFunctionPrivilege> pFuncPrivilege = pFunc.ConvertCase<IEntityFunctionPrivilege>();
+			pFuncPrivilege->UnregistEntityStateEvent(m_fsm.GetChildEntityName());
+		}
+	}
 	virtual const char *GetEntityName() const { return "ScannerSet"; }
 
     const char* GetEntityVersion() const { return MODULE_VERSION_FULL; }
@@ -102,25 +109,49 @@ public:
 #endif //RVC_OS_WIN
 		pTransactionContext->SendAnswer(erroCode);
 	}
+
+	void OnStarted()
+	{
+		if(GetFunction()->HasPrivilege()) {
+			CSmartPointer<IEntityFunction> pFunc = GetFunction();
+			CSmartPointer<IEntityFunctionPrivilege> pFuncPrivilege = pFunc.ConvertCase<IEntityFunctionPrivilege>();
+			pFuncPrivilege->RegistEntityStateEvent(m_fsm.GetChildEntityName(), this);
+		} else {
+			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("cur entity has no priviledge!");
+		}
+		m_fsm.AfterInit();
+	}
+
 	virtual void OnPrePause(CSmartPointer<ITransactionContext> pTransactionContext)
 	{
 		LOG_FUNCTION();
+
+#ifdef TWINKLE_LOCAL_DEBUG
+
+		const UINT result = UniTest(this);
+		if(result != 0) {
+			LogError(Severity_High, Error_Unexpect, result, CSimpleStringA::Format("line: %u", result));
+		}
+
+#endif
 		SpReqAnsContext<ScannerService_StartPreview_Req,
 			ScannerService_StartPreview_Ans>::Pointer ctx = 
 			new SpReqAnsContext<ScannerService_StartPreview_Req,
 			ScannerService_StartPreview_Ans>(pTransactionContext);
 		Preview(ctx);
+
 		pTransactionContext->SendAnswer(Error_Succeed);
 	}
+
 	virtual void OnPreContinue(CSmartPointer<ITransactionContext> pTransactionContext)
 	{
 		Exit(NULL);
 		pTransactionContext->SendAnswer(Error_Succeed);
 	}
+
 	virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,
 		CSmartPointer<ITransactionContext> pTransactionContext)
 	{
-		LOG_FUNCTION();
 		ErrorCodeEnum erroCode = m_fsm.OnExit();
 		pTransactionContext->SendAnswer(erroCode);
 	}
@@ -128,7 +159,6 @@ public:
 	void Preview(SpReqAnsContext<ScannerService_StartPreview_Req,
 		ScannerService_StartPreview_Ans>::Pointer ctx)
 	{
-		LOG_FUNCTION();
 		StartPreviewEvent* pEvent = new StartPreviewEvent();
 		pEvent->m_ctx = ctx;
 		m_fsm.PostEventFIFO(pEvent);
@@ -152,12 +182,7 @@ public:
 
 	void Exit(SpOnewayCallContext<ScannerService_Exit_Info>::Pointer ctx)
 	{
-		LOG_FUNCTION();
 		ErrorCodeEnum erroCode = m_fsm.OnDevExit();
-		if(FAILURED(erroCode))
-		{
-			Dbg("OnDevExit results 0x%x(%d).", erroCode, erroCode);
-		}
 	}
 
 	void GetDevInfo(SpReqAnsContext<ScannerService_GetDevInfo_Req,
@@ -168,21 +193,47 @@ public:
 	}
 
 	void GetOnlineCameras(SpReqAnsContext<ScannerService_GetOnlineCameras_Req,
-		ScannerService_GetOnlineCameras_Ans>::Pointer ctx) {
-			m_fsm.GetOnlineDevices(ctx);
+		ScannerService_GetOnlineCameras_Ans>::Pointer ctx) 
+	{
+		m_fsm.GetOnlineDevices(ctx);
 	}
 
+
+
 	void SetWinPos(SpReqAnsContext<ScannerService_SetWindowPos_Req,
 		ScannerService_SetWindowPos_Ans>::Pointer ctx)
 	{
-		SetWinPosEvent* pEvent = new SetWinPosEvent();
-		pEvent->m_ctx = ctx;
-		m_fsm.PostEventFIFO(pEvent);
+		static ScannerService_SetWindowPos_Req  lastReq = {-1, -1, -1, -1, -1};
+
+		if((ctx->Req.type != lastReq.type
+			|| ctx->Req.pointX != lastReq.pointX
+			|| ctx->Req.pointY != lastReq.pointY
+			|| ctx->Req.nWidth != lastReq.nWidth
+			/*|| ctx->Req.reserved4 != lastReq.reserved4*/)) {
+
+				lastReq.type = ctx->Req.type;
+				lastReq.pointX = ctx->Req.pointX;
+				lastReq.pointY = ctx->Req.pointY;
+				lastReq.nWidth = ctx->Req.nWidth;
+				lastReq.reserved4 = ctx->Req.reserved4;
+
+				PendingTask* pTask = new PendingTask(&m_fsm);
+				pTask->SetContext(ctx);
+				GetFunction()->PostThreadPoolTask(pTask);
+
+		} else {
+
+			LogWarn(Severity_Low, Error_Debug, LOG_WARN_DUPLICATE_SETWINPOS
+				, CSimpleStringA::Format("same request with last-one: %d,%d,%d,%d,%d"
+														, ctx->Req.type, ctx->Req.pointX, ctx->Req.pointY, ctx->Req.nWidth, ctx->Req.reserved4));
+			ctx->Answer(Error_Succeed);
+		}
 	}
 
 	void SetProperty(SpReqAnsContext<ScannerService_SetProperty_Req, 
 		ScannerService_SetProperty_Ans>::Pointer ctx)
 	{
+		WaitingFSMForIdle();
 		SetPropertyEvent* pEvent = new SetPropertyEvent();
 		pEvent->m_ctx = ctx;
 		m_fsm.PostEventFIFO(pEvent);
@@ -238,7 +289,7 @@ public:
 		const CAutoArray<DWORD> &Param, 
 		const char *pszEntityName, 
 		const char *pszModuleName,
-		const char *pszMessage, const linkContext& pLinkInfo)
+		const char *pszMessage, const linkContext &pLinkInfo)
 	{
 		switch (dwUserCode)
 		{
@@ -249,13 +300,13 @@ public:
 			m_fsm.OnDeviceRemoved();
 			break;
 		case EVENT_USB_CAMERA_NOT_ONLY:
-			Dbg("EVENT_USB_CAMERA_NOT_ONLY occurs !!!");
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("EVENT_USB_CAMERA_NOT_ONLY occurs !!!");
 			break;
 		case EVENT_USB_CAMERA_INPUT:
-			Dbg("EVENT_USB_CAMERA_INPUT occurs !!!");
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("EVENT_USB_CAMERA_INPUT occurs !!!");
 			break;
 		case LOG_ERROR_PORTABLESCANNER_IN_PREVIEW:
-			Dbg("LOG_ERROR_PORTABLESCANNER_IN_PREVIEW: %s", pszMessage);
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("LOG_ERROR_PORTABLESCANNER_IN_PREVIEW: %s", pszMessage);
 			{
 				m_fsm.PSEntityPostCameraError(pszMessage);
 			}
@@ -263,6 +314,39 @@ public:
 		}
 	}
 
+	void OnEntityStateHook(const char *pszEntityName,const char *pszTriggerEntity,
+		EntityStateEnum eState,EntityStateEnum eLastState)
+	{
+		m_fsm.OnChildEntityStateChange(eLastState, eState);
+	}
+	void OnUserStateHook(const char *pszEntityName,DWORD dwState,DWORD dwLastState)
+	{
+
+	}
+	void OnCeateConnection(const char *pszCallerEntity,const char *pszServiceEntity)
+	{
+
+	}
+	void OnCloseConnection(const char *pszCallerEntity,const char *pszServiceEntity)
+	{
+
+	}
+
+	void WaitingFSMForIdle() 
+	{
+		static const int waitTimes = 30;
+		static const int waitEachTimeout = 300;
+		int waitCurrTimes = 0;
+
+		while(m_fsm.IsWorking() && (++waitCurrTimes <= waitTimes)) {
+			Sleep(waitEachTimeout);
+		}
+
+		if(waitCurrTimes > waitTimes) {
+			LogWarn(Severity_Low, Error_TimeOut, 0, "Waiting FSM to Idle timeout!");
+		}
+	}
+
 private:
 	CScannerFSM m_fsm;
 	CUUID m_uuidMaintainWatcher;

Някои файлове не бяха показани, защото твърде много файлове са промени