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

📄 processing.cpp

📁 tapi3.0实现
💻 CPP
📖 第 1 页 / 共 5 页
字号:

        LogMessage("ProcessCallNotificationEvent: "
                   "incoming call while another call in progress");

        
        ITBasicCallControl *pSecondCall = NULL;

        hr = pCall->QueryInterface(IID_ITBasicCallControl, 
                                   (void**)&pSecondCall);

        pCall->Release();
        pCall = NULL;


        if (FAILED(hr))
        {
            LogError("ProcessCallNotificationEvent: failed to qi incoming call "
                     "for ITBasicCallConrtrol");

            return hr;
        }


        //
        // reject the incoming call
        //

        LogMessage("ProcessCallNotificationEvent: rejecting the incoming call");
        

        hr = pSecondCall->Disconnect(DC_REJECTED);

        pSecondCall->Release();
        pSecondCall = NULL;

        return E_FAIL;
    }


    //
    // check to see if we own the call
    //

    CALL_PRIVILEGE cp;
   
    hr = pCall->get_Privilege( &cp );


    if ( FAILED(hr) )
    {
        LogError("ProcessCallNotificationEvent: Failed to get call owner info");

        pCall->Release();
        pCall = NULL;

        LeaveCriticalSection(&g_CurrentCallCritSection);

        return hr;
    }

    if ( CP_OWNER != cp )
    {

        //
        // we don't own the call. ignore it.
        //

        LogMessage("ProcessCallNotificationEvent: We don't own the call.");

        pCall->Release();
        pCall = NULL;

        LeaveCriticalSection(&g_CurrentCallCritSection);

        return E_FAIL;
    }
    else
    {
        LogMessage("ProcessCallNotificationEvent: Incoming call.");
    }


    //
    // keep the call for future use
    // 

    hr = pCall->QueryInterface(IID_ITBasicCallControl, 
                               (void**)&g_pCurrentCall);


    if (FAILED(hr))
    {
        LogError("ProcessCallNotificationEvent: failed to qi incoming call for"
                  "ITBasicCallControl.");
        
        g_pCurrentCall = NULL;
    }
    
    LeaveCriticalSection(&g_CurrentCallCritSection);

    pCall->Release();
    pCall = NULL;


    return hr;

} // ProcessCallNotificationEvent


///////////////////////////////////////////////////////////////////////////////
//
// ProcessCallMediaEvent
//
// processing for TE_CALLMEDIA event. if stream is active, record the 
// incoming data
//
///////////////////////////////////////////////////////////////////////////////

HRESULT ProcessCallMediaEvent(IDispatch *pEvent)
{

    //
    // Get ITCallMediaEvent interface from the event
    //

    ITCallMediaEvent *pCallMediaEvent = NULL;

    HRESULT hr = pEvent->QueryInterface( IID_ITCallMediaEvent, 
                                 (void **)&pCallMediaEvent );

    if (FAILED(hr))
    {
    
        //
        // the event does not have the interface we want
        //

        LogError("ProcessCallMediaEvent: TE_CALLMEDIA. "
                 "Failed to QI event for ITCallMediaEvent");

        return hr;
    }


    //
    // get the CALL_MEDIA_EVENT that we are being notified of.
    //

    CALL_MEDIA_EVENT CallMediaEvent;

    hr = pCallMediaEvent->get_Event(&CallMediaEvent);

    if ( FAILED(hr) )
    {

        //
        // failed to get call media event 
        //
        
        LogError("ProcessCallMediaEvent: TE_CALLMEDIA. "
                 "Failed to get call media event hr = 0x%lx", hr);
        
        pCallMediaEvent->Release();
        pCallMediaEvent = NULL;

        return hr;
    }


    LogMessage("ProcessCallMediaEvent: processing call media event");

    switch (CallMediaEvent) 
    {

        case CME_STREAM_INACTIVE:
        {

            LogMessage("ProcessCallMediaEvent: CME_STREAM_INACTIVE");

            break;
        }

        case CME_STREAM_NOT_USED:
            
            LogMessage("ProcessCallMediaEvent: CME_STREAM_NOT_USED");
            
            break;

        case CME_NEW_STREAM:

            LogMessage("ProcessCallMediaEvent: CME_NEW_STREAM received");

            break;

        case CME_STREAM_FAIL:

            LogError("ProcessCallMediaEvent: CME_STREAM_FAIL received");
            
            break;

        case CME_TERMINAL_FAIL:
            
            LogError("ProcessCallMediaEvent: CME_STREAM_FAIL received");

            break;

        case CME_STREAM_ACTIVE:
        {

            LogError("ProcessCallMediaEvent: CME_STREAM_ACTIVE received");


            //
            // Get the terminal on the active stream
            //    

            ITTerminal *pRecordStreamTerminal = NULL;

            hr = GetTerminalFromMediaEvent(pCallMediaEvent, 
                                           &pRecordStreamTerminal);

            if ( FAILED(hr) )
            {
                // 
                // the stream has no terminals associated with it
                //

                LogError("ProcessCallMediaEvent: "
                         "failed to get terminal on the active stream");

                break; 
            }

          
            //
            // make sure the direction is right -- we are recording, so the 
            // terminal should be TD_RENDER
            //

            TERMINAL_DIRECTION td;

            hr = pRecordStreamTerminal->get_Direction( &td);

            if ( FAILED(hr) ) 
            {

                LogError("ProcessCallMediaEvent: "
                         "failed to get record terminal's direction.");

                pRecordStreamTerminal->Release();
                pRecordStreamTerminal = NULL;

                break; 
            }
            
            
            //
            // double check that the terminal is rendering terminal
            // since we are the recording side
            //

            if ( TD_RENDER != td ) 
            {

                //
                // this should never ever happen
                //

                LogError("ProcessCallMediaEvent: bad terminal direction");

                pRecordStreamTerminal->Release();
                pRecordStreamTerminal = NULL;

                hr = E_FAIL;

                break;

            }

            //
            // Now do the actual streaming.
            //

            //
            // this will block until:
            //
            // the call is disconnected, or
            // the user chooses to close the app, or
            // there is an error
            //
            // Since we are in the message processing thread,
            // the application will not be able to process messages
            // (the messages will still be queued) until this call
            // returns.
            //
            // If it is important that messages are processed while
            // file is being recorded, recording should be done on 
            // a different thread.
            // 

            RecordMessage(pRecordStreamTerminal);
        
            pRecordStreamTerminal->Release();
            pRecordStreamTerminal = NULL;
    
            break;
        }
    
        default:

            break;
    
    } // switch (call media event)


    //
    // We no longer need the event interface.
    //

    pCallMediaEvent->Release();
    pCallMediaEvent = NULL;

    
    return S_OK;    

}


///////////////////////////////////////////////////////////////////////////////
//
// ProcessCallStateEvent
//
// processing for TE_CALLSTATE. if CS_OFFERING, creates and selects MST, 
// answers the call . Release call if disconnected. 
//
// also verifies that the event is for the current call
//
///////////////////////////////////////////////////////////////////////////////

HRESULT ProcessCallStateEvent(IDispatch *pEvent)
{

    HRESULT hr = S_OK;


    //
    // TE_CALLSTATE is a call state event.  
    // pEvent is an ITCallStateEvent
    // 

    ITCallStateEvent *pCallStateEvent = NULL;


    //
    // Get the interface
    //

    hr = pEvent->QueryInterface(IID_ITCallStateEvent, 
                                (void **)&pCallStateEvent);

    if ( FAILED(hr) )
    {

        LogError("ProcessCallStateEvent: "
                 "Failed to QI event for ITCallStateEvent");

        return hr;
    }


    //
    // make sure the message is for the active call!
    //

    EnterCriticalSection(&g_CurrentCallCritSection);

    if (!IsMessageForActiveCall(pCallStateEvent))
    {
        LogMessage("ProcessCallStateEvent: received TE_CALLSTATE message "
                   "for a different call. ignoring.");

        pCallStateEvent->Release();
        pCallStateEvent = NULL;

        LeaveCriticalSection(&g_CurrentCallCritSection);

        return E_FAIL;
    }


    //
    // get the CallState that we are being notified of.
    //

    CALL_STATE CallState;

    hr = pCallStateEvent->get_State(&CallState);


    //
    // no longer need the event
    //

    pCallStateEvent->Release();
    pCallStateEvent = NULL;


    if (FAILED(hr))
    {
         LogError("ProcessCallStateEvent: "
                  "failed to get state from call state event.");

         LeaveCriticalSection(&g_CurrentCallCritSection);

         return hr;
    }



    //
    // log the new call state
    //

    if (CS_OFFERING == CallState)
    {
        
        LogMessage("ProcessCallStateEvent: call state is CS_OFFERING");


        //
        // try to create and select media streaming terminal on one of
        // the call's incoming audio streams
        //

        hr = CreateAndSelectMST();

        if (S_OK == hr)
        {
        
            //
            // we have selected a terminal on one of the streams
            // answer the call
            //

            LogMessage("ProcessCallStateEvent: answering the call");

            hr = g_pCurrentCall->Answer();

            if (FAILED(hr))
            {
                LogError("ProcessCallStateEvent: Failed to answer the call");
            }

        }
        else
        {
            
            //
            // we could not create mst on any of the streams of 
            // the incoming call. reject the call.
            //

            LogMessage("ProcessCallStateEvent: rejecting the call");

            HRESULT hr2 = g_pCurrentCall->Disconnect(DC_REJECTED);

            if (FAILED(hr2))
            {
                LogError("ProcessCallStateEvent: Failed to reject the call");
            }

        }


        
    } // CS_OFFERING
    else if (CS_DISCONNECTED == CallState)
    {

        LogMessage("ProcessCallStateEvent: call state is CS_DISCONNECTED. "
                   "Releasing the call.");


        //
        // release the call -- no longer need it!
        //

        g_pCurrentCall->Release();
        g_pCurrentCall = NULL;


        //
        // signal the main thread that it can exit if it is time to exit
        //

        LogMessage("ProcessCallStateEvent: signaling main thread.");

        SetEvent(g_hExitEvent);

    } // CS_DISCONNECTED
    else if (CS_CONNECTED == CallState)
    {
        
        LogMessage("ProcessCallStateEvent: call state is CS_CONNECTED");

    } // CS_CONNECTED


    //
    // no longer need to protect current call
    //

    LeaveCriticalSection(&g_CurrentCallCritSection);

    return hr;

}



/////////////////////////////////////////////////////////////////////////////
//
// OnTapiEvent
//
// handler for tapi events. called on a thread that provides asychronous
// processing of tapi messages
//
/////////////////////////////////////////////////////////////////////////////

HRESULT OnTapiEvent(TAPI_EVENT TapiEvent, IDispatch *pEvent)
{
    
    LogMessage("OnTapiEvent: message received");


    HRESULT hr = S_OK;


    switch ( TapiEvent )
    {
    
        case TE_CALLNOTIFICATION:
        {

            LogMessage("OnTapiEvent: received TE_CALLNOTIFICATION");

            hr = ProcessCallNotificationEvent(pEvent);

            break;

        } // TE_CALLNOTIFICATION
        

        case TE_CALLSTATE:
        {
            LogMessage("OnTapiEvent: received TE_CALLSTATE");

            hr = ProcessCallStateEvent(pEvent);

            break;

        } // TE_CALLSTATE


        case TE_CALLMEDIA:
        {

            LogMessage("OnTapiEvent: received TE_CALLMEDIA");

            hr = ProcessCallMediaEvent(pEvent);

            break;    
        
        }

⌨️ 快捷键说明

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