Monitor.cpp
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:11k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. // Monitor.cpp : Defines the class behaviors for the application.
  2. //
  3. #include "stdafx.h"
  4. #include "Monitor.h"
  5. #include "VideoUSB.h"
  6. #include "MonitorDialog.h"
  7. #include "ConectDialog.h"
  8. #include <afxmt.h>
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CMonitorApp
  16. BEGIN_MESSAGE_MAP(CMonitorApp, CWinApp)
  17. //{{AFX_MSG_MAP(CMonitorApp)
  18. //}}AFX_MSG
  19. END_MESSAGE_MAP()
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CMonitorApp construction
  22. CMonitorApp::CMonitorApp()
  23. {
  24. this->appIni = "";
  25. this->IP = "";
  26. this->Port = 0;
  27. this->userName = "";
  28. this->password = "";
  29. this->user_id = 0;
  30. this->hlogWnd = NULL;
  31. }
  32. /////////////////////////////////////////////////////////////////////////////
  33. // The one and only CMonitorApp object
  34. CMonitorApp theApp;
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CMonitorApp initialization
  37. BOOL CMonitorApp::InitInstance()
  38. {   
  39. this->SetAutoRun( );
  40. //读取服务器IP
  41. ::GetPrivateProfileString( "服务器信息" , "服务器IP" , "" , this->IP.GetBufferSetLength( MAX_PATH ) , MAX_PATH , this->appIni );
  42. this->IP.ReleaseBuffer( );
  43. //读取端口
  44. this->Port = ::GetPrivateProfileInt( "服务器信息" , "服务器端口" , 0 , this->appIni );
  45.     //读取用户名
  46. ::GetPrivateProfileString( "用户信息" , "用户名" , "" , this->userName.GetBufferSetLength( MAX_PATH ) , MAX_PATH , this->appIni );
  47. this->userName.ReleaseBuffer( );
  48.     //读取用户密码
  49. ::GetPrivateProfileString( "用户信息" , "密码" , "" , this->password.GetBufferSetLength( MAX_PATH ) , MAX_PATH , this->appIni );
  50. this->password.ReleaseBuffer( );
  51. CMonitorDialog dlg;
  52.     //互斥量,规定同时只能运行一个实例
  53. CMutex mutex( false , "深圳赛力视频监控系统监控客户端" );
  54. CSingleLock slock( &mutex );
  55. if( ! slock.Lock( 0 ) )
  56. {
  57. CWnd::FindWindow( "#32770" , "视频监控系统" )->SetForegroundWindow( );
  58. return false;
  59. }//日志窗口    
  60. if( ::GetPrivateProfileInt( "用户信息" , "日志窗口" , 0 , this->appIni ) )
  61. {
  62. this->hlogWnd = CreateLogWnd( NULL , NULL );
  63. CWnd::FromHandle( this->hlogWnd )->SetWindowText( "视频会议监控客户端日志信息" );
  64. }
  65. m_pMainWnd = &dlg;
  66. //启动监控窗口
  67. dlg.DoModal( );
  68. //关闭命令通道
  69. this->cmdTCP.Close( );
  70. INT_PTR_MAP::iterator itr;
  71. //清除显示视频内存
  72. while( ! this->recv_video_map.empty( ) ) ::Sleep( 100 );
  73.     
  74. ::WriteLog( this->GetLogHwnd( ) , "用户退出程序" );
  75. ::SaveLog( this->hlogWnd , this->appIni.Left( this->appIni.ReverseFind( '\' ) + 1 ) + "监控日志.txt" );
  76. ::DestroyLogWnd( this->hlogWnd );
  77. return FALSE;
  78. }
  79. void CMonitorApp::SetAutoRun( void )
  80. {
  81. CString name;
  82. ::GetModuleFileName( NULL , name.GetBufferSetLength( MAX_PATH ) , MAX_PATH );
  83. name.ReleaseBuffer( );
  84. HKEY key;
  85. ::RegOpenKey( HKEY_LOCAL_MACHINE , "Software\Microsoft\Windows\CurrentVersion\Run" , &key );
  86. ::RegSetValueEx( key , "视频监控" , 0 , REG_SZ , ( const unsigned char * )( const char * )name , name.GetLength( ) );
  87. ::RegCloseKey( key );
  88. this->appIni = name.Left( name.ReverseFind( '\' ) + 1 ) + "monitor.ini";
  89. }
  90. //等待连接
  91. void CMonitorApp::OnInit( void * pContext )
  92. {
  93. CConectDialog * dlg = ( CConectDialog * )pContext;
  94.     //等待窗口出来
  95. while( ! ::IsWindow( dlg->GetSafeHwnd( ) ) ) ::Sleep( 1000 );
  96. PChannelType cType;
  97. PRegisterRES res;
  98. for( ;; )
  99. {   //先等待一秒  
  100. ::Sleep( 1000 );
  101.      //如果连接失败
  102. if( ! theApp.cmdTCP.Connect( theApp.IP , theApp.Port ) && dlg->GetSafeHwnd( ) )
  103. continue;
  104.         //如果是因为窗口退出的,那么直接返回 
  105. if( ! theApp.cmdTCP.IsConnected( ) ) return;
  106. //发送命令通道标志
  107. cType.assembleData( PChannelType::COMMAND , 0 );
  108. if( theApp.cmdTCP.Send( cType.buffer ) )
  109. { //用户注册
  110. PRegisterREQ req;
  111. req.assembleData( ( char * )( const char * )theApp.userName , ( char * )( const char * )theApp.password , PRegisterREQ::MONITOR );
  112. //发送用户注册和接收用户注册回复
  113. struct timeval tm = { 5 , 0 };
  114. if(  theApp.cmdTCP.Send( req.buffer ) && theApp.cmdTCP.Receive( res.buffer , &tm ) && res.buffer.GetSize( ) && res.parseData( res.buffer ) && ! res.ireturn )
  115. break;
  116. }//循环连接
  117. theApp.cmdTCP.Close( );
  118. }//有内存数据
  119. ::WriteLog( theApp.GetLogHwnd( ) , "用户 %s 注册到服务器 %s 成功,连接视频通道" , theApp.userName , theApp.IP );
  120. //先关闭窗口
  121. if( ::IsWindow( dlg->GetSafeHwnd( ) ) )
  122. {
  123. dlg->m_return = res.ireturn;
  124. dlg->SendMessage( WM_CLOSE );
  125. }//发送成功,开始启动线程
  126. if( res.parseData( res.buffer ) && ! res.ireturn )
  127. {
  128. theApp.user_id = res.user_id;
  129. //连接视频通道
  130. theApp.videoTCP.Connect( theApp.IP , theApp.Port );
  131. cType.assembleData( PChannelType::VIDEO , theApp.user_id );
  132. theApp.videoTCP.Send( cType.buffer );
  133. PVideoData vd;
  134. //发送视频头
  135. vd.assembleData( theApp.user_id , 0 , PVideoData::VIDEO_HEADER , 0 , 0 );
  136. theApp.videoTCP.Send( vd.buffer );
  137. //有可能运行失败
  138. CThread::Run( CMonitorApp::OnCommand , &theApp );
  139. //有可能运行失败
  140. CThread::Run( CMonitorApp::OnVideo , &theApp );
  141. }
  142. }
  143. //测试网络连接数据包
  144. void CMonitorApp::SendTestConnect( void )
  145. {
  146. if( this->videoTCP.IsConnected( ) )
  147. {
  148. PConnectTest test;
  149. test.assembleData( this->user_id );
  150. this->cmdTCP.Send( test.buffer );
  151. }
  152. }
  153. //接收命令
  154. void CMonitorApp::OnCommand( void * pContext )
  155. {   //请求在线用户列表
  156. POnlineUserREQ req;
  157. req.assembleData( );
  158. theApp.cmdTCP.Send( req.buffer );
  159. CBuffer buffer;
  160. //2个数据包之间最大的时间间隔是5分钟
  161. struct timeval tm = { 300 , 0 };
  162.     //接收名命令包
  163. while( theApp.cmdTCP.Receive( buffer /* , &tm */ ) )
  164. {
  165. if( ! buffer.GetSize( ) )
  166. break;
  167. try
  168. {
  169. switch( *( int * )( buffer.GetBuffer( ) + INT_SIZE ) )
  170. {//在先用户状态
  171. case POnlineUserRESTAG : theApp.OnlineUser( buffer ); break;
  172.  //窗口控制
  173. case PPanelCommandTAG : theApp.OnWindow( buffer ); break;
  174. }
  175. }
  176. catch( ... )
  177. {
  178. }
  179. }
  180. ::WriteLog( theApp.GetLogHwnd( ) , "失去了与服务器的连接,原因是 %d" , ::WSAGetLastError( ) );
  181. theApp.videoTCP.Close( );
  182. while( ! theApp.recv_video_map.empty( ) ) ::Sleep( 100 );
  183. theApp.cmdTCP.Close( );
  184. if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) )
  185. {
  186. ::WriteLog( theApp.GetLogHwnd( ) , "重新连接服务器" );
  187.         
  188. theApp.m_pMainWnd->PostMessage( WM_CONNECT_MESSAGE );
  189. }
  190. }
  191. //在线用户回复
  192. void CMonitorApp::OnlineUser( CBuffer & buffer )
  193. {
  194. if( ! ::IsWindow( this->m_pMainWnd->GetSafeHwnd( ) ) )
  195. return;
  196. POnlineUserRES res;
  197. res.parseData( buffer );
  198.     //用户在线
  199. if( ! res.user_name.empty( ) )
  200. {   
  201. int id = ( int )::GetPrivateProfileInt( "监控点=窗口号" , res.user_name.c_str( ) , 0 , theApp.appIni ) -1;
  202. if( id >= 0 && id <= 9 && this->m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&res , ( LPARAM ) id ) )
  203. {//发送请求视频数据
  204. PRecvVideoREQ req;
  205. req.assembleData( res.user_id );
  206. this->cmdTCP.Send( req.buffer );
  207. ::WriteLog( this->GetLogHwnd( ) , "程序请求 %s 的视频数据,id : %d" , res.user_name.c_str( ) , res.user_id );
  208. }
  209. }//用户离线
  210. else if( ! this->recv_video_map.empty( ) )
  211. {
  212. INT_PTR_MAP::iterator itr = this->recv_video_map.find( res.user_id );
  213. //如果显示用户信息还存在
  214. if( itr != this->recv_video_map.end( ) )
  215. { //发送用户离线通知
  216. this->m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&res );
  217. //标志删除用户 
  218. this->videoTCP.SetData( res.user_id );
  219. //延时1秒钟
  220. ::Sleep( 1000 );
  221. CVideoUSB * v = ( CVideoUSB * )itr->second;
  222. //删除该用户的视频显示信息 
  223. this->recv_video_map.erase( itr );
  224. delete v;
  225. //恢复工作
  226. theApp.videoTCP.SetData( 0 );
  227. ::WriteLog( this->GetLogHwnd( ) , "id号为%d的用户停止发送数据" , res.user_id );
  228. }
  229. }
  230. }
  231. //窗口控制
  232. void CMonitorApp::OnWindow( CBuffer & buffer )
  233. {
  234. if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) )
  235. {
  236. PPanelCommand cmd;
  237. cmd.parseData( buffer );
  238. this->m_pMainWnd->SendMessage( WM_WINDOW , ( WPARAM )&cmd );
  239. }
  240. }
  241. //接收视频
  242. void CMonitorApp::OnVideo( void * pContext )
  243. {
  244. INT_PTR_MAP::iterator itr;
  245. PVideoData vd;
  246. while( theApp.videoTCP.Receive( vd.buffer ) )
  247. {
  248. if( ! vd.buffer.GetSize( ) )
  249. continue;
  250. try
  251. {
  252. vd.parseData( vd.buffer );
  253. switch( vd.type )
  254. {
  255. case PVideoData::VIDEO_HEADER : 
  256. {
  257. CVideoUSB * video = NULL;
  258. if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) && ( video =( CVideoUSB * )theApp.m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&vd ) ) )
  259. {
  260. ::WriteLog( theApp.GetLogHwnd( ) , "收到 id号为 %d 的视频数据" , vd.user_id );
  261. while( theApp.videoTCP.GetData( ) ) ::Sleep( 1000 );
  262. theApp.recv_video_map[ vd.user_id ] = video;
  263. }
  264. else //显示失败,停止接收视频数据
  265. {
  266. ::WriteLog( theApp.GetLogHwnd( ) , "初始化 id号为 %d 的视频数据失败,停止接收该用户的视频数据" , vd.user_id );
  267. PStopVideoREQ req;
  268. req.assembleData( vd.user_id );
  269. theApp.cmdTCP.Send( req.buffer );
  270. }
  271. }
  272. break;
  273. case PVideoData::VIDEO_DATA : 
  274. //保证视频链表没有改动并且找到了用户
  275. if( ! theApp.videoTCP.GetData( ) && ! theApp.recv_video_map.empty( ) && ( itr = theApp.recv_video_map.find( vd.user_id ) ) != theApp.recv_video_map.end( ) )
  276. {
  277. CVideoUSB * video = ( CVideoUSB * )( itr->second );
  278.                     
  279. if( ! video->Draw(  vd.video , vd.size ) )
  280. {  
  281. ::WriteLog( theApp.GetLogHwnd( ) , "显示 id号为 %d 的视频数据失败,停止接收该用户的视频数据" , vd.user_id );
  282. //显示失败停止接收视频
  283. PStopVideoREQ req;
  284. req.assembleData( vd.user_id );
  285. theApp.cmdTCP.Send( req.buffer );
  286. theApp.recv_video_map.erase( itr );
  287. delete video;
  288. POnlineUserRES res;
  289. res.user_id = vd.user_id;
  290. if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) )
  291. theApp.m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&res );
  292. }//改变该窗口状态标志
  293. else if( ::IsWindow( video->GetSafeHwnd( ) ) && video->GetDlgCtrlID( ) != 2 )
  294. video->SetDlgCtrlID( 2 );
  295. }
  296. break;
  297. }
  298. }
  299. catch( ... )
  300. {
  301. }
  302. }
  303. //清除显示视频内存
  304. try
  305. {
  306. while( theApp.videoTCP.GetData( ) ) ::Sleep( 100 );
  307. while( ! theApp.recv_video_map.empty( ) )
  308. {
  309. itr = theApp.recv_video_map.begin( );
  310. CVideoUSB * video = ( CVideoUSB * )itr->second;
  311. theApp.recv_video_map.erase( itr );
  312. delete video;
  313. }
  314. }
  315. catch( ... )
  316. {
  317. }
  318. ::WriteLog( theApp.GetLogHwnd( ) , "视频线程退出,退出原因是 %d ,关闭命令通道连接n" , ::WSAGetLastError( ) );
  319. theApp.cmdTCP.Close( );
  320. }