📄 voipcall.cpp
字号:
IRTCParticipantStateChangeEvent* pEvent
)
{
TRACE(ZONE_PHONEAPP_EVENT);
if (! pEvent)
{
ASSERT(FALSE);
return E_POINTER;
}
HRESULT hr = pEvent->get_StatusCode(&m_NetworkStatus);
PHONEAPP_DEBUGMSG(FAILED(m_NetworkStatus) && ZONE_PHONEAPP_ERROR,(L"Call disconnected with failure: reason = RTC_E_STATUS_ hresult = 0x%08x", m_NetworkStatus));
PHONEAPP_DEBUGMSG(SUCCEEDED(m_NetworkStatus) && ZONE_PHONEAPP_EVENT, (L"Call disconnected with code: RTC_E_ hresult = 0x%08x", m_NetworkStatus));
return hr;
}
/*------------------------------------------------------------------------------
VoIPCall_t::SendDTMF
Send DTMF to the current participant
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::SendDTMF(
RTC_DTMF DTMFCode
)
{
if (GetCallStatus() != RTCSS_CONNECTED)
{
return S_FALSE;
}
if (!m_cpRTCParticipant)
{
ASSERT(FALSE);
return E_FAIL;
}
CComPtr<IRTCParticipant3> cpParticipant;
//query the IRTCParticipant3 object
HRESULT hr = m_cpRTCParticipant->QueryInterface(
IID_IRTCParticipant3,
reinterpret_cast<VOID**>(&cpParticipant)
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to query interface for IID_IRTCParticipant3"));
return hr;
}
hr = cpParticipant->SendDTMF(DTMFCode);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at sending DTMF for current RTCParticipant -- error code = 0x%x", hr));
}
return hr;
}
/*------------------------------------------------------------------------------
VoIPCall_t::GetStatus
Internal helper function to get the RTCSession status of the call
------------------------------------------------------------------------------*/
RTC_SESSION_STATE
VoIPCall_t::GetCallStatus(
void
)
{
//return static values if we are pending
if (m_CallType == e_vctInvalid)
{
return RTCSS_IDLE;
}
//we MUST have an RTC session at this point
if (! m_cpRTCSession)
{
ASSERT(FALSE);
return RTCSS_IDLE;
}
RTC_SESSION_STATE CurrentStatus = RTCSS_IDLE;
//get the status from the actual session
HRESULT hr = m_cpRTCSession->get_State(&CurrentStatus);
if (FAILED(hr))
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get the status from the internal session (0x%x)", hr));
return RTCSS_IDLE;
}
return CurrentStatus;
}
/*------------------------------------------------------------------------------
VoIPCall_t::DoVerbTalk
Handles the PH_VERB_TALK
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::DoVerbTalk(
void
)
{
return S_OK;
}
/*------------------------------------------------------------------------------
VoIPCall_t::DoVerbEnd
Handles the PH_VERB_END
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::DoVerbEnd(
void
)
{
TRACE(ZONE_PHONEAPP_FUNCTION);
RTC_SESSION_STATE CurrentStatus = GetCallStatus();
//End takes no effect when the session is in the process of transferring
if (CurrentStatus == RTCSS_REFER)
{
return E_NOTIMPL;
}
//End takes no effect when the session is already disconnected
if (CurrentStatus == RTCSS_DISCONNECTED)
{
return E_NOTIMPL;
}
HRESULT hr = End();
return hr;
}
/*------------------------------------------------------------------------------
VoIPCall_t::End
Terminate the call in action
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::End(
void
)
{
TRACE(ZONE_PHONEAPP_FUNCTION);
//have the RTC session begin the SIP BYE transaction
HRESULT hr = m_cpRTCSession->Terminate(RTCTR_NORMAL);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to begin terminating the session. RTC session returns 0x%x on termination request", hr));
}
return hr;
}
/*------------------------------------------------------------------------------
VoIPCall_t::DoVerbHoldUnhold
Initiates a hold or unhold operation
Parameters:
: Verb - the Verb
: fValidateOnly - indicates whether it is validate only
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::DoVerbHoldUnhold(
PH_VERB Verb
)
{
TRACE(ZONE_PHONEAPP_FUNCTION);
//get our status so we can validate the hold/unhold request
RTC_SESSION_STATE CallStatus = GetCallStatus();
if (CallStatus == RTCSS_IDLE)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get session status from internal session object - cannot continue..."));
return E_NOTIMPL;
}
//get the correct RTC interface with which to perform the call control action
CComPtr<IRTCSessionCallControl> cpCallControl;
HRESULT hr = m_cpRTCSession->QueryInterface(
IID_IRTCSessionCallControl,
reinterpret_cast<VOID**>(&cpCallControl)
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not QI the session for the call control object! [Hr = 0x%x]", hr));
return hr;
}
switch (Verb)
{
case PH_VERB_HOLD:
if (CallStatus == RTCSS_HOLD)
{
return S_FALSE;
}
//The hold action is only valid for a connected call
if (CallStatus != RTCSS_CONNECTED)
{
return E_NOTIMPL;
}
hr = cpCallControl->Hold(0);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"IRTCSessionCallControl failed to put this call on hold - hr = 0x%x", hr));
}
break;
case PH_VERB_UNHOLD:
//The unhold action is only valid for a call currently in the 'hold' state
if (CallStatus != RTCSS_HOLD)
{
return E_NOTIMPL;
}
//first put all active sessions on hold
hr = GetApp()->PlaceActiveSessionOnHold();
if (FAILED(hr))
{
//we can not proceed if we failed at putting other sessions on hold
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at putting other active sesssions onhold, hr = 0x%x", hr));
return hr;
}
//have the RTC Client perform the unhold by starting a re-INVITE transaction
hr = cpCallControl->UnHold(0);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"IRTCSessionCallControl failed to unhold this call - hr = 0x%x", hr));
}
break;
default:
ASSERT(FALSE);
hr = E_INVALIDARG;
break;
}
return hr;
}
/*------------------------------------------------------------------------------
VoIPCall_t::DoVerbAcceptRejectIncomingCall
Initiates an acceptance or rejection of an incoming call
Parameters:
: Verb - the Verb
: fValidateOnly - indicate whether this is for validate only purpose or not
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::DoVerbAcceptRejectIncomingCall(
PH_VERB Verb
)
{
TRACE(ZONE_PHONEAPP_FUNCTION);
//check that our internal state is valid for get an Answer request
RTC_SESSION_STATE CallStatus = GetCallStatus();
//we can only answer calls that are in the 'incoming' state
if (CallStatus != RTCSS_INCOMING)
{
return E_NOTIMPL;
}
HRESULT hr = S_OK;
switch (Verb)
{
case PH_VERB_ACCEPT_INCOMING:
//RTC will begin the 200 OK Answer transaction
hr = m_cpRTCSession->Answer();
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"RTC Session failed (syncronously) while answering - could not start the 200 OK transaction. Error code is 0x%x", hr));
}
m_CouldBeMissed = false;
break;
case PH_VERB_REJECT_INCOMING:
//RTC will begin the BYE "Decline" transaction
hr = m_cpRTCSession->Terminate(RTCTR_DND);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"RTC Session failed (synchronously) while rejecting - could not start the BYE transaction. Error code is 0x%x", hr));
}
m_CouldBeMissed = false;
break;
default:
//huh!? How is this possible?
ASSERT(FALSE);
hr = E_INVALIDARG;
break;
}
return hr;
}
/*------------------------------------------------------------------------------
VoIPGroup_t::OnRTCSessionStateChangeEvent
Handle a notification from the phone canvas object that our session
has changed state
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::OnRTCSessionStateChangeEvent(
IRTCSessionStateChangeEvent* pEvent
)
{
TRACE(ZONE_PHONEAPP_EVENT);
//validate input
if (! pEvent)
{
ASSERT(FALSE);
return E_POINTER;
}
if (m_cpRTCSession == NULL)
{
ASSERT(FALSE);
return E_UNEXPECTED;
}
//fetch the latest 'live' state from the session pointer
RTC_SESSION_STATE NewSessionState = RTCSS_IDLE;
HRESULT hr = m_cpRTCSession->get_State(&NewSessionState);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get the new session state from the session - error code = 0x%x", hr));
return E_FAIL;
}
hr = pEvent->get_StatusCode(&m_NetworkStatus);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get the status code from the session - error code = 0x%x", hr));
}
//we got some event - we don't want to be playing the last progress tone
StopRingbackTone();
//update transfer information if this session is being tranferred
if (IsBeingTransferred())
{
StateChangeWhileBeingTransferred(NewSessionState);
}
switch (NewSessionState)
{
case RTCSS_DISCONNECTED:
LogCallIfNecessary();
break;
case RTCSS_INPROGRESS:
//do we need to start the ringback progress tone?
if (m_NetworkStatus == RTC_E_STATUS_INFO_RINGING)
{
StartRingbackTone();
}
break;
}
return S_OK;
}
/*------------------------------------------------------------------------------
VoIPCall_t::OnRTCSessionReferStatusChangeEvent
Handle a notification from the phone canvas object that our session
has changed refer status
this notification is handled by the initiator in the transfer scenario
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::OnRTCSessionReferStatusChangeEvent(
IRTCSessionReferStatusEvent* pEvent
)
{
TRACE(ZONE_PHONEAPP_EVENT);
//validate input
if (!pEvent)
{
ASSERT(FALSE);
return E_POINTER;
}
RTC_SESSION_REFER_STATUS NewReferStatus;
HRESULT hr = pEvent->get_ReferStatus(&NewReferStatus);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get the new refer status from the event - error code = 0x%x", hr));
return hr;
}
switch (NewReferStatus)
{
case RTCSRS_REFERRING:
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_EVENT, (L"received a RTCSessionReferStatusChangeEvent w/ RTCSRS_REFERRING"));
return S_OK;
case RTCSRS_ERROR:
case RTCSRS_DROPPED:
case RTCSRS_REJECTED:
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_EVENT, (L"received a RTCSessionReferStatusChangeEvent w/ RTCSRS_ERROR"));
return S_OK;
case RTCSRS_ACCEPTED:
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_EVENT, (L"received a RTCSessionReferStatusChangeEvent w/ RTCSRS_ACCEPTED"));
return GetApp()->GetTimers().AddTimer(
sc_TransferDoneTimeout,
this,
&m_TransferDoneTimerId
);
case RTCSRS_DONE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -