⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtcevent.cpp

📁 Windows CE .Net 下面 VOIP编程的经典实例。对于初学Windows 平台下VOIP编程技术的程序员颇具借鉴意义!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			// set up session based upon type																		
			switch(enRST) {
			case RTCST_PC_TO_PC:
			case RTCST_PHONE_TO_PHONE:
			case RTCST_PC_TO_PHONE:
				
				DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event VoIP session connected and in progress\r\n" ) );
				break;
				
				
			case RTCST_IM:						
				DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event IM session connected and in progress\r\n" ) );
				break;						
				
			default:
				break;
			} // end switch Session Type						
			
			break;
		} // end RTCSS_CONNECTED
		
	case RTCSS_DISCONNECTED:
		{
            // turn off incoming voice session ring
            hr = g_pRTCClient->PlayRing( RTCRT_PHONE, VARIANT_FALSE );

            if (FAILED(hr)) {
                DEBUGMSG( ZONE_ERROR, (  L"VoipDemo: Event PlayRing failed! 0x%lx\r\n", hr ) );
            }

            if (!g_pSessionContainer->Exist(pSess)) {
                // incoming session that timed out
                break;
            }

			// store session state locally
			(*g_pSessionContainer)[pSess]->put_SessionState( enRSS );

			// remove the session from the container
			g_pSessionContainer->Remove(pSess);

			EnterCriticalSection( g_pcsSessionDataLock );

			switch (enRST) {
			case RTCST_IM:
				ASSERT(g_bIMSessionOpen);
				g_bIMSessionOpen = FALSE;
				
				if (!g_bVoiceSessionOpen) {
					SysFreeString( g_bstrCurrentlyConnectedURI );
					g_bstrCurrentlyConnectedURI = NULL;
				}
				break;
				
			default:
				ASSERT(g_bVoiceSessionOpen);			

				g_bVoiceSessionOpen = FALSE;
				
				if (!g_bIMSessionOpen) {
					SysFreeString( g_bstrCurrentlyConnectedURI );
					g_bstrCurrentlyConnectedURI = NULL;
				}
				break;
			}// end switch(sessiontype)

			LeaveCriticalSection( g_pcsSessionDataLock );
		} // end RTCSS_DISCONNECTED
		break;

	case RTCSS_INPROGRESS:
		(*g_pSessionContainer)[pSess]->put_SessionState(enRSS);
			break;

	default:
		// do nothing	
		break;
        
    } // end switch (Session state)

Cleanup:
	if (pSSC)
		pSSC->Release();    						
	if (pSess)
		pSess->Release();
	return hr;
} // end SessionStateChangeEvent()

/************************************************************************************************
 
   HRESULT HandleParticipantStateChangeEvent ( IN IDispatch * pEvent )
 
 	Event handler for particpant state change events.
 
 	Relevant Events:
 		INCOMING	-	get participant information for display to user, ask user to accept / reject session.
 		CONNECTED	-	pass connected message to SWCB

 ************************************************************************************************/		

