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

📄 voipcall.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    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 + -