Monitor.cpp
资源名称:视频会议系统.rar [点击查看]
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:11k
源码类别:
IP电话/视频会议
开发平台:
Visual C++
- // Monitor.cpp : Defines the class behaviors for the application.
- //
- #include "stdafx.h"
- #include "Monitor.h"
- #include "VideoUSB.h"
- #include "MonitorDialog.h"
- #include "ConectDialog.h"
- #include <afxmt.h>
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CMonitorApp
- BEGIN_MESSAGE_MAP(CMonitorApp, CWinApp)
- //{{AFX_MSG_MAP(CMonitorApp)
- //}}AFX_MSG
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CMonitorApp construction
- CMonitorApp::CMonitorApp()
- {
- this->appIni = "";
- this->IP = "";
- this->Port = 0;
- this->userName = "";
- this->password = "";
- this->user_id = 0;
- this->hlogWnd = NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // The one and only CMonitorApp object
- CMonitorApp theApp;
- /////////////////////////////////////////////////////////////////////////////
- // CMonitorApp initialization
- BOOL CMonitorApp::InitInstance()
- {
- this->SetAutoRun( );
- //读取服务器IP
- ::GetPrivateProfileString( "服务器信息" , "服务器IP" , "" , this->IP.GetBufferSetLength( MAX_PATH ) , MAX_PATH , this->appIni );
- this->IP.ReleaseBuffer( );
- //读取端口
- this->Port = ::GetPrivateProfileInt( "服务器信息" , "服务器端口" , 0 , this->appIni );
- //读取用户名
- ::GetPrivateProfileString( "用户信息" , "用户名" , "" , this->userName.GetBufferSetLength( MAX_PATH ) , MAX_PATH , this->appIni );
- this->userName.ReleaseBuffer( );
- //读取用户密码
- ::GetPrivateProfileString( "用户信息" , "密码" , "" , this->password.GetBufferSetLength( MAX_PATH ) , MAX_PATH , this->appIni );
- this->password.ReleaseBuffer( );
- CMonitorDialog dlg;
- //互斥量,规定同时只能运行一个实例
- CMutex mutex( false , "深圳赛力视频监控系统监控客户端" );
- CSingleLock slock( &mutex );
- if( ! slock.Lock( 0 ) )
- {
- CWnd::FindWindow( "#32770" , "视频监控系统" )->SetForegroundWindow( );
- return false;
- }//日志窗口
- if( ::GetPrivateProfileInt( "用户信息" , "日志窗口" , 0 , this->appIni ) )
- {
- this->hlogWnd = CreateLogWnd( NULL , NULL );
- CWnd::FromHandle( this->hlogWnd )->SetWindowText( "视频会议监控客户端日志信息" );
- }
- m_pMainWnd = &dlg;
- //启动监控窗口
- dlg.DoModal( );
- //关闭命令通道
- this->cmdTCP.Close( );
- INT_PTR_MAP::iterator itr;
- //清除显示视频内存
- while( ! this->recv_video_map.empty( ) ) ::Sleep( 100 );
- ::WriteLog( this->GetLogHwnd( ) , "用户退出程序" );
- ::SaveLog( this->hlogWnd , this->appIni.Left( this->appIni.ReverseFind( '\' ) + 1 ) + "监控日志.txt" );
- ::DestroyLogWnd( this->hlogWnd );
- return FALSE;
- }
- void CMonitorApp::SetAutoRun( void )
- {
- CString name;
- ::GetModuleFileName( NULL , name.GetBufferSetLength( MAX_PATH ) , MAX_PATH );
- name.ReleaseBuffer( );
- HKEY key;
- ::RegOpenKey( HKEY_LOCAL_MACHINE , "Software\Microsoft\Windows\CurrentVersion\Run" , &key );
- ::RegSetValueEx( key , "视频监控" , 0 , REG_SZ , ( const unsigned char * )( const char * )name , name.GetLength( ) );
- ::RegCloseKey( key );
- this->appIni = name.Left( name.ReverseFind( '\' ) + 1 ) + "monitor.ini";
- }
- //等待连接
- void CMonitorApp::OnInit( void * pContext )
- {
- CConectDialog * dlg = ( CConectDialog * )pContext;
- //等待窗口出来
- while( ! ::IsWindow( dlg->GetSafeHwnd( ) ) ) ::Sleep( 1000 );
- PChannelType cType;
- PRegisterRES res;
- for( ;; )
- { //先等待一秒
- ::Sleep( 1000 );
- //如果连接失败
- if( ! theApp.cmdTCP.Connect( theApp.IP , theApp.Port ) && dlg->GetSafeHwnd( ) )
- continue;
- //如果是因为窗口退出的,那么直接返回
- if( ! theApp.cmdTCP.IsConnected( ) ) return;
- //发送命令通道标志
- cType.assembleData( PChannelType::COMMAND , 0 );
- if( theApp.cmdTCP.Send( cType.buffer ) )
- { //用户注册
- PRegisterREQ req;
- req.assembleData( ( char * )( const char * )theApp.userName , ( char * )( const char * )theApp.password , PRegisterREQ::MONITOR );
- //发送用户注册和接收用户注册回复
- struct timeval tm = { 5 , 0 };
- if( theApp.cmdTCP.Send( req.buffer ) && theApp.cmdTCP.Receive( res.buffer , &tm ) && res.buffer.GetSize( ) && res.parseData( res.buffer ) && ! res.ireturn )
- break;
- }//循环连接
- theApp.cmdTCP.Close( );
- }//有内存数据
- ::WriteLog( theApp.GetLogHwnd( ) , "用户 %s 注册到服务器 %s 成功,连接视频通道" , theApp.userName , theApp.IP );
- //先关闭窗口
- if( ::IsWindow( dlg->GetSafeHwnd( ) ) )
- {
- dlg->m_return = res.ireturn;
- dlg->SendMessage( WM_CLOSE );
- }//发送成功,开始启动线程
- if( res.parseData( res.buffer ) && ! res.ireturn )
- {
- theApp.user_id = res.user_id;
- //连接视频通道
- theApp.videoTCP.Connect( theApp.IP , theApp.Port );
- cType.assembleData( PChannelType::VIDEO , theApp.user_id );
- theApp.videoTCP.Send( cType.buffer );
- PVideoData vd;
- //发送视频头
- vd.assembleData( theApp.user_id , 0 , PVideoData::VIDEO_HEADER , 0 , 0 );
- theApp.videoTCP.Send( vd.buffer );
- //有可能运行失败
- CThread::Run( CMonitorApp::OnCommand , &theApp );
- //有可能运行失败
- CThread::Run( CMonitorApp::OnVideo , &theApp );
- }
- }
- //测试网络连接数据包
- void CMonitorApp::SendTestConnect( void )
- {
- if( this->videoTCP.IsConnected( ) )
- {
- PConnectTest test;
- test.assembleData( this->user_id );
- this->cmdTCP.Send( test.buffer );
- }
- }
- //接收命令
- void CMonitorApp::OnCommand( void * pContext )
- { //请求在线用户列表
- POnlineUserREQ req;
- req.assembleData( );
- theApp.cmdTCP.Send( req.buffer );
- CBuffer buffer;
- //2个数据包之间最大的时间间隔是5分钟
- struct timeval tm = { 300 , 0 };
- //接收名命令包
- while( theApp.cmdTCP.Receive( buffer /* , &tm */ ) )
- {
- if( ! buffer.GetSize( ) )
- break;
- try
- {
- switch( *( int * )( buffer.GetBuffer( ) + INT_SIZE ) )
- {//在先用户状态
- case POnlineUserRESTAG : theApp.OnlineUser( buffer ); break;
- //窗口控制
- case PPanelCommandTAG : theApp.OnWindow( buffer ); break;
- }
- }
- catch( ... )
- {
- }
- }
- ::WriteLog( theApp.GetLogHwnd( ) , "失去了与服务器的连接,原因是 %d" , ::WSAGetLastError( ) );
- theApp.videoTCP.Close( );
- while( ! theApp.recv_video_map.empty( ) ) ::Sleep( 100 );
- theApp.cmdTCP.Close( );
- if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) )
- {
- ::WriteLog( theApp.GetLogHwnd( ) , "重新连接服务器" );
- theApp.m_pMainWnd->PostMessage( WM_CONNECT_MESSAGE );
- }
- }
- //在线用户回复
- void CMonitorApp::OnlineUser( CBuffer & buffer )
- {
- if( ! ::IsWindow( this->m_pMainWnd->GetSafeHwnd( ) ) )
- return;
- POnlineUserRES res;
- res.parseData( buffer );
- //用户在线
- if( ! res.user_name.empty( ) )
- {
- int id = ( int )::GetPrivateProfileInt( "监控点=窗口号" , res.user_name.c_str( ) , 0 , theApp.appIni ) -1;
- if( id >= 0 && id <= 9 && this->m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&res , ( LPARAM ) id ) )
- {//发送请求视频数据
- PRecvVideoREQ req;
- req.assembleData( res.user_id );
- this->cmdTCP.Send( req.buffer );
- ::WriteLog( this->GetLogHwnd( ) , "程序请求 %s 的视频数据,id : %d" , res.user_name.c_str( ) , res.user_id );
- }
- }//用户离线
- else if( ! this->recv_video_map.empty( ) )
- {
- INT_PTR_MAP::iterator itr = this->recv_video_map.find( res.user_id );
- //如果显示用户信息还存在
- if( itr != this->recv_video_map.end( ) )
- { //发送用户离线通知
- this->m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&res );
- //标志删除用户
- this->videoTCP.SetData( res.user_id );
- //延时1秒钟
- ::Sleep( 1000 );
- CVideoUSB * v = ( CVideoUSB * )itr->second;
- //删除该用户的视频显示信息
- this->recv_video_map.erase( itr );
- delete v;
- //恢复工作
- theApp.videoTCP.SetData( 0 );
- ::WriteLog( this->GetLogHwnd( ) , "id号为%d的用户停止发送数据" , res.user_id );
- }
- }
- }
- //窗口控制
- void CMonitorApp::OnWindow( CBuffer & buffer )
- {
- if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) )
- {
- PPanelCommand cmd;
- cmd.parseData( buffer );
- this->m_pMainWnd->SendMessage( WM_WINDOW , ( WPARAM )&cmd );
- }
- }
- //接收视频
- void CMonitorApp::OnVideo( void * pContext )
- {
- INT_PTR_MAP::iterator itr;
- PVideoData vd;
- while( theApp.videoTCP.Receive( vd.buffer ) )
- {
- if( ! vd.buffer.GetSize( ) )
- continue;
- try
- {
- vd.parseData( vd.buffer );
- switch( vd.type )
- {
- case PVideoData::VIDEO_HEADER :
- {
- CVideoUSB * video = NULL;
- if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) && ( video =( CVideoUSB * )theApp.m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&vd ) ) )
- {
- ::WriteLog( theApp.GetLogHwnd( ) , "收到 id号为 %d 的视频数据" , vd.user_id );
- while( theApp.videoTCP.GetData( ) ) ::Sleep( 1000 );
- theApp.recv_video_map[ vd.user_id ] = video;
- }
- else //显示失败,停止接收视频数据
- {
- ::WriteLog( theApp.GetLogHwnd( ) , "初始化 id号为 %d 的视频数据失败,停止接收该用户的视频数据" , vd.user_id );
- PStopVideoREQ req;
- req.assembleData( vd.user_id );
- theApp.cmdTCP.Send( req.buffer );
- }
- }
- break;
- case PVideoData::VIDEO_DATA :
- //保证视频链表没有改动并且找到了用户
- if( ! theApp.videoTCP.GetData( ) && ! theApp.recv_video_map.empty( ) && ( itr = theApp.recv_video_map.find( vd.user_id ) ) != theApp.recv_video_map.end( ) )
- {
- CVideoUSB * video = ( CVideoUSB * )( itr->second );
- if( ! video->Draw( vd.video , vd.size ) )
- {
- ::WriteLog( theApp.GetLogHwnd( ) , "显示 id号为 %d 的视频数据失败,停止接收该用户的视频数据" , vd.user_id );
- //显示失败停止接收视频
- PStopVideoREQ req;
- req.assembleData( vd.user_id );
- theApp.cmdTCP.Send( req.buffer );
- theApp.recv_video_map.erase( itr );
- delete video;
- POnlineUserRES res;
- res.user_id = vd.user_id;
- if( ::IsWindow( theApp.m_pMainWnd->GetSafeHwnd( ) ) )
- theApp.m_pMainWnd->SendMessage( WM_VIDEO_MESSAGE , ( WPARAM )&res );
- }//改变该窗口状态标志
- else if( ::IsWindow( video->GetSafeHwnd( ) ) && video->GetDlgCtrlID( ) != 2 )
- video->SetDlgCtrlID( 2 );
- }
- break;
- }
- }
- catch( ... )
- {
- }
- }
- //清除显示视频内存
- try
- {
- while( theApp.videoTCP.GetData( ) ) ::Sleep( 100 );
- while( ! theApp.recv_video_map.empty( ) )
- {
- itr = theApp.recv_video_map.begin( );
- CVideoUSB * video = ( CVideoUSB * )itr->second;
- theApp.recv_video_map.erase( itr );
- delete video;
- }
- }
- catch( ... )
- {
- }
- ::WriteLog( theApp.GetLogHwnd( ) , "视频线程退出,退出原因是 %d ,关闭命令通道连接n" , ::WSAGetLastError( ) );
- theApp.cmdTCP.Close( );
- }