HRESULT
HandleParticipantStateChangeEvent(
							IN IDispatch* pEvent
							)
{
	HRESULT hr = S_OK;
	RTC_PARTICIPANT_STATE enRPS;
	RTC_SESSION_TYPE enRST;

	IRTCParticipantStateChangeEvent * pPSC = NULL;
	IRTCParticipant* pPart = NULL;
	IRTCSession * pSess = NULL;
	
	P_PARTICIPANT_INFO pPartInfo = NULL;
	BSTR bstrPartName = NULL;	
	INT iRetVal = 0;

	hr = pEvent->QueryInterface(
		IID_IRTCParticipantStateChangeEvent,
		(VOID **)&pPSC
		);
	
	if ( FAILED(hr) || !pPSC)
	{
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event QueryInterface failed in HandleParticipantStateChangeEvent 0x%lx\r\n", hr ) );
		goto Cleanup;
		
	}
	
	// get participant, then get the session, then get the session type (IM or VOICE)
	
	hr = pPSC->get_State( &enRPS );

	if (FAILED(hr)) {
		
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event: Participant::get_State failed! 0x%lx\r\n", hr ) );
		goto Cleanup;
	}
	
	DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event RTCE_PARTICIPANT_STATE_CHANGE - %s\r\n", GetStringFromVal(enRPS, ParticipantStateTbl) ) );
	
	hr = pPSC->get_Participant(&pPart);	// does AddRef(pPart)
	
	if (FAILED(hr) || !pPart) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo:Event failure getting participant! 0x%lx\r\n", hr) );
		goto Cleanup;
	}							
	
	hr = pPart->get_Session(&pSess); // does AddRef(pSess)
	
	if(FAILED(hr) || !pSess) {
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event get_Session failed! 0x%lx\r\n", hr ) );
		goto Cleanup;	
	}

    if (FALSE == g_pSessionContainer->Exist(pSess)) {
        pSess->get_Type( &enRST );

        // create a new CSession object to store the session
        CSession* pSessionObj = new CSession( pSess, enRST, RTCSS_INCOMING, g_fnSWCB );
        g_pSessionContainer->Add( pSess, pSessionObj );

    } else {
        enRST = (*g_pSessionContainer)[pSess]->get_SessionType();
    }
	

	switch(enRPS)
	{
	case RTCPS_INCOMING:
		{	
			if (enRST != RTCST_PHONE_TO_PHONE) {	
				// get the participant info

				pPartInfo = (*g_pSessionContainer)[pSess]->get_ParticipantInfo( pPart );
				
				if ( !pPartInfo ) {
					DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event Error getting participant info from CSession\r\n") );
					(*g_pSessionContainer)[pSess]->Reject();
					hr = E_FAIL;
					goto Cleanup;
				}				
											

				iRetVal = SWCB_CALL_REJECTED;

				// Ensure that we only get 1 IM session
				// Ensure that we're only accepting additional sessions from the same user
				//		that is ONLY concurrent IM and Voice from the same location
				
				switch(enRST)
				{
				case RTCST_PC_TO_PC:
					// case RTCST_PC_TO_PHONE: // Will never get this 
										
					EnterCriticalSection( g_pcsSessionDataLock );

					if (g_bIMSessionOpen && g_bstrCurrentlyConnectedURI) {
						if (!SipURIsResolve(g_bstrCurrentlyConnectedURI, pPartInfo->get_Addr())) {
							
							LeaveCriticalSection( g_pcsSessionDataLock );
							
							DEBUGMSG( ZONE_ERROR|ZONE_STATUS|ZONE_CALL, (L"VoipDemo: Event Error, only allowing concurrent sessions from a single source\r\n") );
							(*g_pSessionContainer)[pSess]->Reject();
							hr = E_FAIL;
							goto Cleanup;
						}
					}
			
					LeaveCriticalSection( g_pcsSessionDataLock );
					
					// ask user to accept / deny session
					iRetVal = (*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_CALL_INITIATING_INCOMING, pPartInfo, pSess );
					break;			
					
				case RTCST_IM:
					
					EnterCriticalSection( g_pcsSessionDataLock );
					
					if (g_bVoiceSessionOpen && g_bstrCurrentlyConnectedURI) {
						if (!SipURIsResolve(g_bstrCurrentlyConnectedURI, pPartInfo->get_Addr())) {
							
							LeaveCriticalSection( g_pcsSessionDataLock );
							
							DEBUGMSG( ZONE_ERROR|ZONE_STATUS|ZONE_CALL, (L"VoipDemo: Event Error, only allowing concurrent sessions from a single source\r\n") );						
							(*g_pSessionContainer)[pSess]->Reject();
							hr = E_FAIL;
							goto Cleanup;
						}
					}
					
					LeaveCriticalSection( g_pcsSessionDataLock );

					// ask user to accept / deny session
					iRetVal = (*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_INITIATING_INCOMING, pPartInfo, pSess );				
					break;
					
				} // end switch (sessiontype)							

				switch (iRetVal) 
				{
				case SWCB_CALL_REJECTED:
					(*g_pSessionContainer)[pSess]->Reject();
					break;
					
				case SWCB_CALL_TIMEOUT:
					// timeout do nothing	
					break;
				case SWCB_CALL_ACCEPTED:
					if ((*g_pSessionContainer)[pSess]->Accept() == FALSE) {
						hr = E_FAIL;
					}
					
					EnterCriticalSection( g_pcsSessionDataLock );
					
					if (!g_bstrCurrentlyConnectedURI)
						g_bstrCurrentlyConnectedURI = SysAllocString(pPartInfo->get_Addr());
					
					LeaveCriticalSection( g_pcsSessionDataLock );
					break;
					
				default:
					DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Event error from SWCB function, unexpected retval: %i\r\n", iRetVal) );
					break;
				}	// end switch (SWCB retval)
			} // end if (!enRST != RTCST_PHONE_TO_PHONE)

			else {
				//RTCST_PHONE_TO_PHONE

				// will we ever get this message on a phone to phone session?				
				// phone to phone sessions should have the following states:
				// INPROGRESS -> call initiating
				// ANSWERING ?
				// CONNECTED -> adds participant's reference to the call?
				// DISCONNECTED -> remove references for all added participants??

				// Note: we shouldn't accept or reject the session from here. The two phones will handle that.  We should
				// just show status of the call.
				//
				// (*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_CALL_PARTICIPANT_JOINED, , pSess )
				//
			}

			break;
		} // end case RTCPS_INCOMING
	case RTCPS_CONNECTED:
		{
			hr = pPart->get_Name( &bstrPartName );

			if (FAILED(hr)) {
				DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Event failed! getting name from Participant->get_Name(): 0x%l\r\n") );
				goto Cleanup;
			}

			DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event participant %s connected to session %s.\r\n", bstrPartName, GetStringFromVal(enRST, SessionTypeTbl)) );

			switch(enRST) 
			{
			case RTCST_PC_TO_PC:
			case RTCST_PC_TO_PHONE:
			case RTCST_PHONE_TO_PHONE:
				// call the SWCB function for this particular session 
				(*g_pSessionContainer)[pSess]->get_SWCBfn()(SWCBM_CALL_PARTICIPANT_JOINED, bstrPartName, pSess );
				break;
				
				
			case RTCST_IM:								
				// call the SWCB function for this particular session
				(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_PARTICIPANT_JOINED, bstrPartName, pSess );
				break;			
				
			default:
				break;
			} // end switch Session Type						
			SysFreeString( bstrPartName );
			break;
		}

	case RTCPS_DISCONNECTED:
		{
			hr = pPart->get_Name( &bstrPartName );

			if (FAILED(hr)) {
				DEBUGMSG( ZONE_ERROR|ZONE_CALL, (L"VoipDemo: Event Failed! getting participant name. 0x%lx\r\n", hr) );
				goto Cleanup; 
			}

			switch (enRST) {
			case RTCST_PC_TO_PC:
			case RTCST_PC_TO_PHONE:	
			case RTCST_PHONE_TO_PHONE:
				(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_CALL_PARTICIPANT_LEFT, bstrPartName, pSess );
				break;
				
			case RTCST_IM:
				(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_PARTICIPANT_LEFT, bstrPartName, pSess );
				break;
				
			default:
				break;
			}

			SysFreeString( bstrPartName );

			if (enRST == RTCST_PHONE_TO_PHONE) {
			// if in a phone to phone call the participant leaves, do we need to explicitly remove him?  or do we
			// release his reference to the session? or both? 
			// if (pPart->get_Removable()) {
			// pSess->RemoveParticipant(pPart);
			// }
			// pSess->Release(); // release participant's reference to the session. (?)
			}
			break;
		}
		
	default:
		break;
	} // end switch (Participant state	

Cleanup:
	if (pPart)
		pPart->Release();

	if (pSess)
		pSess->Release();
	
	if (pPSC)
		pPSC->Release();
	return hr;
} // end ParticipantStateChangeEvent()

/************************************************************************************************
 
   HRESULT HandleClientEvent( IN IDispatch* pEvent )
 
 	Event Handler for client events
 
 	Currently the only relevant event is SHUTDOWN_COMPLETE, so final app cleanup
 	is done here.

 ************************************************************************************************/

HRESULT
HandleClientEvent(
			IN IDispatch* pEvent
			)
{
	HRESULT hr = S_OK;
	
	IRTCClientEvent * pCE;           
	
	hr = pEvent->QueryInterface(
		IID_IRTCClientEvent,					
		(VOID **)&pCE
		);
		
	RTC_CLIENT_EVENT_TYPE enCET;
	
	hr = pCE->get_EventType( &enCET);

	pCE->Release();
	pCE = NULL;

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event ClientEvent::get_EventType failed! 0x%lx\r\n", hr ) );
		return hr;
	}
	
	DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event RTCE_CLIENT - %s\r\n", GetStringFromVal(enCET, ClientEventTbl) ) );

	switch(enCET)
	{												
	case RTCCET_ASYNC_CLEANUP_DONE:
		{
			// PrepareForShutdown has completed.  It's okay to shutdown now.
			// This event is being observed by ShutdownRTC()

			SetEvent( g_hShutdownEventComplete );
			DEBUGMSG( ZONE_STATUS, ( L"VoipDemo: Event RTCE_ASYNC_CLEANUP completed\r\n" ) );

			break;
		}
		
	default:
		break;
	}			

	return hr;
} // end ClientEvent()

