ConnectorFSM.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. #include "stdafx.h"
  2. #include "ConnectorFSM.h"
  3. #include "../include/ModuleMix.h"
  4. #define RELEASEING_TIMER_INTERVAL 1200
  5. #define RELEASEING_SIP_TIMER 20000
  6. #define SIP_CALL_TIMER 70000 //sip呼叫超时时间,20170314,增加超时时间解决坐席忽闪问题
  7. #define RELEASEING_SIP_TIMEOUT 30000
  8. #define SIP_CONNECT_FAIL_TIMES 10
  9. #define LIVEDETECT_CONNECT_INTERVAL 5000 //live detection实体检测间隔5s
  10. #define LIVEDETECTION_TIMEOUT 60000 //活体检测超时时间60s
  11. class SyncServiceClient:public SyncService_ClientBase
  12. {
  13. public:
  14. SyncServiceClient(CEntityBase *pEntity, ACMCallFSM* fsm) : SyncService_ClientBase(pEntity), m_fsm(fsm) {}
  15. ACMCallFSM *m_fsm;
  16. };
  17. class MyPhoneClient : public PhoneService_ClientBase
  18. {
  19. public:
  20. MyPhoneClient(CEntityBase *pEntity, ACMCallFSM* fsm) : PhoneService_ClientBase(pEntity), m_fsm(fsm) {}
  21. virtual void OnMessage(ErrorCodeEnum Error, PhoneService_PhoneState_Info &Msg, CSmartPointer<IReleasable> pData)
  22. {
  23. Dbg("rx sip phone state = %d, status = %s", Msg.state, (LPCSTR)Msg.status);
  24. //LOG_TRACE("rx sip phone state = %d", Msg.state);
  25. if (Error == Error_Succeed) {
  26. switch (Msg.state) {
  27. case ePhone_Init:
  28. case ePhone_Terminated:
  29. {
  30. FSMEvent *e = new FSMEvent(USER_EVT_SIP_STATE_IDLE);
  31. m_fsm->PostEventFIFO(e);
  32. }
  33. break;
  34. case ePhone_Ready:
  35. {
  36. Dbg("sip channel connected");
  37. FSMEvent *e = new FSMEvent(USER_EVT_SIP_STATE_CONNECTED);
  38. m_fsm->PostEventFIFO(e);
  39. }
  40. break;
  41. default:
  42. break;
  43. }
  44. }
  45. }
  46. ACMCallFSM *m_fsm;
  47. };
  48. class MyChannelClient : public ChannelService_ClientBase
  49. {
  50. public:
  51. MyChannelClient(CEntityBase *pEntity, ACMCallFSM* fsm) : ChannelService_ClientBase(pEntity), m_fsm(fsm) {}
  52. virtual void OnMessage(ErrorCodeEnum Error, ChannelService_State_Info &Msg, CSmartPointer<IReleasable> pData)
  53. {
  54. if (Error == Error_Succeed) {
  55. switch (Msg.state) {
  56. case eChannelState_Idle:
  57. {
  58. FSMEvent *e = new FSMEvent(USER_EVT_CHAN_STATE_IDLE);
  59. m_fsm->PostEventFIFO(e);
  60. }
  61. break;
  62. case eChannelState_Connected:
  63. {
  64. Dbg("CHAN_STATE_CONNECTED.param = %s", (LPCSTR)Msg.param);
  65. FSMEvent *e = new ChanStateConnectedEvent(Msg.param);
  66. m_fsm->PostEventFIFO(e);
  67. }
  68. break;
  69. default:
  70. break;
  71. }
  72. }
  73. }
  74. ACMCallFSM *m_fsm;
  75. };
  76. ACMCallFSM::ACMCallFSM( )
  77. : m_pPhoneClient(NULL), m_pChannelClient(NULL), m_bRing(FALSE),m_nCurSipServer(MAIN_SERVER),m_nCurChanServer(MAIN_SERVER)
  78. {
  79. }
  80. ACMCallFSM::~ACMCallFSM()
  81. {
  82. }
  83. ErrorCodeEnum ACMCallFSM::OnInit()
  84. {
  85. memset(m_strSIPProxyIP,0,sizeof(m_strSIPProxyIP));
  86. memset(m_strSIPCallNum,0,sizeof(m_strSIPCallNum));
  87. memset(m_iSIPProxyPort,0,sizeof(m_iSIPProxyPort));
  88. memset(m_strChanCallNum,0,sizeof(m_strChanCallNum));
  89. memset(m_strChanProxyIP,0,sizeof(m_strChanProxyIP));
  90. memset(m_iSIPProxyPort,0,sizeof(m_iSIPProxyPort));
  91. ErrorCodeEnum Error = LoadConfig();
  92. if (Error != Error_Succeed)
  93. goto on_error;
  94. Dbg("LoadConfig success");
  95. GetEntityBase()->GetFunction()->SetSysVar("CallState", "O"); // set to offline state
  96. Error = LoadTerminalId();
  97. if (Error != Error_Succeed)
  98. goto on_error;
  99. Dbg("sip proxy ip1:%s,num1:%s,port1:%d;ip2:%s,num2:%s,port2:%d", (LPCSTR)m_strSIPProxyIP[0],(LPCSTR)m_strSIPCallNum[0], m_iSIPProxyPort[0],(LPCSTR)m_strSIPProxyIP[1],(LPCSTR)m_strSIPCallNum[1], m_iSIPProxyPort[1]);
  100. Dbg("chan proxy ip1:%s,num1:%s,port1:%d;ip2:%s,num2:%s,port2:%d", (LPCSTR)m_strChanProxyIP[0],(LPCSTR)m_strChanCallNum[0], m_iChanProxyPort[0],(LPCSTR)m_strChanProxyIP[1],(LPCSTR)m_strChanCallNum[1], m_iChanProxyPort[1]);
  101. Dbg("TerminalId: %s", (LPCSTR)m_strTerminalId);
  102. m_bHangup = FALSE;
  103. m_bHandFree = TRUE;
  104. m_bAgentHandFree = TRUE;
  105. m_bIsAgentControl = FALSE;
  106. m_nSipErrorNum = 0;
  107. m_nLiveDetctionTime = 0;
  108. memset(&m_CallingParam,0,sizeof(m_CallingParam));
  109. m_pPhoneClient = new MyPhoneClient(m_pEntity, this);
  110. Error = m_pPhoneClient->Connect();
  111. if (Error != Error_Succeed)
  112. goto on_error;
  113. PhoneService_BeginState_Sub PhoneSub;
  114. Error = m_pPhoneClient->BeginState(PhoneSub);
  115. if (Error != Error_Succeed)
  116. goto on_error;
  117. m_pSyncServiceClient = new SyncServiceClient(m_pEntity, this);
  118. Error = m_pSyncServiceClient->Connect();
  119. if (Error != Error_Succeed)
  120. {
  121. Dbg("Connect SyncService Fail!");
  122. m_pSyncServiceClient->SafeDelete();
  123. m_pSyncServiceClient = NULL;
  124. }
  125. m_nSysCallType = 0;
  126. m_pChannelClient = new MyChannelClient(m_pEntity, this);
  127. Error = m_pChannelClient->Connect();
  128. if (Error != Error_Succeed) {
  129. m_pChannelClient->SafeDelete();
  130. m_pChannelClient = NULL;
  131. goto on_error;
  132. }
  133. ChannelService_BeginState_Sub ChannelSub;
  134. Error = m_pChannelClient->BeginState(ChannelSub);
  135. if (Error != Error_Succeed) {
  136. m_pChannelClient->GetFunction()->CloseSession();
  137. m_pChannelClient = NULL;
  138. goto on_error;
  139. }
  140. Dbg("fsm init ok!");
  141. AddStateHooker(this);
  142. return Error;
  143. on_error:
  144. Dbg("on_error");
  145. FSMEvent *e = new FSMEvent(USER_EVT_ERROR);
  146. PostEventFIFO(e); // jump to error state
  147. return Error;
  148. }
  149. BOOL ACMCallFSM::ReConnectionAssistchan()
  150. {
  151. if (m_pChannelClient != NULL)
  152. {
  153. m_pChannelClient->GetFunction()->CloseSession();
  154. m_pChannelClient = NULL;
  155. Dbg("Close AssistChannel Session ");
  156. }
  157. if (m_pChannelClient == NULL)
  158. {
  159. Dbg("ReConnection AssistChannel Session");
  160. ErrorCodeEnum Error;
  161. m_pChannelClient = new MyChannelClient(m_pEntity, this);
  162. Error = m_pChannelClient->Connect();
  163. if (Error != Error_Succeed)
  164. {
  165. m_pChannelClient->SafeDelete();
  166. Dbg("m_channelClient connect fail!");
  167. return FALSE;
  168. }
  169. if (Error == Error_Succeed)
  170. {
  171. ChannelService_BeginState_Sub ChannelSub;
  172. Error = m_pChannelClient->BeginState(ChannelSub);
  173. if (Error != Error_Succeed)
  174. {
  175. Dbg("BeginState biz channel failed!");
  176. m_pChannelClient->GetFunction()->CloseSession();
  177. m_pChannelClient = NULL;
  178. return FALSE;
  179. }
  180. }
  181. }
  182. return TRUE;
  183. }
  184. BOOL ACMCallFSM::ReConnectionSipphone()
  185. {
  186. if (m_pPhoneClient != NULL)
  187. {
  188. m_pPhoneClient->GetFunction()->CloseSession();
  189. m_pPhoneClient = NULL;
  190. Dbg("Close sip Session ");
  191. }
  192. if (m_pPhoneClient == NULL)
  193. {
  194. Dbg("ReConnection sip Session");
  195. ErrorCodeEnum Error;
  196. m_pPhoneClient = new MyPhoneClient(m_pEntity, this);
  197. Error = m_pPhoneClient->Connect();
  198. if (Error != Error_Succeed)
  199. {
  200. m_pPhoneClient->SafeDelete();
  201. Dbg("m_phoneClient connect fail!");
  202. return FALSE;
  203. }
  204. if (Error == Error_Succeed)
  205. {
  206. PhoneService_BeginState_Sub PhoneSub;
  207. Error = m_pPhoneClient->BeginState(PhoneSub);
  208. if (Error != Error_Succeed)
  209. {
  210. Dbg("BeginState sip failed!");
  211. m_pPhoneClient->GetFunction()->CloseSession();
  212. m_pPhoneClient = NULL;
  213. return FALSE;
  214. }
  215. }
  216. }
  217. return TRUE;
  218. }
  219. int ACMCallFSM::GetDelayTime()
  220. {
  221. ErrorCodeEnum error= Error_Unexpect;
  222. SyncService_GetMachineData_Req req;
  223. req.key = "DelayTime";
  224. SyncService_GetMachineData_Ans ans;
  225. DWORD Timeout = 500;
  226. if (m_pSyncServiceClient)
  227. {
  228. error = m_pSyncServiceClient->GetMachineData(req,ans,Timeout);
  229. }
  230. if (error == Error_Succeed)
  231. {
  232. int delaytime = atoi(ans.value);
  233. return delaytime;
  234. }
  235. else
  236. {
  237. return -1;
  238. }
  239. }
  240. void ACMCallFSM::SetDelayTime()
  241. {
  242. if (m_pSyncServiceClient)
  243. {
  244. SyncService_SetMachineData_Info info;
  245. info.key = "DelayTime";
  246. info.data = "0";
  247. m_pSyncServiceClient->SetMachineData(info);
  248. Dbg("set delay time to 0");
  249. }
  250. }
  251. ErrorCodeEnum ACMCallFSM::OnExit()
  252. {
  253. return Error_Succeed;
  254. }
  255. void ACMCallFSM::OnStateTrans(int iSrcState, int iDstState)
  256. {
  257. Dbg("FSM state from state %s to %s", GetStateName(iSrcState), GetStateName(iDstState));
  258. if (CheckBeginRing(iSrcState, iDstState)) {
  259. StartRing();
  260. } else {
  261. if (CheckEndRing(iSrcState, iDstState))
  262. StopRing();
  263. }
  264. if (iSrcState != FSM_STATE_INIT && iDstState != FSM_STATE_EXIT) {
  265. int st1 = TranslateState(iSrcState);
  266. int st2 = TranslateState(iDstState);
  267. if (st1 != st2) {
  268. PhoneState evt;
  269. evt.state = st2;
  270. evt.status = CSimpleStringA::Format("OnStateTrans from state %d to %d", st1, st2);
  271. //LOG_TRACE(evt.status);
  272. if (!((st2 == eState_Fail)&&(m_nCurChanServer!=Error_Server)&&(m_nCurSipServer!=Error_Server))||m_bHangup)
  273. {
  274. Dbg("Broadcast state from %d to %d", st1, st2);
  275. SpSendBroadcast(GetEntityBase()->GetFunction(), SP_MSG_OF(PhoneState), SP_MSG_SIG_OF(PhoneState), evt);
  276. }
  277. SetCallState(st2);
  278. GetEntityBase()->GetFunction()->SetUserDefineState(st2+USER_SIP_OFFLINE);
  279. }
  280. }
  281. }
  282. ErrorCodeEnum ACMCallFSM::SetCallState(int state)
  283. {
  284. char *sts[] = {
  285. "O", // Offline
  286. "C", // Connecting
  287. "H", // HandFree
  288. "P", // Pickup
  289. "B", // Broken
  290. "F", // Fail
  291. "R", // Releasing
  292. "L" // LiveDetect
  293. };
  294. char* strCallState = "O";
  295. if (0 <= state && state < sizeof(sts)/sizeof(char*)){
  296. strCallState = sts[state];
  297. }
  298. Dbg("set call state to [%s].", strCallState);
  299. return GetEntityBase()->GetFunction()->SetSysVar("CallState", strCallState);
  300. }
  301. void ACMCallFSM::s0_on_entry()
  302. {
  303. m_strHintCallNum.Clear();
  304. m_nCurChanServer = MAIN_SERVER;
  305. m_nCurSipServer = MAIN_SERVER;
  306. memset(&m_CallingParam,0,sizeof(m_CallingParam));
  307. GetEntityBase()->GetFunction()->SetSysVar("CallType", "N"); //进入初始状态时设置呼叫模式为常规呼叫
  308. m_nSysCallType = 0;
  309. }
  310. void ACMCallFSM::s0_on_exit()
  311. {
  312. m_bHangup = FALSE;
  313. }
  314. unsigned int ACMCallFSM::s0_on_event(FSMEvent* event)
  315. {
  316. if (event->iEvt == USER_EVT_PICKUP_CALL)
  317. {
  318. memset(&m_CallingParam,0,sizeof(m_CallingParam)); //正常呼叫
  319. GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE, CALLTYPE_NORMAL); // 设置呼叫模式为常规呼叫
  320. m_nSysCallType = 0;
  321. }
  322. else if (event->iEvt == USER_EVT_HANDFREE_CALL)
  323. {
  324. GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE,CALLTYPE_NORMAL); // 设置呼叫模式为常规呼叫
  325. m_nSysCallType = 0;
  326. memset(&m_CallingParam,0,sizeof(m_CallingParam)); // 正常呼叫
  327. }
  328. else if (event->iEvt == USER_EVT_COMMAND_CALL)
  329. {
  330. //由指令模块触发呼叫
  331. GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE, CALLTYPE_MOBILE); // 设置呼叫模式为手机呼叫
  332. m_nSysCallType = 1;
  333. Dbg("start command call!");
  334. }
  335. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  336. {
  337. ReConnectionAssistchan();
  338. }
  339. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  340. {
  341. ReConnectionSipphone();
  342. }
  343. else if (event->iEvt == USER_EVT_STARTVIDEODISPLAY)
  344. {
  345. StartVideoDisplayEvent *e = static_cast<StartVideoDisplayEvent *>(event);
  346. StartVideo((LPCSTR)e->m_param);
  347. }
  348. else if (event->iEvt == USER_EVT_SHOWLOACALVIDEO)
  349. {
  350. ShowLocalVideoEvent *e = static_cast<ShowLocalVideoEvent *>(event);
  351. SetCallingType(NORMAL_CALLTYPE);
  352. StartVideo((LPCSTR)e->m_param);
  353. }
  354. else if (event->iEvt == USER_EVT_SHOWLOACALREMOTEVIDEO)
  355. {
  356. ShowLocalAndRemoteVideoEvent *e = static_cast<ShowLocalAndRemoteVideoEvent *>(event);
  357. SetCallingType(NORMAL_CALLTYPE);
  358. StartVideo((LPCSTR)e->m_param);
  359. }
  360. else if (event->iEvt == USER_EVT_DOUBLE_RECORD_CALL)
  361. {
  362. m_CallingParam.nCallType = DOUBLERECORD_CALLTYPE;
  363. //GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_CALLTYPE,CALLTYPE_RECORD); // 设置呼叫模式为双录呼叫
  364. m_nSysCallType = 0;
  365. Dbg("start double record call,call type is %d.", m_CallingParam.nCallType);
  366. }
  367. else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO)
  368. {
  369. Dbg("stop show local and remote video.");
  370. StopVideo();
  371. SetCallingType(NORMAL_CALLTYPE);
  372. }
  373. return 0;
  374. }
  375. void ACMCallFSM::s7_on_entry()
  376. {
  377. }
  378. void ACMCallFSM::s7_on_exit()
  379. {
  380. }
  381. unsigned int ACMCallFSM::s7_on_event(FSMEvent* event)
  382. {
  383. if (event->iEvt == USER_EVT_STOPLOCALVIDEO)
  384. {
  385. Dbg("stop show local video");
  386. StopVideo();
  387. }
  388. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  389. {
  390. ReConnectionSipphone();
  391. }
  392. return 0;
  393. }
  394. void ACMCallFSM::s9_on_entry()
  395. {
  396. Dbg("start liveness detection.");
  397. m_nLiveDetctionTime = 0;
  398. ScheduleTimer(9, 2*LIVEDETECT_CONNECT_INTERVAL);
  399. }
  400. void ACMCallFSM::s9_on_exit()
  401. {
  402. CancelTimer(9);
  403. m_nLiveDetctionTime = 0;
  404. }
  405. unsigned int ACMCallFSM::s9_on_event(FSMEvent* event)
  406. {
  407. if (event->iEvt == USER_EVT_STOPVIDEODISPLAY)
  408. {
  409. //ScheduleTimer(9,3000);
  410. Dbg("stop live detection display");
  411. StopVideo();
  412. LogEvent(Severity_Middle,LOG_EVT_RELEASELIVEDETECTION,"release live detection");
  413. }
  414. else if (event->iEvt == EVT_TIMER)
  415. {
  416. m_nLiveDetctionTime += LIVEDETECT_CONNECT_INTERVAL;
  417. if (Error_InvalidState == GetLivenessDetectionStatus()){
  418. StopLivenessDetection();
  419. }
  420. else{
  421. if (m_nLiveDetctionTime > LIVEDETECTION_TIMEOUT){
  422. Dbg("liveness detection timeout.");
  423. StopLivenessDetection();
  424. }
  425. else{
  426. ScheduleTimer(9, LIVEDETECT_CONNECT_INTERVAL);
  427. }
  428. }
  429. }
  430. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  431. {
  432. ReConnectionSipphone();
  433. }
  434. return 0;
  435. }
  436. void ACMCallFSM::s8_on_entry()
  437. {
  438. int time = GetDelayTime();
  439. Dbg("get Delay time = %d",time);
  440. if (time > 0)
  441. {
  442. ScheduleTimer(8,time*1000);
  443. }
  444. else
  445. {
  446. PostEventFIFO(new FSMEvent(EVT_TIMER));
  447. }
  448. }
  449. void ACMCallFSM::s8_on_exit()
  450. {
  451. CancelTimer(8);
  452. }
  453. unsigned int ACMCallFSM::s8_on_event(FSMEvent* event)
  454. {
  455. return 0;
  456. }
  457. void ACMCallFSM::s10_on_entry()
  458. {
  459. //LOG_FUNCTION();
  460. ErrorCodeEnum Error = Error_Succeed;
  461. if (m_nCurSipServer == Error_Server)
  462. {
  463. Error = Error_NetBroken;
  464. }
  465. if (Error != Error_Succeed)
  466. {
  467. PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
  468. }
  469. }
  470. void ACMCallFSM::s10_on_exit() {}
  471. unsigned int ACMCallFSM::s10_on_event(FSMEvent* event)
  472. {
  473. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  474. {
  475. ReConnectionAssistchan();
  476. }
  477. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  478. {
  479. ReConnectionSipphone();
  480. }
  481. else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO)
  482. {
  483. Dbg("hang up call and stop show local and remote video.");
  484. PostEventFIFO(new FSMEvent(USER_EVT_HANGUP));
  485. m_bHangup=TRUE;
  486. StopVideo();
  487. }
  488. return 0;
  489. }
  490. void ACMCallFSM::s11_on_entry()
  491. {
  492. ErrorCodeEnum Error = Error_Succeed;
  493. if (m_nCurSipServer == Error_Server)
  494. {
  495. Error = Error_NetBroken;
  496. }
  497. if (Error == Error_Succeed)
  498. {
  499. if (m_CallingParam.nCallType != NORMAL_CALLTYPE && m_CallingParam.nCallType != DOUBLERECORD_CALLTYPE)
  500. {
  501. Dbg("Begin Make Distribute Call!");
  502. Error = MakeCall(m_nCurSipServer,m_CallingParam);
  503. if (Error!=Error_Succeed)
  504. {
  505. m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
  506. }
  507. Dbg("make call result:0x%08x", Error);
  508. }
  509. else
  510. {
  511. if (NORMAL_CALLTYPE == m_CallingParam.nCallType){
  512. Dbg("Begin Make Normal Call!");
  513. }
  514. else{
  515. Dbg("Begin Make Record Call!");
  516. }
  517. Error = MakeCall(m_strHintCallNum.GetLength() > 0 ? (LPCSTR)m_strHintCallNum : (LPCSTR)m_strSIPCallNum[m_nCurSipServer],m_nCurSipServer);
  518. if (Error!=Error_Succeed)
  519. {
  520. m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
  521. }
  522. Dbg("make call result:0x%08x", Error);
  523. }
  524. }
  525. if (Error != Error_Succeed) {
  526. if (Error_NetBroken == Error || Error_TimeOut == Error){
  527. PostEventFIFO(new FSMEvent(USER_EVT_HANGUP));
  528. m_bHangup = TRUE;
  529. if (Error_TimeOut == Error){
  530. LogFatal(Severity_High, Error_TimeOut, 0, "获取IP失败,请检查机器网络!");
  531. }
  532. else{
  533. LogFatal(Severity_High, Error_NetBroken, 0, "系统故障,尝试恢复中(预计90s内),请稍等!");
  534. }
  535. }
  536. else{
  537. PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
  538. }
  539. }
  540. else
  541. {
  542. ScheduleTimer(11,SIP_CALL_TIMER);
  543. }
  544. }
  545. void ACMCallFSM::s11_on_exit()
  546. {
  547. CancelTimer(11);
  548. }
  549. unsigned int ACMCallFSM::s11_on_event(FSMEvent* event)
  550. {
  551. if (event->iEvt == USER_EVT_HANGUP)
  552. {
  553. m_bHangup = TRUE;
  554. }
  555. else if (event->iEvt == USER_EVT_SIP_STATE_IDLE)
  556. {
  557. m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
  558. m_nSipErrorNum++;
  559. //StopChannel();
  560. }
  561. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  562. {
  563. ReConnectionAssistchan();
  564. }
  565. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  566. {
  567. ReConnectionSipphone();
  568. }
  569. else if (event->iEvt == EVT_TIMER)
  570. {
  571. Dbg("sip call timeout,release call");
  572. m_nSipErrorNum++;
  573. }
  574. else if (event->iEvt == USER_EVT_JMP_FAIL)
  575. {
  576. m_nSipErrorNum++;
  577. }
  578. else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO)
  579. {
  580. Dbg("hang up call and stop show local and remote video.");
  581. PostEventFIFO(new FSMEvent(USER_EVT_HANGUP));
  582. m_bHangup=TRUE;
  583. StopVideo();
  584. }
  585. return 0;
  586. }
  587. void ACMCallFSM::s12_on_entry()
  588. {
  589. ErrorCodeEnum Error = Error_Succeed;
  590. if (m_nCurChanServer == Error_Server)
  591. {
  592. Error = Error_NetBroken;
  593. }
  594. m_nSipErrorNum = 0;
  595. Sleep(200);
  596. if (Error == Error_Succeed)
  597. {
  598. Dbg("begin start channel,m_nCurChanServer=%d",m_nCurChanServer);
  599. if (m_CallingParam.nCallType == NORMAL_CALLTYPE && m_CallingParam.nCallType != DOUBLERECORD_CALLTYPE)
  600. {
  601. Error = StartChannel(m_nCurChanServer);
  602. }
  603. else
  604. {
  605. Error = StartChannel(m_nCurChanServer,m_CallingParam);
  606. if (DOUBLERECORD_CALLTYPE == m_CallingParam.nCallType){
  607. if (FALSE == m_bHandFree){
  608. StopSpeakerAudioCapture();
  609. Dbg("double record call type, current is pick up mode, stop speaker audio capture.");
  610. }
  611. }
  612. }
  613. Dbg("start channel result:0x%08x", Error);
  614. if (Error != Error_Succeed)
  615. {
  616. Dbg("start channel failed:0x%08x,start hangup", Error);
  617. HangupCall();
  618. m_nCurChanServer?(m_nCurChanServer=Error_Server):(m_nCurChanServer=BACK_SERVER);
  619. Dbg("hangup call result:0x%08x", Error);
  620. }
  621. }
  622. if (Error != Error_Succeed)
  623. {
  624. PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
  625. }
  626. }
  627. void ACMCallFSM::s12_on_exit() {}
  628. unsigned int ACMCallFSM::s12_on_event(FSMEvent* event)
  629. {
  630. if (event->iEvt == USER_EVT_HANGUP)
  631. {
  632. m_bHangup = TRUE;
  633. }
  634. else if (event->iEvt == USER_EVT_SIP_STATE_IDLE)
  635. {
  636. m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
  637. StopChannel();
  638. }
  639. else if (event->iEvt == USER_EVT_CHAN_STATE_IDLE)
  640. {
  641. if (!m_bHangup)
  642. {
  643. m_nCurChanServer?(m_nCurChanServer=Error_Server):(m_nCurChanServer=BACK_SERVER);
  644. }
  645. HangupCall();
  646. //StopVideo();
  647. }
  648. else if (event->iEvt == USER_EVT_CHAN_STATE_CONNECTED)
  649. {
  650. ChanStateConnectedEvent *e = static_cast<ChanStateConnectedEvent *>(event);
  651. StartVideo((LPCSTR)e->m_param);
  652. }
  653. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  654. {
  655. ReConnectionAssistchan();
  656. }
  657. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  658. {
  659. ReConnectionSipphone();
  660. }
  661. else if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO)
  662. {
  663. Dbg("hang up call and stop show local and remote video.");
  664. PostEventFIFO(new FSMEvent(USER_EVT_HANGUP));
  665. m_bHangup=TRUE;
  666. StopVideo();
  667. }
  668. return 0;
  669. }
  670. void ACMCallFSM::s13_on_entry()
  671. {
  672. if (m_bHandFree)
  673. {
  674. PostEventLIFO(new FSMEvent(USER_EVT_JMP_HANDFREE));
  675. }
  676. else
  677. {
  678. PostEventLIFO(new FSMEvent(USER_EVT_JMP_PICKUP));
  679. }
  680. }
  681. void ACMCallFSM::s13_on_exit() {}
  682. unsigned int ACMCallFSM::s13_on_event(FSMEvent* event)
  683. {
  684. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  685. {
  686. ReConnectionAssistchan();
  687. }
  688. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  689. {
  690. ReConnectionSipphone();
  691. }
  692. return 0;
  693. }
  694. void ACMCallFSM::s14_on_entry()
  695. {
  696. }
  697. void ACMCallFSM::s14_on_exit()
  698. {
  699. }
  700. unsigned int ACMCallFSM::s14_on_event(FSMEvent* event)
  701. {
  702. if (event->iEvt == USER_EVT_STOPLOACALREMOTEVIDEO)
  703. {
  704. Dbg("stop show local and remote video.");
  705. StopVideo();
  706. }
  707. else if (event->iEvt == USER_EVT_STOP_RECORD_BROADCAST)
  708. {
  709. Dbg("stop double record broadcast.");
  710. }
  711. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  712. {
  713. ReConnectionSipphone();
  714. }
  715. return 0;
  716. }
  717. void ACMCallFSM::s20_on_entry()
  718. {
  719. StopChannel();
  720. }
  721. void ACMCallFSM::s20_on_exit() {}
  722. unsigned int ACMCallFSM::s20_on_event(FSMEvent* event)
  723. {
  724. if (event->iEvt == USER_EVT_CHAN_STATE_IDLE)
  725. {
  726. StopVideo();
  727. }
  728. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  729. {
  730. ReConnectionAssistchan();
  731. }
  732. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  733. {
  734. ReConnectionSipphone();
  735. }
  736. return 0;
  737. }
  738. void ACMCallFSM::s21_on_entry()
  739. {
  740. ScheduleTimer(21,RELEASEING_SIP_TIMER);
  741. HangupCall();
  742. }
  743. void ACMCallFSM::s21_on_exit()
  744. {
  745. CancelTimer(21);
  746. CancelTimer(210);
  747. }
  748. unsigned int ACMCallFSM::s21_on_event(FSMEvent* event)
  749. {
  750. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  751. {
  752. ReConnectionAssistchan();
  753. }
  754. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  755. {
  756. ReConnectionSipphone();
  757. }
  758. else if (event->iEvt == EVT_TIMER)
  759. {
  760. if(event->param1 == 21)
  761. {
  762. Dbg("hangupcall timeout,release call");
  763. ScheduleTimer(210,RELEASEING_SIP_TIMEOUT);
  764. ReleaseCall(0);
  765. }
  766. else if (event->param1 == 210)
  767. {
  768. Dbg("release call timeout,restart sipphone");
  769. PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
  770. //重启mod_sipphone
  771. //RealSipErrorCheck();
  772. LogEvent(Severity_High,EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone ");
  773. }
  774. }
  775. return 0;
  776. }
  777. void ACMCallFSM::s22_on_entry()
  778. {
  779. StopChannel();
  780. }
  781. void ACMCallFSM::s22_on_exit() {}
  782. unsigned int ACMCallFSM::s22_on_event(FSMEvent* event)
  783. {
  784. if (event->iEvt == USER_EVT_CHAN_STATE_IDLE)
  785. {
  786. StopVideo();
  787. }
  788. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  789. {
  790. ReConnectionAssistchan();
  791. }
  792. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  793. {
  794. ReConnectionSipphone();
  795. }
  796. return 0;
  797. }
  798. void ACMCallFSM::s23_on_entry()
  799. {
  800. if((!m_bHangup)&&(((m_nCurSipServer==BACK_SERVER)&&(m_nCurChanServer!=Error_Server))||((m_nCurChanServer==BACK_SERVER)&&(m_nCurSipServer!=Error_Server))))
  801. {
  802. PostEventLIFO(new FSMEvent(USER_EVT_RECONNECT));
  803. }
  804. else
  805. {
  806. ScheduleTimer(23, RELEASEING_TIMER_INTERVAL);
  807. }
  808. }
  809. void ACMCallFSM::s23_on_exit()
  810. {
  811. CancelTimer(23);
  812. }
  813. unsigned int ACMCallFSM::s23_on_event(FSMEvent* event)
  814. {
  815. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  816. {
  817. ReConnectionAssistchan();
  818. }
  819. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  820. {
  821. ReConnectionSipphone();
  822. }
  823. else if (event->iEvt == EVT_TIMER)
  824. {
  825. if (m_nSipErrorNum >= SIP_CONNECT_FAIL_TIMES)
  826. {
  827. m_nSipErrorNum = 0;
  828. //RealSipErrorCheck();
  829. LogEvent(Severity_High,EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone ");
  830. }
  831. }
  832. return 0;
  833. }
  834. void ACMCallFSM::s24_on_entry()
  835. {
  836. ScheduleTimer(24, RELEASEING_TIMER_INTERVAL);
  837. }
  838. void ACMCallFSM::s24_on_exit()
  839. {
  840. CancelTimer(24);
  841. }
  842. unsigned int ACMCallFSM::s24_on_event(FSMEvent* event)
  843. {
  844. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  845. {
  846. ReConnectionAssistchan();
  847. }
  848. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  849. {
  850. ReConnectionSipphone();
  851. }
  852. return 0;
  853. }
  854. void ACMCallFSM::s3_on_entry() {}
  855. void ACMCallFSM::s3_on_exit() {}
  856. unsigned int ACMCallFSM::s3_on_event(FSMEvent* event)
  857. {
  858. //LOG_TRACE("ACMCallFSM::s3_on_event, id = %d", event->iEvt);
  859. if (event->iEvt == USER_EVT_TO_HANDFREE)
  860. {
  861. //m_bHandFree = TRUE;
  862. }
  863. else if (event->iEvt == USER_EVT_TO_PICKUP)
  864. {
  865. //m_bHandFree = FALSE;
  866. }
  867. else if (event->iEvt == USER_EVT_SIP_STATE_IDLE)
  868. {
  869. StopChannel();
  870. }
  871. else if (event->iEvt == USER_EVT_CHAN_STATE_IDLE)
  872. {
  873. HangupCall();
  874. StopVideo();
  875. }
  876. else if (event->iEvt == USER_EVT_AGENT_WRITABLE)
  877. {
  878. AllowAgentWrite();
  879. }
  880. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  881. {
  882. ReConnectionAssistchan();
  883. }
  884. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  885. {
  886. ReConnectionSipphone();
  887. }
  888. return 0;
  889. }
  890. void ACMCallFSM::s4_on_entry() {}
  891. void ACMCallFSM::s4_on_exit() {}
  892. unsigned int ACMCallFSM::s4_on_event(FSMEvent* event)
  893. {
  894. if (event->iEvt == USER_EVT_TO_HANDFREE)
  895. {
  896. //m_bHandFree = TRUE;
  897. }
  898. else if (event->iEvt == USER_EVT_TO_PICKUP)
  899. {
  900. //m_bHandFree = FALSE;
  901. }
  902. else if (event->iEvt == USER_EVT_SIP_STATE_IDLE) {
  903. StopChannel();
  904. } else if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) {
  905. HangupCall();
  906. StopVideo();
  907. } else if (event->iEvt == USER_EVT_AGENT_WRITABLE) {
  908. AllowAgentWrite();
  909. }
  910. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  911. {
  912. ReConnectionAssistchan();
  913. }
  914. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  915. {
  916. ReConnectionSipphone();
  917. }
  918. return 0;
  919. }
  920. void ACMCallFSM::s50_on_entry() {}
  921. void ACMCallFSM::s50_on_exit() {}
  922. unsigned int ACMCallFSM::s50_on_event(FSMEvent* event)
  923. {
  924. if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) {
  925. StopVideo();
  926. }
  927. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  928. {
  929. ReConnectionAssistchan();
  930. }
  931. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  932. {
  933. ReConnectionSipphone();
  934. }
  935. return 0;
  936. }
  937. void ACMCallFSM::s51_on_entry() {}
  938. void ACMCallFSM::s51_on_exit() {}
  939. unsigned int ACMCallFSM::s51_on_event(FSMEvent* event)
  940. {
  941. if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) {
  942. StopVideo();
  943. }
  944. return 0;
  945. }
  946. void ACMCallFSM::s52_on_entry()
  947. {
  948. ScheduleTimer(52,RELEASEING_SIP_TIMER);
  949. }
  950. void ACMCallFSM::s52_on_exit()
  951. {
  952. CancelTimer(52);
  953. CancelTimer(520);
  954. }
  955. unsigned int ACMCallFSM::s52_on_event(FSMEvent* event)
  956. {
  957. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  958. {
  959. ReConnectionAssistchan();
  960. }
  961. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  962. {
  963. ReConnectionSipphone();
  964. }
  965. else if (event->iEvt == EVT_TIMER)
  966. {
  967. if (event->param1 == 52)
  968. {
  969. ScheduleTimer(520,RELEASEING_SIP_TIMEOUT);
  970. Dbg("sip finished timeout,release call");
  971. ReleaseCall(0);
  972. }
  973. else if (event->param1 == 520)
  974. {
  975. Dbg("release call timeout,restart sipphone");
  976. PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
  977. //重启mod_sipphone
  978. //RealSipErrorCheck();
  979. LogEvent(Severity_High,EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone ");
  980. }
  981. }
  982. return 0;
  983. }
  984. void ACMCallFSM::s53_on_entry()
  985. {
  986. ScheduleTimer(53, RELEASEING_TIMER_INTERVAL);
  987. }
  988. void ACMCallFSM::s53_on_exit()
  989. {
  990. CancelTimer(53);
  991. }
  992. unsigned int ACMCallFSM::s53_on_event(FSMEvent* event)
  993. {
  994. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  995. {
  996. ReConnectionAssistchan();
  997. }
  998. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  999. {
  1000. ReConnectionSipphone();
  1001. }
  1002. else if (event->iEvt == EVT_TIMER)
  1003. {
  1004. if (m_nSipErrorNum >= SIP_CONNECT_FAIL_TIMES)
  1005. {
  1006. m_nSipErrorNum = 0;
  1007. //RealSipErrorCheck();
  1008. LogEvent(Severity_High,EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone ");
  1009. }
  1010. }
  1011. return 0;
  1012. }
  1013. void ACMCallFSM::s60_on_entry()
  1014. {
  1015. StopChannel();
  1016. HangupCall();
  1017. }
  1018. void ACMCallFSM::s60_on_exit() {}
  1019. unsigned int ACMCallFSM::s60_on_event(FSMEvent* event)
  1020. {
  1021. if (event->iEvt == USER_EVT_CHAN_STATE_IDLE)
  1022. {
  1023. StopVideo();
  1024. }
  1025. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  1026. {
  1027. ReConnectionAssistchan();
  1028. }
  1029. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  1030. {
  1031. ReConnectionSipphone();
  1032. }
  1033. return 0;
  1034. }
  1035. void ACMCallFSM::s61_on_entry() {}
  1036. void ACMCallFSM::s61_on_exit() {}
  1037. unsigned int ACMCallFSM::s61_on_event(FSMEvent* event)
  1038. {
  1039. if (event->iEvt == USER_EVT_CHAN_STATE_IDLE) {
  1040. StopVideo();
  1041. }
  1042. else if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  1043. {
  1044. ReConnectionAssistchan();
  1045. }
  1046. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  1047. {
  1048. ReConnectionSipphone();
  1049. }
  1050. return 0;
  1051. }
  1052. void ACMCallFSM::s62_on_entry()
  1053. {
  1054. ScheduleTimer(62,RELEASEING_SIP_TIMER);
  1055. }
  1056. void ACMCallFSM::s62_on_exit()
  1057. {
  1058. CancelTimer(62);
  1059. CancelTimer(620);
  1060. }
  1061. unsigned int ACMCallFSM::s62_on_event(FSMEvent* event)
  1062. {
  1063. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  1064. {
  1065. ReConnectionAssistchan();
  1066. }
  1067. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  1068. {
  1069. ReConnectionSipphone();
  1070. }
  1071. else if (event->iEvt == EVT_TIMER)
  1072. {
  1073. if (event->param1 == 62)
  1074. {
  1075. ScheduleTimer(620,RELEASEING_SIP_TIMEOUT);
  1076. Dbg("sip hangup timeout,release call");
  1077. ReleaseCall(0);
  1078. }
  1079. else if (event->param1 == 620)
  1080. {
  1081. Dbg("release call timeout,restart sipphone");
  1082. PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
  1083. //重启mod_sipphone
  1084. //RealSipErrorCheck();
  1085. LogEvent(Severity_High,EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone ");
  1086. }
  1087. }
  1088. return 0;
  1089. }
  1090. void ACMCallFSM::s63_on_entry()
  1091. {
  1092. ScheduleTimer(63, RELEASEING_TIMER_INTERVAL);
  1093. }
  1094. void ACMCallFSM::s63_on_exit()
  1095. {
  1096. CancelTimer(63);
  1097. }
  1098. unsigned int ACMCallFSM::s63_on_event(FSMEvent* event)
  1099. {
  1100. if (event->iEvt == USER_EVT_ASSISTCHAN_IDEL)
  1101. {
  1102. ReConnectionAssistchan();
  1103. }
  1104. else if (event->iEvt == USER_EVT_SIPPHONE_IDEL)
  1105. {
  1106. ReConnectionSipphone();
  1107. }
  1108. else if (event->iEvt == EVT_TIMER)
  1109. {
  1110. if (m_nSipErrorNum >= SIP_CONNECT_FAIL_TIMES)
  1111. {
  1112. m_nSipErrorNum = 0;
  1113. //RealSipErrorCheck();
  1114. LogEvent(Severity_High,EVENT_MOD_RELEASESIP_TIMEOUT,"restart sipphone ");
  1115. }
  1116. }
  1117. return 0;
  1118. }
  1119. int ACMCallFSM::TranslateState( int innerState )
  1120. {
  1121. switch (innerState) {
  1122. case s0:
  1123. return eState_Offline;
  1124. case s8:
  1125. case s10:
  1126. case s11:
  1127. case s12:
  1128. case s13:
  1129. return eState_Connecting;
  1130. case s20:
  1131. case s21:
  1132. case s22:
  1133. case s23:
  1134. case s24:
  1135. return eState_Fail;
  1136. case s3:
  1137. return eState_HandFree;
  1138. case s4:
  1139. return eState_Pickup;
  1140. case s50:
  1141. case s51:
  1142. case s52:
  1143. case s53:
  1144. return eState_Broken;
  1145. case s7:
  1146. case s14:
  1147. case s60:
  1148. case s61:
  1149. case s62:
  1150. case s63:
  1151. return eState_Releasing;
  1152. case s9:
  1153. return eState_LiveDetect;
  1154. default:
  1155. assert(0);
  1156. return 0;
  1157. }
  1158. }