浏览代码

Merge branch 'develop' of http://mayun.itc.cmbchina.cn/QD_RemoteBankArea/LR04.02_RVCTerminalPlus into develop

gifur 4 年之前
父节点
当前提交
d18f12a1a1

+ 96 - 47
Module/mod_chromium/CModTools.cpp

@@ -34,7 +34,7 @@ namespace Chromium{
 //CRITICAL_SECTION g_csInvokFreeRDP;
 	std::mutex g_mutexFreerdp;
 
-CModTools::CModTools(CEntityBase* pEntity){
+void CModTools::InitCModTools(CEntityBase* pEntity){
 	this->m_pEntity = pEntity;
 }
 
@@ -65,6 +65,11 @@ bool CModTools::killAllChromium()
 #endif
 }
 
+bool CModTools::killChromiumByName(std::string name)
+{
+	return true;
+}
+
 std::pair<bool, std::string> CModTools::getAdUrl()
 {
 	auto configRet = ReadCenterConfigStr();
@@ -73,14 +78,23 @@ std::pair<bool, std::string> CModTools::getAdUrl()
 	return strUrl.length() > 0 ? std::make_pair(true, strUrl) : std::make_pair(false, strUrl);
 }
 
-std::pair<bool, std::string> CModTools::GenerateErrPage(ERR_PAGE_REASON errType)
+std::pair<bool, std::string> CModTools::getErrUrl()
 {
 	CSimpleStringA errPagePath;
-	this->m_pEntity->GetFunction()->GetPath("Base", errPagePath);
+	m_pEntity->GetFunction()->GetPath("Base", errPagePath);
 	errPagePath.Append(CSimpleStringA(SPLIT_SLASH_STR) + "res" + CSimpleStringA(SPLIT_SLASH_STR) + "ManagerDesktop" + CSimpleStringA(SPLIT_SLASH_STR) + "errPage.html");
+
+	return std::make_pair(true, errPagePath.GetData());
+}
+
+std::pair<bool, std::string> CModTools::GenerateErrPage(ERR_PAGE_REASON errType)
+{
+	auto errUrlRet = getErrUrl();
+	CSimpleStringA errPagePath = errUrlRet.second.c_str();
 	
 	switch (errType)
 	{
+		/* 不应该有
 	case ERR_PAGE_REASON::CardStoreIsBusy:
 		errPagePath.Append(CSimpleStringA("?reason=") + errType._to_string() + "&errmsg=卡库正在使用中");
 		setLimitReason(errType._to_string());
@@ -88,7 +102,7 @@ std::pair<bool, std::string> CModTools::GenerateErrPage(ERR_PAGE_REASON errType)
 	case ERR_PAGE_REASON::MachineTypeError:
 		errPagePath.Append(CSimpleStringA("?reason=") + errType._to_string() + "&errmsg=双屏版只检测到单屏");
 		setLimitReason("breakdown");
-		break;
+		break;*/
 	case ERR_PAGE_REASON::breakdown:
 	{
 		CSimpleStringA m_sAuthErrMsg, ts;
@@ -106,9 +120,31 @@ std::pair<bool, std::string> CModTools::GenerateErrPage(ERR_PAGE_REASON errType)
 		errPagePath.Append(CSimpleStringA("?reason=") + errType._to_string());
 		break;
 	default:
-		break;
+		return std::make_pair(false, std::string("unknown err_page_reason:").append(errType._to_string()));
+	}
+
+	errPagePath.Append(" ");
+	CSimpleStringA cachePath;
+	this->m_pEntity->GetFunction()->GetPath("Temp", cachePath);
+	cachePath.Append(CSimpleStringA(SPLIT_SLASH_STR) + "cefCache");
+	errPagePath.Append(" --cache-path=").Append(cachePath);
+
+	errPagePath.Append(" --no-sandbox");
+	errPagePath.Append(" --hide-controls");
+	errPagePath.Append(" --always-on-top");
+	switch (errType)
+	{
+	case ERR_PAGE_REASON::TerminalManagerKickOut:
+	case ERR_PAGE_REASON::TerminalManagerOff:
+		errPagePath.Append(" --logextend=").Append((+PAGE_TYPE::TerminalManager)._to_string());
+	case ERR_PAGE_REASON::CameraConfig:
+		errPagePath.Append(" --logextend=").Append((+PAGE_TYPE::CameraConfig)._to_string());
+	default:
+		errPagePath.Append(" --logextend=").Append((+PAGE_TYPE::errPage)._to_string());
 	}
-	Dbg("GenerateErrPage type=%s, dstPage=%s", errType._to_string(), errPagePath);
+	
+
+	Dbg("GenerateErrPage type=%s, dstPage=%s", errType._to_string(), errPagePath.GetData());
 
 	return std::make_pair(true, (const char*)errPagePath.GetData());
 }
@@ -228,12 +264,13 @@ std::string CModTools::generateAdCmd(std::string AdUrl) {
 	strCmdLine.Append(" --no-sandbox");
 	strCmdLine.Append(" --hide-controls");
 	//strCmdLine.Append(" --always-on-top");
-	strCmdLine.Append(" --logextend=ad");
+	strCmdLine.Append(" --logextend=").Append((+PAGE_TYPE::Ad)._to_string());
 	strCmdLine.Append(" --run-extend");
 	DbgEx("cmdline : %s", strCmdLine.GetData());
 	return strCmdLine.GetData();
 }
 
+
 std::string CModTools::generateCefclientCmd(bool isExtend, std::string mainUrl)
 {
 	CSimpleStringA strChromiumPath = GetCefHead(this->m_pEntity), strCmdLine = "";
@@ -255,60 +292,78 @@ std::string CModTools::generateCefclientCmd(bool isExtend, std::string mainUrl)
 	strCmdLine.Append(" --no-sandbox");
 	strCmdLine.Append(" --hide-controls");
 	strCmdLine.Append(" --always-on-top");
-	strCmdLine.Append(" --logextend=slv");
+	strCmdLine.Append(" --logextend=").Append((+PAGE_TYPE::slv)._to_string());
 	DbgEx("cmdline : %s", strCmdLine.GetData());
 
 	return strCmdLine.GetData();
 }
 
-std::pair<ErrorCodeEnum, int> CModTools::StartChromiumBrowser(){
+void CModTools::openAdPage() {
+	//get major version
+	CSystemStaticInfo sysInfo;
+	m_pEntity->GetFunction()->GetSystemStaticInfo(sysInfo);
+	auto majorVersion = sysInfo.MachineVersion.GetMajor();
+	if (majorVersion >= 5)
+	{
+		auto AdUrlRet = getAdUrl();
+		if (AdUrlRet.first)
+		{
+			auto strAdCmd = generateAdCmd(AdUrlRet.second);
+			auto openAdRet = openCef(strAdCmd);
+			if (Error_Succeed != openAdRet.first)
+				DbgEx("open Ad err!");
+		}
+		else
+			DbgEx("StartChromiumBrowser Ad url err!");
+	}
+	//open ad do not affect the result of cef open
+}
+
+
+std::pair<ErrorCodeEnum, int> CModTools::StartChromiumBrowser(ERR_PAGE_REASON reason){
 
 	g_mutexFreerdp.lock();
 	std::shared_ptr<void> delHandleFun((void*)0, [&](void*) {
 		g_mutexFreerdp.unlock();
 	});
+	static bool adOpen = false;
+	if (!adOpen) {//only open ad in first time
+		openAdPage();
+		adOpen = true;
+	}
 	
-
-	auto mainUrlRet = getMainUrl();
-
-	if (0 == mainUrlRet.second.length())
+	if (reason._to_integral() == ERR_PAGE_REASON::normal)
 	{
-		DbgEx("StartChromiumBrowser get url failed!");
-		return std::make_pair(Error_Unexpect, 0);
-	}
+		auto mainUrlRet = getMainUrl();
+
+		if (0 == mainUrlRet.second.length())
+		{
+			DbgEx("StartChromiumBrowser get url failed!");
+			return std::make_pair(Error_Unexpect, 0);
+		}
 
-	auto strCmdLine = generateCefclientCmd(mainUrlRet.first, mainUrlRet.second);
+		auto strCmdLine = generateCefclientCmd(mainUrlRet.first, mainUrlRet.second);
 
-	auto openCefRet = openCef(strCmdLine);
-	if (Error_Succeed == openCefRet.first)
+		auto openCefRet = openCef(strCmdLine);
+		if (Error_Succeed == openCefRet.first)
+			return std::make_pair(Error_Succeed, openCefRet.second);
+	}
+	else
 	{
-		//get major version
-		CSystemStaticInfo sysInfo;
-		m_pEntity->GetFunction()->GetSystemStaticInfo(sysInfo);
-		auto majorVersion = sysInfo.MachineVersion.GetMajor();
-		if (majorVersion >= 5)
+		//open err page
+		auto errPageUrl = GenerateErrPage(reason);
+		if (!errPageUrl.first)
 		{
-			auto AdUrlRet = getAdUrl();
-			if (AdUrlRet.first)
-			{
-				auto strAdCmd = generateAdCmd(AdUrlRet.second);
-				auto openAdRet = openCef(strAdCmd);
-				if (Error_Succeed != openAdRet.first)
-					DbgEx("open Ad err!");
-			}
-			else
-				DbgEx("StartChromiumBrowser Ad url err!");
+			DbgEx("errPage get url failed!");
+			return std::make_pair(Error_Unexpect, 0);
 		}
-		//open ad do not affect the result of cef open
-		return std::make_pair(Error_Succeed, openCefRet.second);
-	}
-
-	
+		auto errPageRet = openCef(errPageUrl.second);
+		return errPageRet;
 
+	}
 
-	DbgEx("Leave StartChromiumBrowser tid: %d", std::this_thread::get_id());
-	
 	return std::make_pair(Error_Unexpect, 0);
+	
 
 }
 
@@ -353,18 +408,12 @@ void CModTools::RestartProxyServer(){
 	Error = spEntityFunction->StopTcpBridgeServer();
 
 	if (Error != Error_Succeed) 
-	{
 		LOG_TRACE("stop tcp bridge server failed! error = %d", Error);
-		//		return;
-	}
 
 	Error = spEntityFunction->StartTcpBridgeServer(4504);
 
 	if (Error != Error_Succeed) 
-	{
 		LOG_TRACE("start tcp bridge server failed! error = %d", Error);
-//		return;
-	}
 	return;
 }
 

+ 21 - 8
Module/mod_chromium/CModTools.h

@@ -5,6 +5,8 @@
 #include <tuple>
 #include <mutex>
 #include "guitask/enum.h"
+#include <boost/serialization/singleton.hpp>
+using boost::serialization::singleton;
 
 #if (defined _WIN32 || defined _WIN64)
 #define CEFCLIENT_NAME		"cefclient.exe"
@@ -14,7 +16,6 @@
 
 namespace Chromium{
 
-//extern CRITICAL_SECTION g_csInvokFreeRDP;
 	BETTER_ENUM(ERR_PAGE_REASON, int, 
 		CameraConfig,
 		CardStoreIsBusy,
@@ -23,29 +24,41 @@ namespace Chromium{
 		TerminalManagerOff,
 		breakdown,
 		disabled,
-		jobuncomplete)
+		jobuncomplete,
+		normal)
+	BETTER_ENUM(PAGE_TYPE, int,
+		CameraConfig,
+		TerminalManager,
+		errPage,
+		Ad,
+		slv,
+		init)
 	
-class CModTools{
+class CModTools : public singleton<CModTools>
+{
 private:
 	CEntityBase* m_pEntity;
 public:
-	explicit CModTools(CEntityBase* pEntity);
-
-	std::pair<ErrorCodeEnum, int> StartChromiumBrowser();
-	static bool killAllChromium();	//通过taskkill 关闭掉所有的cefclient
+	void InitCModTools(CEntityBase* pEntity);
+	std::pair<ErrorCodeEnum, int> StartChromiumBrowser(ERR_PAGE_REASON reason = ERR_PAGE_REASON::normal);
+	bool killAllChromium();	//通过taskkill 关闭掉所有的cefclient
+	bool killChromiumByName(std::string name);
 	void RestartProxyServer();
 	std::pair<CSimpleStringA, int>  ReadConfig();	//读本地配置,已废弃
 	std::tuple<CSimpleStringA, CSimpleStringA, CSimpleStringA, CSimpleStringA, CSimpleStringA> ReadCenterConfigStr(CSimpleStringA entityName = "");
+	void setLimitReason(const char* reason);
 private:
 	std::pair<bool, std::string> getMainUrl();
 	std::pair<bool, std::string> getAdUrl();
+	std::pair<bool, std::string> getErrUrl();
 	std::string generateCefclientCmd(bool isExtend, std::string mainUrl);
 	std::string generateAdCmd(std::string AdUrl);
 	std::pair<ErrorCodeEnum, int> openCef(std::string cmdline);
 	void cefClientGuardian(std::string cmdline);
+	void openAdPage();
 	std::pair<bool, std::string> GenerateErrPage(ERR_PAGE_REASON errType);
-	void setLimitReason(const char* reason);
 	std::string GetSpShellBootTime();
+
 };
 
 template<class T>

+ 1 - 2
Module/mod_chromium/CSocketClient.cpp

@@ -181,8 +181,7 @@ ErrorCodeEnum CSocketClient::Reconnect()
 {
 	boost::system::error_code ec;
 	DbgEx("CSocketClient method -> reconnect thread_id = %ld, object=%ld", std::this_thread::get_id(), this);
-	CModTools modTools(this->m_pEntity);
-	modTools.RestartProxyServer();
+	CModTools::get_mutable_instance().RestartProxyServer();
 	m_psocket->connect(m_ep, ec);
 	if (ec)
 	{

+ 1 - 16
Module/mod_chromium/CWSCodec.h

@@ -7,22 +7,7 @@
 #include "cJSON.h"
 #include "baseEx.h"
 
-//      message type 
-//      Info = 0,           //info message, no response
-// 	    BeginSession = 1,   //start entity session
-// 		EndSession = 2,     //end entity session
-// 		Request = 3,        //call request
-// 		RequestAck = 4,     //request acknowledge
-// 		SessionAck = 5,     //start session acknowledge
-// 		Register = 6,       //register entity event
-// 		Unregister = 7,     //unregister entity event
-// 		Event = 8,          //event message
-// 		LogEvent = 9,       //log event
-// 		LogWarn = 10,       //log warn
-// 		SetVarReq = 11,     //set sysvar request
-// 		SetVarAck = 12,     //set sysvar response
-// 		GetVarReq = 13,     //get sysvar request
-// 		GetVarAck = 14      //get sysvar response
+
 namespace Chromium{
 typedef struct entity_def_struct{
 	char entity_name[64];

+ 1 - 1
Module/mod_chromium/guitask/guitask.cpp

@@ -72,7 +72,7 @@ bool chromiumRpcTask::openrpcServer(int port)
 	});
 
 	thd.detach();
-	Dbg("rpc start, async run");
+	//Dbg("rpc start, async run");
 	m_rpcServerWork = true;
 
 	return true;

+ 276 - 13
Module/mod_chromium/mod_chromium.cpp

@@ -18,7 +18,7 @@
 #include "path.h"
 #include "guitask/guitask.h"
 #include "EventCode.h"
-
+#include "../mod_upload/Upload_client_g.h"
 
 
 #define COMPKEY_TERMINATE ((UINT_PTR) 0)
@@ -120,8 +120,6 @@ namespace Chromium {
 	void CChromiumEntity::OnPreStart(CAutoArray<CSimpleStringA> strArgs, CSmartPointer<ITransactionContext> pTransactionContext)
 	{
 		GetFunction()->GetSystemStaticInfo(m_sysInfo);
-		// 
-			//MessageBox(0,0,0,0);
 
 		ErrorCodeEnum Error;
 		Error = GetFunction()->StartTcpBridgeServer(m_iTcpBridgePort);
@@ -141,7 +139,8 @@ namespace Chromium {
 			pTransactionContext->SendAnswer(Error);
 			return;
 		}
-		CModTools::killAllChromium();
+		CModTools::get_mutable_instance().InitCModTools(this);
+		CModTools::get_mutable_instance().killAllChromium();
 		// load all struct define xml & start websocket server
 		CSimpleStringA strStructPath;
 		GetFunction()->GetPath("Base", strStructPath);
@@ -158,20 +157,45 @@ namespace Chromium {
 			DbgEx("open rpcTask failed");
 		}
 
+		/*低柜
 		//LOG_EVT_BEGIN_CAMERA_CONFIG, LOG_EVT_END_CAMERA_CONFIG
 		Error = GetFunction()->SubscribeLog(m_uidCameraListener, this, Log_Event, Severity_None, Error_IgnoreAll, -1, "CameraConfigManage");
 		if (Error != Error_Succeed)
 			LOG_TRACE("subscribe Camera log failed!"); //非必须
-
-		Error = GetFunction()->SubscribeLog(m_uuidAccessAuth, this, Log_Event, Severity_Middle, Error_IgnoreAll, -1, "AccessAuthorization");
+			*/
+		Error = GetFunction()->SubscribeLog(m_uuidAccessAuth, this, Log_Event, Severity_None, Error_IgnoreAll, -1, "AccessAuthorization");
 		if (Error != Error_Succeed)
 			LOG_TRACE("subscribe AccessAuthorization log failed!"); 
+		else
+			LOG_TRACE("subscribe AccessAuthorization success!");
+		GetFunction()->SubscribeLog(m_uuidAccessAuth, this, Log_Error, Severity_None, Error_IgnoreAll, -1, "AccessAuthorization");
+
+		GetFunction()->RegistSysVarEvent("UIState", this);
 
+		generateBussinessLimitTimer();
 
 		// 按照单屏方式
 		pTransactionContext->SendAnswer(Error_Succeed);
 	}
 
+	void CChromiumEntity::OnSysVarEvent(const char* pszKey, const char* pszValue, const char* pszOldValue, const char* pszEntityName)
+	{
+		if ((_strnicmp(pszKey, "UIState", strlen("UIState")) == 0))
+		{
+			if (_strnicmp(pszValue, "M", strlen("M")) == 0)
+			{
+				static bool firstEnter = true;
+				if (firstEnter)
+				{
+					firstEnter = false;
+					Dbg("first Enter main page");
+				}
+			}
+
+
+		}
+	}
+
 	void CChromiumEntity::OnPreClose(EntityCloseCauseEnum eCloseCause, CSmartPointer<ITransactionContext> pTransactionContext)
 	{
 		if (m_pTimerListener != NULL)
@@ -191,10 +215,14 @@ namespace Chromium {
 		switch (dwUserCode)
 		{
 		case LOG_EVT_BEGIN_CAMERA_CONFIG:
-			Dbg("show Screen Camera config, open page cameraconfig");
+		{
+			auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::CameraConfig);
+			Dbg("show Screen Camera config, open page cameraconfig, %d", openRet.first);
+		}
 			break;
 		case LOG_EVT_END_CAMERA_CONFIG:
 			Dbg("end show Screen Camera config, close page cameraconfig");
+			CModTools::get_mutable_instance().killChromiumByName((+PAGE_TYPE::CameraConfig)._to_string());
 			break;
 		case EVENT_ACCESSAUTH_SUCCEED:
 			Dbg("access auth success, open page mainurl");
@@ -205,9 +233,12 @@ namespace Chromium {
 					generateCefclientTimer();//非--test时,才会打开浏览器
 			}
 			break;
-		case EVENT_ACCESSAUTH_FAILED:
-		case EVENT_ACCESSAUTH_TIMEOUT:
-			Dbg("access failed, open page breakdown");
+		case ERR_ACCESSAUTH_FAILED:
+		case ERR_ACCESSAUTH_TIMEOUT:
+		{
+			auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::breakdown);
+			Dbg("access failed, open page breakdown, %d", openRet.first);
+		}
 			break;
 		default:
 			break;
@@ -221,21 +252,248 @@ namespace Chromium {
 		{
 		case 0:
 			GetFunction()->SetSysVar("TerminalManagerState", "L", true);
+			{
+				auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::TerminalManagerOff);
+				Dbg("TerminalManagerState L, open page TerminalManagerOff, %d", openRet.first);
+			}
 			break;
 		case 1:
 			GetFunction()->SetSysVar("TerminalManagerState", "N", true);
+			{
+				Dbg("TerminalManagerState N, try close TerminalManager");
+				CModTools::get_mutable_instance().killChromiumByName((+PAGE_TYPE::TerminalManager)._to_string());
+			}
 			break;
 		case 2:
 			GetFunction()->SetSysVar("TerminalManagerState", "K", true);
+			{
+				auto openRet = CModTools::get_mutable_instance().StartChromiumBrowser(ERR_PAGE_REASON::TerminalManagerKickOut);
+				Dbg("TerminalManagerState K, open page TerminalManagerKickOut, %d", openRet.first);
+			}
 			break;
 		case 99:
 			GetFunction()->SetSysVar("TerminalManagerState", "N", true);
+			{
+				Dbg("TerminalManagerState N, try close TerminalManager");
+				CModTools::get_mutable_instance().killChromiumByName((+PAGE_TYPE::TerminalManager)._to_string());
+			}
 			break;
 		default:
 			break;
 		}
 	}
 
+	// 输入为北京时间 输出为北京时间戳
+	int CChromiumEntity::StandardToStamp(const char* str_time, bool dateOnly)
+	{
+		Dbg("StandardToStamp str = %s", str_time);
+		struct tm stm;
+		int iY, iM, iD, iH, iMin, iS;
+
+		// 检查有效性
+		if ('-' != str_time[4] || '-' != str_time[7])
+		{
+			return 0;
+		}
+
+		memset(&stm, 0, sizeof(stm));
+		iY = atoi(str_time);
+		iM = atoi(str_time + 5);
+		iD = atoi(str_time + 8);
+		if (dateOnly)
+		{
+			iH = 0;
+			iMin = 0;
+			iS = 0;
+		}
+		else {
+			iH = atoi(str_time + 11);
+			iMin = atoi(str_time + 14);
+			iS = atoi(str_time + 17);
+		}
+
+		stm.tm_year = iY - 1900;
+		stm.tm_mon = iM - 1;
+		stm.tm_mday = iD;
+		stm.tm_hour = iH;
+		stm.tm_min = iMin;
+		stm.tm_sec = iS;
+
+		/*printf("%d-%0d-%0d %0d:%0d:%0d\n", iY, iM, iD, iH, iMin, iS);*/   //标准时间格式例如:2016:08:02 12:12:30
+		return (int)mktime(&stm);
+	}
+
+	TradeManageCodeEnum CChromiumEntity::CheckJobLimited() {
+		/*if (!isOutsidePad())
+		{
+			return Undefined;
+		}*/
+		CSmartPointer<IConfigInfo> spConfig;
+		ErrorCodeEnum BootTimeCfgError = GetFunction()->OpenConfig(Config_Run, spConfig);
+		CSimpleStringA strLastRecordTime = "", strControl = "", strExpirationDate = "";
+		time_t now = time(0);
+		localtime(&now);
+		ErrorCodeEnum errorRead = Error_Succeed;
+		errorRead = spConfig->ReadConfigValue("Record", "LastRecordTime", strLastRecordTime);
+		if (errorRead != Error_Succeed)
+		{
+			Dbg("Read Record LastRecordTime -> Failed! Maybe LastRecordTime not exist!");
+			strLastRecordTime = "";
+		}
+
+		errorRead = spConfig->ReadConfigValue("Record", "Control", strControl);
+		if (errorRead != Error_Succeed)
+		{
+			Dbg("Read Record Control -> Failed! Maybe Control not exist!");
+			strControl = "";
+		}
+
+		errorRead = spConfig->ReadConfigValue("Record", "ExpirationDate", strExpirationDate);
+		if (errorRead != Error_Succeed)
+		{
+			Dbg("Read Record ExpirationDate -> Failed! Maybe ExpirationDate not exist!");
+			strExpirationDate = "";
+		}
+		if (strControl.Compare("on") == 0)
+		{
+			// 控制标识为on时,检查过期时间,过期时间之前都设置为启用
+			if (strExpirationDate == "")
+			{
+				Dbg("CheckJobLimited -> on -> strExpirationDate=null ");
+				CModTools::get_mutable_instance().setLimitReason("");
+				return TradeManageCodeEnum::Trade;
+			}
+			int timestamp_expiration = StandardToStamp(strExpirationDate.Append(" 23:59:59"), false);
+
+			if (now < timestamp_expiration)
+			{
+				// 过期之前都可以进行交易
+				Dbg("CheckJobLimited -> on -> strExpirationDate>now ");
+				CModTools::get_mutable_instance().setLimitReason("");
+				return TradeManageCodeEnum::Trade;
+			}
+			else {
+				// 过期之后 设置为normal
+				Dbg("CheckJobLimited -> on -> strExpirationDate<now -> control to normal");
+				spConfig->WriteConfigValue("Record", "Control", "normal");
+				strControl = "normal";
+				Dbg("过期之后 设置为normal");
+			}
+		}
+
+		if (strControl.Compare("off") == 0)
+		{
+			// 展示交易暂停页面
+			Dbg("CheckJobLimited -> off ");
+			CModTools::get_mutable_instance().setLimitReason("disabled");
+			return TradeManageCodeEnum::Disabled;
+		}
+
+		if (strControl.Compare("normal") == 0 || strControl.IsNullOrEmpty())
+		{
+			if (strLastRecordTime == "")
+			{
+				Dbg("CheckJobLimited -> normal -> strLastRecordTime=null ");
+				CModTools::get_mutable_instance().setLimitReason("");
+				return TradeManageCodeEnum::Trade;
+			}
+			int timestamp_lastRecordTime = StandardToStamp(strLastRecordTime, true);
+
+			if (now < timestamp_lastRecordTime + 3600 * 24 * 2)
+			{
+				Dbg("CheckJobLimited -> normal -> now < lastRecordTime + 3600*24*2 ");
+				CModTools::get_mutable_instance().setLimitReason("");
+				return TradeManageCodeEnum::Trade;
+			}
+			else if (CheckTradeRecord()) {
+				// 展示交易暂停页面
+				Dbg("CheckJobLimited -> normal -> now < CheckTradeRecord = true ");
+				CModTools::get_mutable_instance().setLimitReason("jobuncomplete");
+				return TradeManageCodeEnum::JobUncomplete;
+			}
+		}
+		// 理论上不会流转到这里来
+		CModTools::get_mutable_instance().setLimitReason("");
+		return TradeManageCodeEnum::Trade;
+	}
+
+	bool CChromiumEntity::CheckTradeRecord() {
+		std::list<int> timeList;
+
+		using namespace Upload;
+		UploadService_ClientBase* pClient = new UploadService_ClientBase(this);
+		auto rc = pClient->Connect();
+		if (rc != Error_Succeed)
+		{
+			Dbg("connect to Upload entity fail: %d", rc);
+		}
+		else
+		{
+			UploadService_UploadDateList_Req req = {};
+			UploadService_UploadDateList_Ans ans = {};
+
+			rc = pClient->UploadDateList(req, ans, 10000);
+
+			if (rc != Error_Succeed)
+			{
+				Dbg("UploadDateList fail from Upload: %d", rc);
+			}
+			else
+			{
+				Dbg("UploadDateList succeed from Upload");
+				for (int i = 0; i < ans.uploadDateStr.GetCount(); ++i)
+				{
+					CSimpleStringA str = (CSimpleStringA)ans.uploadDateStr[i];
+					int t = StandardToStamp(ans.uploadDateStr[i], true);
+					timeList.push_back(t);
+				}
+			}
+
+			pClient->SafeDelete();
+			pClient = NULL;
+		}
+
+		// 比较时间戳 登记时间 <= 列表时间 < 今天 返回true
+		time_t now = time(0);
+		localtime(&now);
+		now -= now % (3600 * 24);
+		now -= 3600 * 8; //处理东八区问题
+		CSmartPointer<IEntityFunction> spFunction = GetFunction();
+		CSmartPointer<IConfigInfo> spConfig;
+		ErrorCodeEnum BootTimeCfgError = spFunction->OpenConfig(Config_Run, spConfig);
+		CSimpleStringA strLastRecordTime = "";
+		ErrorCodeEnum errorRead = Error_Succeed;
+		errorRead = spConfig->ReadConfigValue("Record", "LastRecordTime", strLastRecordTime);
+		if (errorRead != Error_Succeed)
+		{
+			Dbg("Read Record LastRecordTime -> Failed! Maybe LastRecordTime not exist!");
+			strLastRecordTime = "";
+		}
+
+		int timestamp_lastRecordTime = now;
+		if (!strLastRecordTime.IsNullOrEmpty())
+		{
+			timestamp_lastRecordTime = StandardToStamp(strLastRecordTime, false);
+		}
+		for (std::list<int>::iterator it = timeList.begin(); it != timeList.end(); ++it)
+		{
+			if (timestamp_lastRecordTime <= *it && *it < now)
+			{
+				Dbg("CheckTradeRecord lastRecordTime=%d, time_list=%d, now=%d", timestamp_lastRecordTime, *it, now);
+				return true;
+			}
+		}
+		return false;
+	}
+
+	void CChromiumEntity::OnBusinessLimitTimerListener(void* pData)
+	{
+		Dbg("定时任务检查业务禁用");
+		// 检查是否禁用业务
+		//ShowLimitScreen();
+		GetFunction()->ResetTimer(BROWSER_TIMER_ID, BROWSER_TIMER_INTERVAL);
+	}
+
 	void CChromiumEntity::CefClintNotify()
 	{
 #if(defined _WIN32 || defined _WIN64)
@@ -364,11 +622,16 @@ namespace Chromium {
 		GetFunction()->SetTimer(CHROMIUM_TIMER_ID, m_pTimerListener, 3000);	//间隔执行时间
 	}
 
+	void CChromiumEntity::generateBussinessLimitTimer() {
+		DbgEx("Start BusinessLimitTimer");
+		pBusinessLimitTimerListener = new TimerOutHelper<CChromiumEntity>(this, &CChromiumEntity::OnBusinessLimitTimerListener, NULL, false);
+		GetFunction()->SetTimer(BROWSER_TIMER_ID, pBusinessLimitTimerListener, 5000);
+	}
+
 
 	void CChromiumEntity::OnTaskTimerListener(void* pData)
 	{
 		static int max_restartTime = 3;
-		static CModTools modTools(this);
 		DbgEx("OnTaskTimerListener");
 		if (max_restartTime == 0)
 		{
@@ -380,9 +643,9 @@ namespace Chromium {
 
 		//基于Desk2S功能判断,当当前并未启动cefclient时,对cefclient.exe进行清理
 		if (0 == m_cefArr.size())
-			DbgEx("kill chromium %s", modTools.killAllChromium() ? "success" : "fail");
+			DbgEx("kill chromium %s", CModTools::get_mutable_instance().killAllChromium() ? "success" : "fail");
 
-		auto rc = modTools.StartChromiumBrowser();
+		auto rc = CModTools::get_mutable_instance().StartChromiumBrowser();
 		max_restartTime--;
 		DbgEx("TaskTimerListen, startChromiumBrowser, rc:%d, pid:%d", rc.first, rc.second);
 		if (0 == rc.first)

+ 29 - 3
Module/mod_chromium/mod_chromium.h

@@ -12,7 +12,7 @@
 #include "..\\mod_browser\\IEBrowser_msg_g.h"
 #endif
 
-
+#include "guitask/enum.h"
 #include "../mod_healthmanager/HealthManager_msg_g.h"
 
 #define SP_MSG_HANDLE_NS_EX(ns, msg, ns_msg, OnMsg) \
@@ -27,9 +27,27 @@
 				} \
 				break;
 
+
+
+
 #pragma once
 namespace Chromium {
-	class CChromiumEntity : public CEntityBase, public ILogListener, public IBroadcastListener
+	BETTER_ENUM(TradeManageCodeEnum, int,
+		Undefined,
+		Trade,
+		JobUncomplete,
+		Disabled)
+
+	BETTER_ENUM(TerminalManageCodeEnum, int,
+		Off,
+		On,
+		KickOut)
+
+#define BROWSER_TIMER_ID 0xF001
+#define BROWSER_TIMER_INTERVAL 3600000
+
+
+	class CChromiumEntity : public CEntityBase, public ILogListener, public IBroadcastListener, public ISysVarListener
 	{
 	public:
 		CChromiumEntity();
@@ -48,10 +66,11 @@ namespace Chromium {
 		void OnCustomerCmd(const char* pszEntityName, DWORD dwMessageId, DWORD dwMessageSignature, IEBrowser::CustomerCmd& evt);
 #endif
 		void generateCefclientTimer();
+		void generateBussinessLimitTimer();
 	private:
 		CSystemStaticInfo m_sysInfo;
 		CWebsocketServer* m_pWsServer;
-		ITimerListener* m_pTimerListener;
+		ITimerListener *m_pTimerListener, * pBusinessLimitTimerListener;//浏览器监控Timer,业务禁用Timer
 		int m_iTcpBridgePort;
 		std::map<std::string, std::tuple<HANDLE, HANDLE, std::string>> m_cefArr;//open discribe: slv, job Handle, process Handle, cmdline
 		HANDLE m_hIOCP;
@@ -64,8 +83,15 @@ namespace Chromium {
 			const DWORD dwSysError, const DWORD dwUserCode, const DWORD dwEntityInstanceID, const WORD wEntityDevelID,
 			const CAutoArray<DWORD>& Param, const char* pszEntityName, const char* pszModuleName, const char* pszMessage);
 
+		virtual void OnSysVarEvent(const char* pszKey, const char* pszValue, const char* pszOldValue, const char* pszEntityName);
+
 		void OnTerminalManage(const char* pszEntityName, DWORD dwMessageId, DWORD dwMessageSignature, HealthManager::TerminalManager& evt);//终端锁定罚出
 
+		TradeManageCodeEnum CheckJobLimited();
+		int StandardToStamp(const char* str_time, bool dateOnly);
+		void OnBusinessLimitTimerListener(void* pData);//每3600s检测业务禁用
+		bool CheckTradeRecord();
+
 
 		SP_BEGIN_MSG_DISPATCH_MAP(CChromiumEntity)
 #if (defined _WIN32 || defined _WIN64)

+ 0 - 377
Module/mod_localmediaplay/AdvertManage/BaseFun.cpp

@@ -379,380 +379,3 @@ bool getUniqueDir(string path, string &dirName)
 	}
 	return false;
 }
-
-
-
-UINT GetPrivateProfileIntEx(LPCSTR lpAppName,LPCSTR lpKeyName,INT nDefault,LPCSTR lpFileName)
-{
-	char lpReturnedString[MAX_PATH] = { 0 };
-	DWORD nRet = GetPrivateProfileStringEx(
-		lpAppName,
-		lpKeyName,
-		"",
-		lpReturnedString,
-		sizeof(lpReturnedString),
-		lpFileName
-	);
-
-	if (nRet == 0) {
-		return nDefault;
-	}
-		
-	return atoi(lpReturnedString);
-}
-
-BOOL WritePrivateProfileStringEx(LPCSTR lpAppName,LPCSTR lpKeyName,LPCSTR lpString,LPCSTR lpFileName)
-{
-	FILE* fp = NULL;
-	static char szLine[RVC_MAX_INI_LEN] = { 0 };
-	static char tmpstr[RVC_MAX_INI_LEN] = { 0 };
-	memset(szLine, 0, sizeof(szLine));
-	memset(tmpstr, 0, sizeof(tmpstr));
-	int rtnval;
-	int i = 0;
-	int secFlag = 0;
-
-	if ((fp = fopen(lpFileName, "rw+")) == NULL){
-		return FALSE;
-	}
-
-	int lineLen = 0;//整行长度      
-	int orgEqualPos = 0;//=号在原行中的位置
-	int equalPos = 0; //=号在去空格后的位置
-	strcpy(tmpstr, "[");
-	strcat(tmpstr, lpAppName);
-	strcat(tmpstr, "]");
-	int endFlag;
-	while (!feof(fp))
-	{
-
-		rtnval = fgetc(fp);
-		if (rtnval == EOF){
-			//最后一行可能无换行符号   	
-			rtnval = '\n';
-			endFlag = 1;
-		}
-		//注释行    
-		if ('#' == rtnval || ';' == rtnval)
-		{
-			fgets(szLine, sizeof(szLine), fp);
-			//reset 
-			i = 0;
-			lineLen = 0;
-			orgEqualPos = 0;
-			equalPos = 0;
-			memset(szLine, 0, sizeof(szLine));
-			continue;
-		}
-		else if ('/' == rtnval)
-		{
-			szLine[i++] = rtnval;
-			lineLen++;
-			if ('/' == (rtnval = fgetc(fp))) //注释行
-			{
-				fgets(szLine, sizeof(szLine), fp);
-				//reset 
-				i = 0;
-				lineLen = 0;
-				orgEqualPos = 0;
-				equalPos = 0;
-				memset(szLine, 0, sizeof(szLine));
-				continue;
-			}
-		}
-
-		if (rtnval != ' ' && rtnval != '\t')
-		{
-			szLine[i++] = rtnval;   //去掉空格和tab后的字符串
-			if (rtnval == '=')
-			{
-				orgEqualPos = lineLen;
-				equalPos = i - 1;
-			}
-
-		}
-
-		lineLen++; //字符
-
-		if (rtnval == '\n'){
-			szLine[--i] = '\0';
-			if (szLine[--i] == '\r')
-				szLine[i--] = '\0';
-
-			if ((equalPos != 0) && (secFlag == 1))
-			{
-				szLine[equalPos] = '\0';
-				if (strcasecmp(szLine, lpKeyName) == 0)
-				{
-					//找到key对应变量
-					int leftPos = ftell(fp);
-					int writePos = leftPos - lineLen + orgEqualPos + 1;
-					fseek(fp, 0, SEEK_END);
-					int leftLen = ftell(fp) - leftPos;
-					char* pLeft = new char[leftLen];
-					fseek(fp, leftPos, SEEK_SET);
-					fread(pLeft, leftLen, 1, fp);
-					fseek(fp, writePos, SEEK_SET);
-					fwrite(lpString, strlen(lpString), 1, fp);
-					fwrite("\n", sizeof(char), 1, fp);
-					fwrite(pLeft, leftLen, 1, fp);
-					delete[]pLeft;
-					pLeft = 0;
-					fclose(fp);
-					return TRUE;
-				}
-			}
-
-			else
-			{
-				if (strcasecmp(tmpstr, szLine) == 0)
-				{
-					//找到section    
-					secFlag = 1;
-				}
-				else if (secFlag == 1 && szLine[0] == '[' && szLine[i] == ']')
-				{//进入下个section了,说明没找到
-					int leftPos = ftell(fp) - lineLen;
-					int writePos = leftPos;
-					fseek(fp, 0, SEEK_END);
-					int leftLen = ftell(fp) - leftPos;
-					char* pLeft = new char[leftLen];
-					fseek(fp, leftPos, SEEK_SET);
-					fread(pLeft, leftLen, 1, fp);
-					fseek(fp, writePos, SEEK_SET);
-					fwrite("\n", sizeof(char), 1, fp);
-					fwrite(lpKeyName, strlen(lpKeyName), 1, fp);
-					fwrite("=", sizeof(char), 1, fp);
-					fwrite(lpString, strlen(lpString), 1, fp);
-					fwrite("\n", sizeof(char), 1, fp);
-					fwrite(pLeft, leftLen, 1, fp);
-					delete[]pLeft;
-					pLeft = 0;
-					fclose(fp);
-					return TRUE;
-				}
-			}
-			//reset 
-			if (endFlag == 1)
-				break;
-			i = 0;
-			lineLen = 0;
-			orgEqualPos = 0;
-			equalPos = 0;
-			memset(szLine, 0, sizeof(szLine));
-		}
-	}
-	//到文件尾了	
-	if (secFlag)
-	{//必须有section
-		fseek(fp, 0, SEEK_END);
-		fwrite("\n", sizeof(char), 1, fp);
-		fwrite(lpKeyName, strlen(lpKeyName), 1, fp);
-		fwrite("=", sizeof(char), 1, fp);
-		fwrite(lpString, strlen(lpString), 1, fp);
-		fwrite("\n", sizeof(char), 1, fp);
-	}
-	fclose(fp);
-	return TRUE;
-}
-
-DWORD GetPrivateProfileStringEx(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName)
-{
-	FILE* fp = NULL;
-	static char szLine[RVC_MAX_INI_LEN] = { 0 };
-	static char tmpstr[RVC_MAX_INI_LEN] = { 0 };
-	int rtnval;
-	int i = 0;
-	int secFlag = 0;
-
-	if ((fp = fopen(lpFileName, "r")) == NULL){
-		Dbg("have no such file[%s]", lpFileName);
-		return -1;
-	}
-
-	int equalPos = 0; //=号在去空格后的位置
-	strcpy(tmpstr, "[");
-	strcat(tmpstr, lpAppName);
-	strcat(tmpstr, "]");
-	int endFlag = 0;
-	while (!feof(fp))
-	{
-		rtnval = fgetc(fp);
-		if (rtnval == EOF){
-			//最后一行可能无换行符号     	
-			rtnval = '\n';
-			endFlag = 1;
-		}
-		//注释行    
-		if ('#' == rtnval || ';' == rtnval)
-		{
-			fgets(szLine, sizeof(szLine), fp);
-			//reset 
-			i = 0;
-			equalPos = 0;
-			memset(szLine, 0, sizeof(szLine));
-			continue;
-		}
-		else if ('/' == rtnval)
-		{
-			szLine[i++] = rtnval;
-			if ('/' == (rtnval = fgetc(fp))) //注释行
-			{
-				fgets(szLine, sizeof(szLine), fp);
-				//reset 
-				i = 0;
-				equalPos = 0;
-				memset(szLine, 0, sizeof(szLine));
-				continue;
-			}
-		}
-
-		if (rtnval != ' ' && rtnval != '\t')
-		{
-			szLine[i++] = rtnval;   //去掉空格和tab后的字符串
-			if (rtnval == '=')
-			{
-				equalPos = i - 1;
-			}
-		}
-
-		if (rtnval == '\n'){
-			szLine[--i] = '\0';
-
-			if (szLine[--i] == '\r')
-				szLine[i--] = '\0';
-
-			if ((equalPos != 0) && (secFlag == 1))
-			{
-				szLine[equalPos] = '\0'; //=号变0
-				if (strcasecmp(szLine, lpKeyName) == 0)
-				{
-					//找到key对应变量 
-					strncpy(lpReturnedString, szLine + equalPos + 1, nSize - 1);
-					lpReturnedString[nSize - 1] = '\0';
-					fclose(fp);
-					return 1;
-				}
-			}
-			else
-			{
-				if (strcasecmp(tmpstr, szLine) == 0)
-				{
-					//找到section    
-					secFlag = 1;
-				}
-				else if (secFlag == 1 && szLine[0] == '[' && szLine[i] == ']')
-				{//进入下个section了,说明没找到
-					break;
-				}
-			}
-
-			if (endFlag == 1)
-				break;
-			//reset 
-			i = 0;
-			equalPos = 0;
-			memset(szLine, 0, sizeof(szLine));
-
-		}
-	}
-	fclose(fp);
-	//没找到则用默认
-	strncpy(lpReturnedString, lpDefault, nSize - 1);
-	lpReturnedString[nSize - 1] = '\0';
-
-	return 0;
-}
-
-
-DWORD GetPrivateProfileSectionEx(LPCSTR lpAppName, LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName)
-{
-	//由于项目中未使用,暂未实现
-	assert(0);
-	return 0;
-}
-
-
-DWORD GetPrivateProfileSectionNamesEx(LPSTR lpszReturnBuffer, DWORD nSize, LPCSTR lpFileName)
-{
-	FILE* fp = NULL;
-	static char szLine[RVC_MAX_INI_LEN] = { 0 };
-	static char tmpstr[RVC_MAX_INI_LEN] = { 0 };
-	int rPos = 0;
-
-	memset(lpszReturnBuffer, 0, nSize);
-	int rtnval;
-	int i = 0;
-	int endFlag;
-
-	if ((fp = fopen(lpFileName, "r")) == NULL){
-		return -1;
-	}
-
-	while (!feof(fp))
-	{
-		rtnval = fgetc(fp);
-		if (rtnval == EOF){
-			//最后一行可能无换行符号    	
-			rtnval = '\n';
-			endFlag = 1;
-		}
-		//注释行    
-		if ('#' == rtnval || ';' == rtnval)
-		{
-			fgets(szLine, sizeof(szLine), fp);
-			//reset 
-			i = 0;
-			memset(szLine, 0, sizeof(szLine));
-			continue;
-		}
-		else if ('/' == rtnval)
-		{
-			szLine[i++] = rtnval;
-			if ('/' == (rtnval = fgetc(fp))) //注释行
-			{
-				fgets(szLine, sizeof(szLine), fp);
-				//reset 
-				i = 0;
-				memset(szLine, 0, sizeof(szLine));
-				continue;
-			}
-		}
-
-		if (rtnval != ' ' && rtnval != '\t')
-		{
-			szLine[i++] = rtnval;   //去掉空格和tab后的字符串
-
-		}
-
-		if (rtnval == '\n')
-		{
-			szLine[--i] = '\0';
-			if (szLine[--i] == '\r')
-				szLine[i--] = '\0';
-
-			if (szLine[0] == '[' && szLine[i] == ']')
-			{
-				//找到section    
-				for (int j = 1; j < i && rPos < nSize - 1; j++)
-					lpszReturnBuffer[rPos++] = szLine[j];
-				lpszReturnBuffer[rPos++] = '\0';
-				if (rPos >= nSize)
-				{
-					break;
-				}
-			}
-
-			if (endFlag == 1)
-				break;
-
-			//reset 
-			i = 0;
-			memset(szLine, 0, sizeof(szLine));
-
-		}
-	}
-	lpszReturnBuffer[rPos] = '\0';
-	fclose(fp);
-	return 0;
-}

+ 0 - 41
Module/mod_localmediaplay/AdvertManage/BaseFun.h

@@ -21,44 +21,3 @@ void Wchar_tToString(std::string& szDst, wchar_t *wchar);
 void StringToWstring(std::wstring& szDst, std::string str);
 void stopForDebug();
 bool getUniqueDir(string path, string &dirName);//获取路径中唯一的一个文件夹名,失败返回false
-
-
-UINT
-GetPrivateProfileIntEx(
-	LPCSTR lpAppName,
-	LPCSTR lpKeyName,
-	INT nDefault,
-	LPCSTR lpFileName
-);
-
-BOOL
-WritePrivateProfileStringEx(
-	LPCSTR lpAppName,
-	LPCSTR lpKeyName,
-	LPCSTR lpString,
-	LPCSTR lpFileName
-);
-DWORD
-GetPrivateProfileStringEx(
-	LPCSTR lpAppName,
-	LPCSTR lpKeyName,
-	LPCSTR lpDefault,
-	LPSTR lpReturnedString,
-	DWORD nSize,
-	LPCSTR lpFileName
-);
-
-DWORD
-GetPrivateProfileSectionEx(
-	LPCSTR lpAppName,
-	LPSTR lpReturnedString,
-	DWORD nSize,
-	LPCSTR lpFileName
-);
-
-DWORD
-GetPrivateProfileSectionNamesEx(
-	LPSTR lpszReturnBuffer,
-	DWORD nSize,
-	LPCSTR lpFileName
-);

+ 6 - 1
Module/mod_mediacontroller/CMakeLists.txt

@@ -90,6 +90,7 @@ endif(WIN32)
 
 if(WIN32)
 conan_cmake_run(REQUIRES apache-apr/1.4.2@LR04.02_ThirdParty/testing
+lib8k/1.0@LR04.02_ThirdParty/testing
 BASIC_SETUP CMAKE_TARGETS
 BUILD missing)
 else(WIN32)
@@ -117,18 +118,22 @@ target_link_directories(${MODULE_NAME} PRIVATE
 	${CONAN_LIB_DIRS_SPEEXDSP}
 	if(WIN32)
 	${CONAN_LIB_DIRS_IPP}
+	${CONAN_LIB_DIRS_APACHE-APR}
+	${CONAN_LIB_DIRS_LIB8K}
 	else
 	${CONAN_LIB_DIRS_APR}
 	endif(WIN32)
 )
 
-
+message(STATUS "CONAN_PKG_LIBS_APACHE-APR = ${CONAN_PKG_LIBS_APACHE-APR}")
 # 添加实体需要依赖的其他共享库(包括系统库)
 if(WIN32)
 set(${MODULE_PREFIX}_LIBS  ${MODULE_BASE_LIBS} 
 	${CONAN_PKG_LIBS_IPP}
 	${CONAN_PKG_LIBS_PORTAUDIO}
 	${CONAN_PKG_LIBS_FFMPEG}
+	${CONAN_PKG_LIBS_APACHE-APR}
+	${CONAN_PKG_LIBS_LIB8K}
 	ws2_32
 	strmiids
 	winmm

+ 0 - 13
Other/libaudioframework/CMakeLists.txt

@@ -322,19 +322,6 @@ endif(WIN32)
 
 target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS})  
 
-if(MSVC)
-	install(TARGETS ${MODULE_NAME} 
-    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}" COMPONENT libraries
-    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT develops EXCLUDE_FROM_ALL
-    LIBRARY DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT libraries
-    )
-else(MSVC)
-install(TARGETS ${MODULE_NAME} 
-    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}"
-    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}"
-    LIBRARY DESTINATION "${RVC_RUNTIME_PATH}"
-    COMPONENT libraries)
-endif(MSVC)
 
 if(MSVC)
 set(OTHER_CONAN_DEP_LIBS ${OTHER_CONAN_DEP_LIBS} ${CONAN_BIN_DIRS} PARENT_SCOPE)

+ 4 - 4
Other/libaudioframework/audiocontext.c

@@ -2,6 +2,7 @@
 #include "audiocontext.h"
 #include "audiostream.h"
 #include "audiodriver.h"
+#include "audiolog.h"
 
 #ifdef _WIN32
 #else
@@ -55,7 +56,9 @@ static void *APR_THREAD_FUNC audiocontext_run(apr_thread_t *thread_handle, void
 #ifdef _WIN32
 		WaitForSingleObject(ctx->sem, INFINITE);
 #else
+		audio_log_v(AUDIO_LOG_LEVEL_INFO, "before sem_wait......");
 		sem_wait(ctx->sem);
+		audio_log_v(AUDIO_LOG_LEVEL_INFO, "after sem_wait......");
 #endif // _WIN32
 		if (!ctx->bstop) {
 			int i;
@@ -63,6 +66,7 @@ static void *APR_THREAD_FUNC audiocontext_run(apr_thread_t *thread_handle, void
 			//OutputDebugStringA("enter lock");
 			for (i = 0; i < ctx->arr_drv->nelts; ++i) {
 				audiodriver_t *drv = APR_ARRAY_IDX(ctx->arr_drv, i, audiodriver_t*);
+				//ÔÝʱÆÁ±ÎrtpÁ÷·¢Ë͹¦ÄÜ
 				drv->vtbl->process_frame(drv);
 			}
 			while (ctx->event_list_cnt > 0) {
@@ -113,10 +117,6 @@ apr_status_t audiocontext_create(apr_pool_t *pool, audioengine_t *e, audiocontex
 	if (ctx->sem){
 		int ivalue = -1;
 		sem_getvalue(ctx->sem, &ivalue);
-		printf("%s:%d sem_init success, and sem value is %d.\n", __FUNCTION__, __LINE__, ivalue);
-	}
-	else {
-		printf("%s:%d sem_init failed for %s.\n", __FUNCTION__, __LINE__, strerror(errno));
 	}
 #endif // _WIN32
 	if (!ctx->sem) {

+ 1 - 0
Other/libaudioframework/audioengine.c

@@ -74,6 +74,7 @@ static void engine_on_clock(audioengine_t *e)
 		for (i = 0; i < e->arr_ctx->nelts; ++i) {
 			audiocontext_t *ctx = APR_ARRAY_IDX(e->arr_ctx, i, audiocontext_t*);
 			audiocontext_signal(ctx);
+			audio_log_v(AUDIO_LOG_LEVEL_INFO, "audiocontext_signal ********");
 		}
 	}
 	apr_thread_mutex_unlock(e->mtx);

+ 6 - 0
Other/libaudioframework/audiomicspk2.h

@@ -7,6 +7,12 @@
 extern "C" {
 #endif
 
+#define AMS_OPT_RECORD		0x01
+#define AMS_OPT_PLAY		0x02
+#define AMS_OPT_RECPLAY		0x03
+#define AMS_OPT_AS_STREAM	0x00
+#define AMS_OPT_AS_ENGINE	0x04
+
 #include "audiostream.h"
 
 typedef struct audiomicspk2_t audiomicspk2_t;

+ 117 - 46
Other/libaudioframework/audiomicspklinux.c

@@ -1,4 +1,3 @@
-#include "precompile.h"
 #include "audiomicspklinux.h"
 #include "audiocontext.h"
 #include "audiolog.h"
@@ -7,8 +6,11 @@
 #include <portaudio.h>
 #include <assert.h>
 #include <speex/speex_resampler.h>
+#include <time.h>
+
 
 #define MAX_DELAY			60
+#define CLOCK_PERIOD		20
 
 static int get_device_index(int indev, const char* key)
 {
@@ -39,20 +41,21 @@ static int outStreamCallback(const void* input,
 	apr_status_t status;
 
 	if (output) {
-		unsigned nsamples_req = frameCount;
-		if (micspk->ply_buf_cnt == 0 && nsamples_req == micspk->capture_frame_samples) {
-			SHORT data[160];
-			spx_uint32_t in_len = micspk->frame_samples;
-			spx_uint32_t out_len = micspk->capture_frame_samples;
-			delay_buf_get((delay_buf*)micspk->ply_dbuf, data);
-			if (micspk->user_data)
-			{
-				micspk->on_rx_audio((char*)data, micspk->user_data);
-			}
-			//speex_resampler_process_int((SpeexResamplerState*)micspk->output_resample_state, 0,
-			//	data, &in_len, (spx_int16_t*)output, &out_len);
-			memcpy(output, data, in_len*sizeof(float));
-		}
+		//unsigned nsamples_req = frameCount;
+		//if (micspk->ply_buf_cnt == 0 && nsamples_req == micspk->capture_frame_samples) {
+		//	SHORT data[160];
+		//	spx_uint32_t in_len = micspk->frame_samples;
+		//	spx_uint32_t out_len = micspk->capture_frame_samples;
+		//	delay_buf_get((delay_buf*)micspk->ply_dbuf, data);
+		//	if (micspk->user_data)
+		//	{
+		//		micspk->on_rx_audio((char*)data, micspk->user_data);
+		//	}
+		//	//speex_resampler_process_int((SpeexResamplerState*)micspk->output_resample_state, 0,
+		//	//	data, &in_len, (spx_int16_t*)output, &out_len);
+		//	memcpy(output, data, in_len*sizeof(float));
+		//}
+		audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio speaker outStreamCallback.");
 	}
 	return paContinue;
 }
@@ -74,19 +77,20 @@ static int inStreamCallback(const void* input,
 		}
 		else {
 			unsigned long nsamples = frameCount + micspk->rec_buf_cnt;
-			while (nsamples >= micspk->frame_samples) {
-				unsigned chunk_count = micspk->frame_samples - micspk->rec_buf_cnt;
-				memcpy(micspk->rec_buf + micspk->rec_buf_cnt, input, chunk_count << 1);
-				input = (const short*)input + chunk_count;
-				delay_buf_put(micspk->rec_dbuf, micspk->rec_buf);
-				micspk->rec_buf_cnt = 0;
-				nsamples -= micspk->frame_samples;
-			}
-			if (nsamples > 0) {
-				memcpy(micspk->rec_buf + micspk->rec_buf_cnt, input, nsamples << 1);
-				micspk->rec_buf_cnt += nsamples;
-			}
+			//while (nsamples >= micspk->frame_samples) {
+			//	unsigned chunk_count = micspk->frame_samples - micspk->rec_buf_cnt;
+			//	memcpy(micspk->rec_buf + micspk->rec_buf_cnt, input, chunk_count << 1);
+			//	input = (const short*)input + chunk_count;
+			//	delay_buf_put(micspk->rec_dbuf, micspk->rec_buf);
+			//	micspk->rec_buf_cnt = 0;
+			//	nsamples -= micspk->frame_samples;
+			//}
+			//if (nsamples > 0) {
+			//	memcpy(micspk->rec_buf + micspk->rec_buf_cnt, input, nsamples << 1);
+			//	micspk->rec_buf_cnt += nsamples;
+			//}
 		}
+		audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micro inStreamCallback.");
 	}
 	
 	return paContinue;
@@ -125,6 +129,8 @@ static audiostream_vtbl_t g_stream_vtbl = {
 
 void audiomicspklinux_destroy(audiomicspklinux_t* micspk)
 {
+	sem_post(micspk->audio_device_started_sem);
+
 	if (micspk->ply_stream) {
 		Pa_AbortStream(micspk->ply_stream);
 		Pa_CloseStream(micspk->ply_stream);
@@ -142,6 +148,7 @@ void audiomicspklinux_destroy(audiomicspklinux_t* micspk)
 	if (micspk->opt & AMS_OPT_AS_ENGINE) {
 		//DeleteCriticalSection(&micspk->engine_lock);
 	}
+	sem_destroy(micspk->audio_device_started_sem);
 }
 
 static int initialize_speaker(audiomicspklinux_t* micspk)
@@ -170,7 +177,7 @@ static int initialize_speaker(audiomicspklinux_t* micspk)
 	}
 	audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micspk create success! audio output device defaultSampleRate is %f", info->defaultSampleRate);
 
-	UINT32 capture_frame_samples = info->defaultSampleRate * FRAME_TIME / 1000;
+	uint32_t capture_frame_samples = info->defaultSampleRate * FRAME_TIME / 1000;
 
 	paError = Pa_OpenStream(&micspk->ply_stream, NULL, &outParam, info->defaultSampleRate, capture_frame_samples, paClipOff, &outStreamCallback, micspk);
 	if (paError != 0) {
@@ -196,8 +203,8 @@ static int initialize_speaker(audiomicspklinux_t* micspk)
 static int initialize_micro(audiomicspklinux_t* micspk)
 {
 	const PaDeviceInfo* info;
-	PaStreamParameters inParam;
-	PaError paError;
+	PaStreamParameters inParam = {0};
+	
 	int micro_dev_id = micspk->rec_dev_id;
 
 	if (micro_dev_id == -1) {
@@ -207,30 +214,33 @@ static int initialize_micro(audiomicspklinux_t* micspk)
 			return APR_EGENERAL;
 		}
 	}
+
 	info = Pa_GetDeviceInfo(micro_dev_id);
 	inParam.device = micro_dev_id;
 	inParam.channelCount = 1;
 	inParam.sampleFormat = paFloat32;
-	inParam.suggestedLatency = info->defaultLowOutputLatency;
+	inParam.suggestedLatency = info->defaultLowInputLatency;
 	inParam.hostApiSpecificStreamInfo = NULL;
-	if (Pa_IsFormatSupported(NULL, &inParam, info->defaultSampleRate) != paNoError) {
+	audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio input device name is %s.", info->name);
+	PaError paError = Pa_IsFormatSupported(&inParam, NULL, info->defaultSampleRate);
+	if (paNoError != paError) {
 		audio_log_v(AUDIO_LOG_LEVEL_ERROR, "audio micro create error, cannot open audio input device.");
 		return APR_EGENERAL;
 	}
 	audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micspk create success, open audio input device success! and defaultSampleRate is %f.", info->defaultSampleRate);
 
-	UINT32 capture_frame_samples = info->defaultSampleRate * FRAME_TIME / 1000;
+	uint32_t capture_frame_samples = info->defaultSampleRate * FRAME_TIME / 1000;
 
-	paError = Pa_OpenStream(&micspk->rec_stream, NULL, &inParam, info->defaultSampleRate, capture_frame_samples, paClipOff, &inStreamCallback, micspk);
-	if (paError != 0) {
-		audio_log_v(AUDIO_LOG_LEVEL_ERROR, "audio micspk create error, Pa_OpenStream function failed in dir! ");
+	paError = Pa_OpenStream(&micspk->rec_stream, &inParam, NULL, info->defaultSampleRate, capture_frame_samples, paClipOff|paDitherOff, &inStreamCallback, micspk);
+	if (paNoError != paError) {
+		audio_log_v(AUDIO_LOG_LEVEL_ERROR, "audio input Pa_OpenStream function failed for %s.", Pa_GetErrorText(paError));
 		return APR_EGENERAL;
 	}
 	audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micspk create success, audio input device Pa_OpenStream success!");
 
 	paError = Pa_StartStream(micspk->rec_stream);
 	if (paError != 0) {
-		audio_log_v(AUDIO_LOG_LEVEL_ERROR, "Pa_StartStream function failed in dir! ");
+		audio_log_v(AUDIO_LOG_LEVEL_ERROR, "Pa_StartStream function failed!");
 		Pa_CloseStream(micspk->rec_stream);
 		micspk->rec_stream = NULL;
 		return APR_EGENERAL;
@@ -271,12 +281,11 @@ static void uninitialize_micro(audiomicspklinux_t* micspk)
 	audio_log_v(AUDIO_LOG_LEVEL_INFO, "uninitialize_micro success!");
 }
 
-
-void* audiowork_proc(void* param)
+void* APR_THREAD_FUNC* audiowork_proc(apr_thread_t* threadhandle, void* param)
 {
 	audiomicspklinux_t* micspk = (audiomicspklinux_t*)param;
 	int rc;
-
+	audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk addr is 0x%0x, current sem addr is 0x%0x.  started flag is %s.", __FUNCTION__, __LINE__, param, micspk->audio_device_started_sem, micspk->baudio_device_started_flag ? "true" : "false");
 	//
 	// record need play because of AEC, so 
 	// record <---> record and play
@@ -313,8 +322,36 @@ void* audiowork_proc(void* param)
 			audio_log_v(AUDIO_LOG_LEVEL_INFO, "play mode initialize speak louder param success!");
 		}
 	}
-on_error:
 
+	micspk->baudio_device_started_flag = true;
+
+	audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk addr is 0x%0x, current sem addr is 0x%0x.", __FUNCTION__, __LINE__, micspk, micspk->audio_device_started_sem);
+
+	while (true)
+	{
+		struct timespec ts;
+		//int ivalue = -1;
+		clock_gettime(CLOCK_REALTIME, &ts);
+		ts.tv_nsec += 1000 * 1000 * CLOCK_PERIOD;
+		
+		//sem_getvalue(micspk->audio_device_started_sem, &ivalue);
+		//audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d current sem value is %d.", __FUNCTION__, __LINE__, ivalue);
+		if (-1 == sem_timedwait(micspk->audio_device_started_sem, &ts)) {
+			if (ETIMEDOUT == errno) {
+				if (micspk->opt & AMS_OPT_RECORD) {
+					//on_clock_rec(micspk);
+				}
+				else if (micspk->opt & AMS_OPT_PLAY) {
+					//on_clock_spk(micspk);
+				}
+			}
+		}
+		else {
+			break;
+		}
+	} 
+
+on_error:
 	if (micspk->opt & AMS_OPT_RECORD) {
 		uninitialize_micro(micspk);
 		uninitialize_speaker(micspk);
@@ -352,6 +389,7 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
 
 	micspk = apr_palloc(pool, sizeof(audiomicspklinux_t));
 	memset(micspk, 0, sizeof(audiomicspklinux_t));
+	micspk->audio_device_started_sem = (sem_t*)apr_palloc(pool, sizeof(sem_t));
 
 	frame_samples = FRAME_TIME * clock / 1000;
 	capture_frame_samples = FRAME_TIME * clock / 1000;
@@ -368,23 +406,56 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
 
 	if (opt & AMS_OPT_PLAY) {
 		micspk->base.direction |= STREAM_DIR_WRITE;
-		delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf * *)& micspk->ply_dbuf);
+		delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf**)& micspk->ply_dbuf);
 		micspk->ply_buf = (short*)apr_palloc(pool, frame_samples << 1);
 		micspk->ply_buf_cnt = 0;
 		//micspk->output_resample_state = speex_resampler_init(1, AUDIO_CLOCK, CAPTURE_AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
 	}
 	if (opt & AMS_OPT_RECORD) {
 		micspk->base.direction |= STREAM_DIR_READ;
-		delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf * *)& micspk->rec_dbuf);
+		delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf**)& micspk->rec_dbuf);
 		//micspk->input_resample_state = speex_resampler_init(1, CAPTURE_AUDIO_CLOCK, AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
 	}
-
-	int err = pthread_create(&micspk->audio_work_threadid, NULL, audiowork_proc, micspk);
-	if (0 == err) {
+	micspk->baudio_device_started_flag = false;
+	sem_init(micspk->audio_device_started_sem, 0, 0);
+	audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk addr is 0x%0x, current sem addr is 0x%0x. started flag is %s.", __FUNCTION__, __LINE__, micspk, micspk->audio_device_started_sem, micspk->baudio_device_started_flag ? "true" : "false");
+	apr_status_t err = apr_thread_create(&micspk->audio_work_threadid, NULL, audiowork_proc, micspk, pool);
+	if (APR_SUCCESS == err) {
 		Dbg("create audiomicspk work thread success, %lu.", micspk->audio_work_threadid);
+		bool baudio_work_thread_exit = false;
+		
+		do {
+			struct timespec ts;
+			int ivalue = -1;
+			clock_gettime(CLOCK_REALTIME, &ts);
+			ts.tv_nsec += 1000 * 1000 * 10;
+			sem_getvalue(micspk->audio_device_started_sem, &ivalue);
+			audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d current sem value is %d.", __FUNCTION__, __LINE__, ivalue);
+			if(-1 == sem_timedwait(micspk->audio_device_started_sem, &ts)) {
+				if (ETIMEDOUT == errno){
+					if (micspk->baudio_device_started_flag) {
+						audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d audio device is already started.", __FUNCTION__, __LINE__);
+						break;
+					}
+				}
+			}
+			else{
+				audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d audio device work thread has exit.", __FUNCTION__, __LINE__);
+				baudio_work_thread_exit = true;
+			}
+		} while (!baudio_work_thread_exit);
+
+		if (baudio_work_thread_exit) {
+			audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
+			audiomicspklinux_destroy(micspk);
+			audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
+			return APR_EGENERAL;
+		}
 	}
 	else {
 		Dbg("create audiomicspk work thread failed.");
+		audiomicspklinux_destroy(micspk);
+		return APR_EGENERAL;
 	}
 
 	*p_micspk = micspk;

+ 42 - 41
Other/libaudioframework/audiomicspklinux.h

@@ -1,4 +1,3 @@
-
 #pragma once
 
 #ifdef __cplusplus
@@ -11,49 +10,51 @@ extern "C" {
 #define AMS_OPT_AS_STREAM	0x00
 #define AMS_OPT_AS_ENGINE	0x04
 
+#include "precompile.h"
 #include "audiostream.h"
+#include <stdbool.h>
+
+typedef struct audiomicspklinux_s
+{
+	audiostream_t base;
+	int opt;
+	int rec_dev_id;
+	int ply_dev_id;
+	int frame_samples;
+	int capture_frame_samples;
+
+	void* ply_stream;
+	void* ply_dbuf;
+	short* ply_buf;
+	unsigned ply_buf_cnt;
+
+	void* rec_stream;
+	void* rec_buf;
+	void* rec_dbuf;
+	unsigned long  rec_buf_cnt;
+
+	apr_thread_t* audio_work_threadid;
+	sem_t* audio_device_started_sem;
+	bool baudio_device_started_flag;
+
+	void* input_resample_state;
+	void* output_resample_state;
+
+	int (*on_rx_audio)(char* frame, void* user_data);
+	void* user_data;
+}audiomicspklinux_t;
+
+apr_status_t audiomicspklinux_create(apr_pool_t* pool,
+	audioengine_t* engine,
+	int opt,
+	int clock,
+	const char* rec_dev_key,
+	const char* ply_dev_key,
+	audiomicspklinux_t** p_micspk);
+
+void audiomicspklinux_destroy(audiomicspklinux_t* micspk);
 
 
-	typedef struct audiomicspklinux_s
-	{
-		audiostream_t base;
-
-		int opt;
-		int rec_dev_id;
-		int ply_dev_id;
-		int frame_samples;
-		int capture_frame_samples;
-
-		void* ply_stream;
-		void* ply_dbuf;
-		short* ply_buf;
-		unsigned ply_buf_cnt;
-
-		void* rec_stream;
-		void* rec_buf;
-		void* rec_dbuf;
-		unsigned long  rec_buf_cnt;
-
-		unsigned long int audio_work_threadid;
-
-		void* input_resample_state;
-		void* output_resample_state;
-
-		int (*on_rx_audio)(char* frame, void* user_data);
-		void* user_data;
-
-	}audiomicspklinux_t;
-
-	apr_status_t audiomicspklinux_create(apr_pool_t* pool,
-		audioengine_t* engine,
-		int opt,
-		int clock,
-		const char* rec_dev_key,
-		const char* ply_dev_key,
-		audiomicspklinux_t** p_micspk);
-
-	void audiomicspklinux_destroy(audiomicspklinux_t* micspk);
-
 #ifdef __cplusplus
 } // extern "C" {
 #endif

+ 65 - 9
Other/libaudioframework/audiortp.c

@@ -130,10 +130,18 @@ static apr_status_t read_frame(void *self, audioframe_t *frame)
 					if (digit[j] < sizeof(digitmap)) {
 						int ch = digitmap[digit[j]];
 						audiostream_raise_event(self, STREAM_EVT_RTP_DTMF, digit[j], 0);
+#ifdef _WIN32
 						EnterCriticalSection(&audiortp->m_dtmf_lock);
+#else
+						apr_thread_mutex_lock(audiortp->m_dtmf_mtx);
+#endif
 						if (audiortp->m_recv_dtmf_cnt < MAX_DTMF)
 							audiortp->m_recv_dtmf[audiortp->m_recv_dtmf_cnt++] = digit[j];
+#ifdef _WIN32 
 						LeaveCriticalSection(&audiortp->m_dtmf_lock);
+#else
+						apr_thread_mutex_unlock(audiortp->m_dtmf_mtx);
+#endif
 					}
 				}
 				if (digit_cnt > 0)
@@ -177,9 +185,14 @@ static apr_status_t write_frame(void *self, const audioframe_t *frame)
 	audiortp_t *audiortp = CONTAINING_RECORD(self, audiortp_t, base);
 	int dtmf = 0;
 
+#ifdef WIN32
 	EnterCriticalSection(&audiortp->m_dtmf_lock);
-	if (frame->dtmf && CIRC_LEN(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr, MAX_DTMF) < MAX_DTMF-1) {
-		rtp_dtmf_event *dtmf = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_wr];
+#else
+	apr_thread_mutex_lock(audiortp->m_dtmf_mtx);
+#endif
+
+	if (frame->dtmf && CIRC_LEN(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr, MAX_DTMF) < MAX_DTMF - 1) {
+		rtp_dtmf_event* dtmf = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_wr];
 		dtmf->event = (unsigned char)digit2event(frame->dtmf);
 		dtmf->e_vol = DTMF_VOLUME;
 		dtmf->p = 0;
@@ -188,7 +201,7 @@ static apr_status_t write_frame(void *self, const audioframe_t *frame)
 		audiortp->m_send_dtmf_wr = CIRC_INC(audiortp->m_send_dtmf_wr, MAX_DTMF);
 	}
 	if (!CIRC_IS_EMPTY(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr)) {
-		rtp_dtmf_event *digit = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_rd];
+		rtp_dtmf_event* digit = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_rd];
 		send_dtmf_digit(audiortp->m_rtpsession, digit, audiortp->m_send_dtmf_pt);
 		dtmf = 1;
 		digit->duration += DTMF_DURATION_STEP;
@@ -196,12 +209,17 @@ static apr_status_t write_frame(void *self, const audioframe_t *frame)
 			if (digit->duration == DTMF_DURATION) {
 				digit->e = 1;
 			}
-		} else {
+		}
+		else {
 			audiortp->m_send_dtmf_rd = CIRC_INC(audiortp->m_send_dtmf_rd, MAX_DTMF);
 			rtp_session_advance_timestamp(audiortp->m_rtpsession, DTMF_DURATION);
 		}
 	}
+#ifdef _WIN32
 	LeaveCriticalSection(&audiortp->m_dtmf_lock);
+#else
+	apr_thread_mutex_unlock(audiortp->m_dtmf_mtx);
+#endif // WIN32
 
 	if (dtmf) {
 		/* because we send dtmf, so ignore this frame */
@@ -256,11 +274,16 @@ static audiostream_vtbl_t g_stream_vtbl = {
 void audiortp_destroy(audiortp_t *self)
 {
 	audiortp_t *audiortp = (audiortp_t *)self;
+#ifdef _WIN32
 	DeleteCriticalSection(&audiortp->m_dtmf_lock);
+#else
+	apr_thread_mutex_destroy(audiortp->m_dtmf_mtx);
+#endif // _WIN32
 }
 
 apr_status_t audiortp_create(apr_pool_t *pool, audioengine_t *engine, rtp_session_t *sess, audiortp_t **p_audiortp)
 {
+	apr_status_t status = -1;
 	audiortp_t *audiortp;
 
 	audiortp = apr_palloc(pool, sizeof(audiortp_t));
@@ -296,9 +319,16 @@ apr_status_t audiortp_create(apr_pool_t *pool, audioengine_t *engine, rtp_sessio
 	audiortp->m_on_recv_hook = NULL;
 	audiortp->m_on_send_hook = NULL;
 	audiortp->m_hook_data = NULL;
+
+#ifdef _WIN32
 	InitializeCriticalSection(&audiortp->m_dtmf_lock);
+	status = APR_SUCCESS;
+#else
+	status = apr_thread_mutex_create(&audiortp->m_dtmf_mtx, APR_THREAD_MUTEX_NESTED, pool);
+#endif // _WIN32
+
 	*p_audiortp = audiortp;
-	return APR_SUCCESS;
+	return status;
 }
 
 apr_status_t audiortp_set_param(audiortp_t *audiortp, int flag, const void *ptr)
@@ -396,6 +426,7 @@ apr_status_t audiortp_get_param(audiortp_t *audiortp, int flag, void *ptr)
 apr_status_t audiortp_init(audiortp_t *ar)
 {
 	audiortp_t *audiortp = (audiortp_t *)ar;
+	Dbg("%s : %d", __FUNCTION__, __LINE__);
 	audiortp->m_send_samplebit = pt2bitsample(audiortp->m_send_pt);
 	audiortp->m_recv_samplebit = pt2bitsample(audiortp->m_recv_pt);
 	audiortp->m_send_psize = audiortp->m_send_ptime * audiortp->m_send_clock / 1000 * audiortp->m_send_samplebit / 8;
@@ -405,6 +436,7 @@ apr_status_t audiortp_init(audiortp_t *ar)
 	jbuf_create(audiortp->m_jbuf_psize, audiortp->m_jbuf_ptime, JB_MAX, &audiortp->m_jitterbuf);
 	jbuf_set_adaptive(audiortp->m_jitterbuf, 0, 7, JB_MAX);
 	DEBUG_TRACE("audiortp init, send_psize:%d, recv_psize:%d", audiortp->m_send_psize, audiortp->m_recv_psize);
+	Dbg("%s : %d", __FUNCTION__, __LINE__);
 	return APR_SUCCESS;
 }
 
@@ -430,18 +462,30 @@ apr_status_t audiortp_send_dtmf(audiortp_t *self, const char *digits, unsigned c
 		return -1;
 	if (!(audiostream_get_direction(&audiortp->base)&STREAM_DIR_WRITE))
 		return -1;
+
+
+#ifdef _WIN32
 	EnterCriticalSection(&audiortp->m_dtmf_lock);
-	while (CIRC_LEN(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr, MAX_DTMF) < MAX_DTMF-1 && count < cnt) {
-		rtp_dtmf_event *dtmf = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_wr];
+#else
+	apr_thread_mutex_lock(audiortp->m_dtmf_mtx);
+#endif
+
+	while (CIRC_LEN(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr, MAX_DTMF) < MAX_DTMF - 1 && count < cnt) {
+		rtp_dtmf_event* dtmf = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_wr];
 		dtmf->event = (unsigned char)digit2event(digits[count]);
 		dtmf->e_vol = DTMF_VOLUME;
 		dtmf->p = 0;
 		dtmf->e = 0;
 		dtmf->duration = 0;
 		audiortp->m_send_dtmf_wr = CIRC_INC(audiortp->m_send_dtmf_wr, MAX_DTMF);
-		count ++;
+		count++;
 	}
+#ifdef _WIN32
 	LeaveCriticalSection(&audiortp->m_dtmf_lock);
+#else
+	apr_thread_mutex_unlock(audiortp->m_dtmf_mtx);
+#endif // _WIN32
+	
 
 	return APR_SUCCESS;
 }
@@ -460,15 +504,27 @@ apr_status_t audiortp_recv_dtmf(audiortp_t *self, char *digits, unsigned *cnt)
 	if (!digits)
 		return APR_BADARG;
 
+
+#ifdef _WIN32
 	EnterCriticalSection(&audiortp->m_dtmf_lock);
+#else
+	apr_thread_mutex_lock(audiortp->m_dtmf_mtx);
+#endif
 	while (count < *cnt && i < audiortp->m_recv_dtmf_cnt) {
 		digits[count++] = audiortp->m_recv_dtmf[i++];
 	}
 	if (i < audiortp->m_recv_dtmf_cnt)
-		memmove(&audiortp->m_recv_dtmf[0], &audiortp->m_recv_dtmf[i], audiortp->m_recv_dtmf_cnt-i);
+		memmove(&audiortp->m_recv_dtmf[0], &audiortp->m_recv_dtmf[i], audiortp->m_recv_dtmf_cnt - i);
 	audiortp->m_recv_dtmf_cnt -= i;
 	*cnt = count;
+
+#ifdef _WIN32
 	LeaveCriticalSection(&audiortp->m_dtmf_lock);
+#else
+	apr_thread_mutex_unlock(audiortp->m_dtmf_mtx);
+#endif // _WIN32
+	
+
 
 	return APR_SUCCESS;
 }

+ 5 - 0
Other/libaudioframework/audiortp.h

@@ -57,7 +57,12 @@ struct audiortp_t
 	int m_recv_dtmf_cnt;
 	unsigned int m_recving_dtmf_ts;
 	rtp_dtmf_event m_recving_dtmf_event;
+#ifdef _WIN32
 	CRITICAL_SECTION m_dtmf_lock;
+#else
+	apr_thread_mutex_t* m_dtmf_mtx;
+#endif
+	
 	void (*m_on_send_hook)(const char *buf, int size, void *arg);
 	void (*m_on_recv_hook)(const char *buf, int size, void *arg);
 	void *m_hook_data;

+ 65 - 16
Other/libaudioframework/other/delaybuf.c

@@ -17,6 +17,7 @@
 
 
 
+
 /* Operation types of delay buffer */
 enum OP
 {
@@ -42,7 +43,11 @@ enum OP
 struct delay_buf
 {
     /* Properties and configuration */
+#ifdef _WIN32
 	CRITICAL_SECTION lock;
+#else
+	pthread_mutex_t lock_mtx;
+#endif
     unsigned	     samples_per_frame; /**< Number of samples in one frame  */
     unsigned	     ptime;		/**< Frame time, in ms		     */
     unsigned	     channel_count;	/**< Channel count, in ms	     */
@@ -103,8 +108,11 @@ int delay_buf_create(unsigned clock_rate,
 	return status;
 
     /* Finally, create mutex */
+#ifdef _WIN32
 	InitializeCriticalSection(&b->lock);
-
+#else
+	status = pthread_mutex_init(&b->lock_mtx, NULL);
+#endif
     *p_b = b;
 
     return 0;
@@ -115,19 +123,24 @@ int delay_buf_destroy(delay_buf *b)
     int status;
 
     ASSERT_RETURN(b, -1);
-
+#ifdef _WIN32
 	EnterCriticalSection(&b->lock);
-
+#else
+	pthread_mutex_lock(&b->lock_mtx);
+#endif
     status = wsola_destroy(b->wsola);
     if (status == 0)
 		b->wsola = NULL;
 	circ_buf_destroy(b->circ_buf);
 	b->circ_buf = NULL;
 
-    LeaveCriticalSection(&b->lock);
-
-    DeleteCriticalSection(&b->lock);
-
+#ifdef _WIN32
+	LeaveCriticalSection(&b->lock);
+	DeleteCriticalSection(&b->lock);
+#else
+	pthread_mutex_unlock(&b->lock_mtx);
+	pthread_mutex_destroy(&b->lock_mtx);
+#endif
 	free(b);
 
     return status;
@@ -217,13 +230,21 @@ int delay_buf_put(delay_buf *b,
 
     ASSERT_RETURN(b && frame, -1);
 
-    EnterCriticalSection(&b->lock);
+#ifdef _WIN32
+	EnterCriticalSection(&b->lock);
+#else
+	pthread_mutex_lock(&b->lock_mtx);
+#endif
 
     update(b, OP_PUT);
     
     status = wsola_save(b->wsola, frame, FALSE);
     if (status != 0) {
-	LeaveCriticalSection(&b->lock);
+#ifdef _WIN32
+		LeaveCriticalSection(&b->lock);
+#else
+		pthread_mutex_unlock(&b->lock_mtx);
+#endif
 	return status;
     }
 
@@ -256,7 +277,11 @@ int delay_buf_put(delay_buf *b,
 
     circ_buf_write(b->circ_buf, frame, b->samples_per_frame);
 
-    LeaveCriticalSection(&b->lock);
+#ifdef _WIN32
+	LeaveCriticalSection(&b->lock);
+#else
+	pthread_mutex_unlock(&b->lock_mtx);
+#endif
     return 0;
 }
 
@@ -266,7 +291,11 @@ int delay_buf_get( delay_buf *b,short frame[])
 
     ASSERT_RETURN(b && frame, -1);
 
-    EnterCriticalSection(&b->lock);
+#ifdef _WIN32
+	EnterCriticalSection(&b->lock);
+#else
+	pthread_mutex_lock(&b->lock_mtx);
+#endif
 
     update(b, OP_GET);
 
@@ -279,7 +308,11 @@ int delay_buf_get( delay_buf *b,short frame[])
 
 	if (status == 0) {
 	    if (circ_buf_get_len(b->circ_buf) == 0) {
-		LeaveCriticalSection(&b->lock);
+#ifdef _WIN32
+			LeaveCriticalSection(&b->lock);
+#else
+			pthread_mutex_unlock(&b->lock_mtx);
+#endif
 		return 0;
 	    }
 
@@ -297,7 +330,11 @@ int delay_buf_get( delay_buf *b,short frame[])
 	    /* The buffer is empty now, reset it */
 	    circ_buf_reset(b->circ_buf);
 
-	    LeaveCriticalSection(&b->lock);
+#ifdef _WIN32
+		LeaveCriticalSection(&b->lock);
+#else
+		pthread_mutex_unlock(&b->lock_mtx);
+#endif
 
 	    return 0;
 	}
@@ -305,7 +342,11 @@ int delay_buf_get( delay_buf *b,short frame[])
 
     circ_buf_read(b->circ_buf, frame, b->samples_per_frame);
 
-    LeaveCriticalSection(&b->lock);
+#ifdef _WIN32
+	LeaveCriticalSection(&b->lock);
+#else
+	pthread_mutex_unlock(&b->lock_mtx);
+#endif
 
     return 0;
 }
@@ -315,7 +356,11 @@ int delay_buf_reset(delay_buf *b)
 {
     ASSERT_RETURN(b, -1);
 
-    EnterCriticalSection(&b->lock);
+#ifdef _WIN32
+	EnterCriticalSection(&b->lock);
+#else
+	pthread_mutex_lock(&b->lock_mtx);
+#endif
 
     b->recalc_timer = RECALC_TIME;
 
@@ -325,7 +370,11 @@ int delay_buf_reset(delay_buf *b)
     /* Reset WSOLA */
     wsola_reset(b->wsola, 0);
 
-    LeaveCriticalSection(&b->lock);
+#ifdef _WIN32
+	LeaveCriticalSection(&b->lock);
+#else
+	pthread_mutex_unlock(&b->lock_mtx);
+#endif
 
     return 0;
 }

+ 1 - 1
Other/libaudioframework/precompile.h

@@ -4,7 +4,7 @@
 #include <Mmsystem.h>
 #include <windows.h>
 #else
-#include <wtypes.h>
+//#include <wtypes.h>
 #include <semaphore.h>
 #endif // _WIN32
 

+ 18 - 22
Other/libvideoframework/CMakeLists.txt

@@ -8,23 +8,34 @@ else()
     set(SPBASE_LIB spbase)
 endif(RVC_DEBUG_MODE)
 
+if(MSVC)
+	set(${VIDEONOUSE}_SRCS
+	   videorender.h
+       videoview.h
+       videorender.c
+	   videoview.c
+	)
+else()
+	set(${VIDEONOUSE}_SRCS 
+	)
+endif(MSVC)
 
 if(MSVC)
-	set(${PLATFORM}_SRCS
+	set(${VIDEOPLATFORM}_SRCS
 	   videocap.h
        videoclock.h
        videoplayer.h
-       videorender.h
-       videoview.h
+       #videorender.h
+       #videoview.h
 	   videocap.c
 	   videoclock.c
 	   videoplayer.c
-       videorender.c
-	   videoview.c
+       #videorender.c
+	   #videoview.c
 	   congestion_control/common/platform/windows/mscc.c
 	)
 else()
-	set(${PLATFORM}_SRCS 
+	set(${VIDEOPLATFORM}_SRCS 
 		congestion_control/common/platform/linux/posix.c
 	)
 endif(MSVC)
@@ -133,7 +144,6 @@ set(${MODULE_PREFIX}_SRCS
     congestion_control/common/cf_skiplist.c
     congestion_control/common/cf_stream.c
     congestion_control/common/cf_unwrapper.c
-    #congestion_control/common/platform/windows/mscc.c
     congestion_control/estimator/ack_bitrate_estimator.c
     congestion_control/estimator/aimd_rate_control.c
     congestion_control/estimator/bitrate_controller.c
@@ -191,7 +201,7 @@ set(${MODULE_PREFIX}_SRCS
 	precompile.h
 	precompile.c
 
-	${${PLATFORM}_SRCS}
+	${${VIDEOPLATFORM}_SRCS}
 )
 
 add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS})
@@ -238,20 +248,6 @@ target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS}
 
 target_compile_definitions(${MODULE_NAME} PUBLIC "_XKEYCHECK_H")
 
-if(MSVC)
-	install(TARGETS ${MODULE_NAME} 
-    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}" COMPONENT libraries
-    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT develops EXCLUDE_FROM_ALL
-    LIBRARY DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT libraries
-    )
-else(MSVC)
-install(TARGETS ${MODULE_NAME} 
-    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}"
-    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}"
-    LIBRARY DESTINATION "${RVC_RUNTIME_PATH}"
-    COMPONENT libraries)
-endif(MSVC)
-
 
 if(MSVC)
 set(OTHER_CONAN_DEP_LIBS ${OTHER_CONAN_DEP_LIBS} ${CONAN_BIN_DIRS} PARENT_SCOPE)

+ 2 - 3
Other/libvideoframework/precompile.h

@@ -9,7 +9,7 @@
 #endif
 
 
-#ifdef _WIN32
+#ifdef RVC_OS_WIN
 #include <WinSock2.h>
 #define WIN32_LEAN_AND_MEAN
 #include <Mmsystem.h>
@@ -18,7 +18,7 @@
 #include <process.h>
 #else
 
-#endif // _WIN32
+#endif // RVC_OS_WIN
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -38,6 +38,5 @@
 #else
 #ifndef SPBASE_API
 #define SPBASE_API __declspec(dllimport)
-//#pragma comment(lib, "SpBase.lib")
 #endif
 #endif

+ 1 - 3
Other/libvideoframework/videoutil.h

@@ -1,10 +1,8 @@
 #ifndef VIDEOUTIL_H
 #define VIDEOUTIL_H
 
-#ifdef _WIN32
-#else
+
 #include <stdint.h>
-#endif // _WIN32
 
 #ifdef __cplusplus
 extern "C" {