/************************************************************************************************
 
   HRESULT HandleMessagingEvent( IN IDispatch* pEvent )
 
 	Event Handler for messaging events
 
 	Takes incoming messages and passes them to the UI for display to the user.  It currently 
 	just ignores status messages, as the GUI doesn't yet support them.
 
************************************************************************************************/

HRESULT
HandleMessagingEvent(
			   IN IDispatch* pEvent
			   )
{
	HRESULT hr = S_OK;
	IRTCSession* pSess = NULL;										
	IRTCParticipant* pPart = NULL;
	IRTCMessagingEvent * pME;           
	
	hr = pEvent->QueryInterface(
		IID_IRTCMessagingEvent,
		(VOID **)&pME
		);
	
	//	For use with multiple IM sessions, to identify on which session a messages is coming
	hr = pME->get_Session( &pSess ); // does AddRef(pSess)

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_Session failed 0x%lx\r\n", hr ) );
		goto Cleanup;
	}

	hr = pME->get_Participant( &pPart);

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_Participant failed 0x%lx\r\n", hr ) );
		goto Cleanup;
	}

	RTC_MESSAGING_EVENT_TYPE enMET;			
	hr = pME->get_EventType( &enMET );

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_EventType failed! 0x%lx\r\n", hr ) );		
		goto Cleanup;
	}
	
	switch (enMET)
	{
	case RTCMSET_MESSAGE:
		BSTR bstrIMMsg;
		
		hr = pME->get_Message( &bstrIMMsg );
		
		if (SUCCEEDED(hr)) {	
			DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event incoming IM message received.\r\n" ) );
			
			// form the message into our internal message structure
			IM_MSG sIMMsg = { (*g_pSessionContainer)[pSess]->get_ParticipantInfo(pPart), bstrIMMsg };
			
			// pass the message to the UI for display
			(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_MESSAGE_ARRIVED, &sIMMsg, pSess );				
			SysFreeString( bstrIMMsg );
		} else {
			DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_Message failed! 0x%lx\r\n", hr ) );
		}
			
    	// ring to note incoming message		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -