/////////////////////////////////////////////////////////////////// // SameCall // // check if same call object as g_pCall // /////////////////////////////////////////////////////////////////// bool SameCall(ITCallStateEvent* pCallStateEvent) { // // sanity check // if(NULL == pCallStateEvent) { return false; } // //get call object // ITCallInfo* pCallInfo = NULL; HRESULT hr = pCallStateEvent->get_Call(&pCallInfo); // //check if we have a call and get_Call succeded // if(NULL != pCallInfo && ( SUCCEEDED(hr) && NULL != g_pCall) ) { bool bIsEqual = true; // //get and compare IUnknown for both objects // IUnknown* pIUnkCallInfo = NULL; IUnknown* pIUnkCallControl = NULL; pCallInfo->QueryInterface(IID_IUnknown, (void**)&pIUnkCallInfo); g_pCall->QueryInterface(IID_IUnknown, (void**)&pIUnkCallControl); // //compare // if(pIUnkCallInfo != pIUnkCallControl) { bIsEqual = false; } // //clean up // pCallInfo->Release(); if(NULL != pIUnkCallInfo) { pIUnkCallInfo->Release(); } if(NULL != pIUnkCallControl) { pIUnkCallControl->Release(); } return bIsEqual; } else { return false; } }
/////////////////////////////////////////////////////////////////// // DoCallNotification // // TE_CALLNOTIFICATION means that the application is being notified // of a new call. // // Note that we don't answer to call at this point. The application // should wait for a CS_OFFERING CallState message before answering // the call. // /////////////////////////////////////////////////////////////////// HRESULT DoCallNotification( IN IDispatch * pEvent) { ITCallNotificationEvent * pNotify = NULL; HRESULT hr = pEvent->QueryInterface( IID_ITCallNotificationEvent, (void **)&pNotify ); if (FAILED(hr)) { DoMessage( _T("Incoming call, but failed to get the interface")); return hr; } CALL_PRIVILEGE cp = CP_MONITOR; ITCallInfo * pCall = NULL; // // get the call // hr = pNotify->get_Call( &pCall ); // // release the event object // pNotify->Release(); if(FAILED(hr)) { DoMessage( _T("Incoming call, but failed to get the call")); return hr; } // // check to see if we own the call // hr = pCall->get_Privilege( &cp ); if(FAILED(hr)) { pCall->Release(); DoMessage( _T("Incoming call, but failed to get_Privilege")); return hr; } if ( CP_OWNER != cp ) { // // just ignore it if we don't own it // pCall->Release(); return hr; } // //check if we already have a call - if yes reject it // if(NULL != g_pCall) { ITBasicCallControl* pITBCC = NULL; hr = pCall->QueryInterface( IID_ITBasicCallControl, (void**)&pITBCC ); pCall->Release(); // //sanity check // if(SUCCEEDED(hr)) { // //disconnect - we'll handle the other events from this call later // pITBCC->Disconnect(DC_REJECTED); pITBCC->Release(); } return hr; } // //get the call if do not have already one // hr = pCall->QueryInterface( IID_ITBasicCallControl, (void**)&g_pCall ); pCall->Release(); if(FAILED(hr)) { DoMessage( _T("Incoming call, but failed to QI ITBasicCallControl")); } else { // // update UI // SetStatusMessage(_T("Incoming Owner Call")); } // //clean up // return hr; }
HRESULT OnTapiEvent( TAPI_EVENT TapiEvent, IDispatch * pEvent ) { HRESULT hr; switch ( TapiEvent ) { case TE_CALLNOTIFICATION: { // // TE_CALLNOTIFICATION means that the application is being notified // of a new call. // // Note that we don't answer to call at this point. The application // should wait for a CS_OFFERING CallState message before answering // the call. // ITCallNotificationEvent * pNotify; hr = pEvent->QueryInterface( IID_ITCallNotificationEvent, (void **)&pNotify ); if (S_OK != hr) { DoMessage( L"Incoming call, but failed to get the interface"); } else { CALL_PRIVILEGE cp; ITCallInfo * pCall; // // get the call // hr = pNotify->get_Call( &pCall ); pNotify->Release(); if ( SUCCEEDED(hr) ) { // // check to see if we own the call // hr = pCall->get_Privilege( &cp ); if ( FAILED(hr) || (CP_OWNER != cp) ) { // // just ignore it if we don't own it // pCall->Release(); pEvent->Release(); // we addrefed it CTAPIEventNotification::Event() return S_OK; } // // Get the ITBasicCallControl interface // // // If we're already in a call, disconnect the new call. Otherwise, // save it in our global variable. // ITBasicCallControl * pCallControl; hr = pCall->QueryInterface( IID_ITBasicCallControl, (void**)&pCallControl ); pCall->Release(); if ( SUCCEEDED(hr) ) { if (gpCall == NULL) { gpCall = pCallControl; // // update UI // EnableButton( IDC_ANSWER ); DisableButton( IDC_DISCONNECT ); SetStatusMessage(L"Incoming Owner Call"); } else { // // Reject this call since we're already in a call // hr = pCallControl->Disconnect(DC_REJECTED); pCallControl->Release(); if (FAILED(hr)) { break; } } } } } break; } case TE_CALLSTATE: { // TE_CALLSTATE is a call state event. pEvent is // an ITCallStateEvent CALL_STATE cs; ITCallStateEvent * pCallStateEvent; ITCallInfo * pCall; ITBasicCallControl * pCallControl; // Get the interface hr = pEvent->QueryInterface( IID_ITCallStateEvent, (void **)&pCallStateEvent ); if ( FAILED(hr) ) { break; } // get the CallInfo interface hr = pCallStateEvent->get_Call( &pCall ); if ( FAILED(hr) ) { pCallStateEvent->Release(); break; } //get the ITBasicCallControl interface and compare it to our existing call hr = pCall->QueryInterface( IID_ITBasicCallControl,(void**)&pCallControl ); pCall->Release(); if (FAILED(hr)) { pCallStateEvent->Release(); break; } //ignore call state events for other calls if (pCallControl != gpCall) { pCallControl->Release(); pCallStateEvent->Release(); break; } pCallControl->Release(); // // This is a call state event for our call // // get the CallState that we are being notified of. hr = pCallStateEvent->get_State( &cs ); // Release the interface pCallStateEvent->Release(); if ( FAILED(hr) ) { break; } // if it's offering, update our UI if (CS_OFFERING == cs) { if (gfAutoAnswer) { PostMessage(ghDlg, WM_COMMAND, IDC_ANSWER, 0); } else { SetStatusMessage(L"Click the Answer button"); } } else if (CS_DISCONNECTED == cs) { PostMessage(ghDlg, WM_COMMAND, IDC_DISCONNECTED, 0); } else if (CS_CONNECTED == cs) { // nothing to do -- we handle connection synchronously } break; } case TE_CALLMEDIA: { // TE_CALLMEDIA is a media event. pEvent is // an ITCallMediaEvent CALL_MEDIA_EVENT cme; ITCallMediaEvent * pCallMediaEvent; // Get the interface hr = pEvent->QueryInterface( IID_ITCallMediaEvent, (void **)&pCallMediaEvent ); if ( FAILED(hr) ) { break; } // get the CALL_MEDIA_EVENT that we are being notified of. hr = pCallMediaEvent->get_Event( &cme ); if ( SUCCEEDED(hr) ) { switch ( cme ) { case CME_STREAM_NOT_USED: case CME_STREAM_INACTIVE: case CME_NEW_STREAM: break; case CME_STREAM_FAIL: DoMessage( L"Call media event: stream failed"); break; case CME_TERMINAL_FAIL: DoMessage( L"Call media event: terminal failed"); break; case CME_STREAM_ACTIVE: { // // Find out if this stream has a video render terminal. If not, // we don't need to do anything with this stream. Also note // if this is the video capture stream or the video render // stream. // ITTerminal * pTerminal; BOOL fRenderStream; hr = GetVideoRenderTerminalFromStreamEvent( pCallMediaEvent, &pTerminal, &fRenderStream ); if ( SUCCEEDED(hr) ) { // Get the video window interface for the terminal IVideoWindow *pVideoWindow = NULL; hr = pTerminal->QueryInterface( IID_IVideoWindow, (void**)&pVideoWindow ); pTerminal->Release(); if ( SUCCEEDED(hr) ) { // Put this window in our dialog HostWindow(pVideoWindow, fRenderStream); pVideoWindow->Release(); } } break; } default: break; } } // We no longer need this interface. pCallMediaEvent->Release(); break; } default: break; } pEvent->Release(); // we addrefed it CTAPIEventNotification::Event() return S_OK; }
/********************************************************** * COperator::OnTapiEvent * *------------------------* * Description: * This is the real TAPI event handler, called on our * UI thread upon receipt of the WM_PRIVATETAPIEVENT * message. * Return: * S_OK ************************************************************/ HRESULT COperator::OnTapiEvent( TAPI_EVENT TapiEvent, IDispatch * pEvent ) { HRESULT hr; switch ( TapiEvent ) { case TE_CALLNOTIFICATION: { // TE_CALLNOTIFICATION means that the application is being notified // of a new call. // // Note that we don't answer to call at this point. The application // should wait for a CS_OFFERING CallState message before answering // the call. // ITCallNotificationEvent * pNotify; hr = pEvent->QueryInterface( IID_ITCallNotificationEvent, (void **)&pNotify ); if (S_OK != hr) { DoMessage( L"Incoming call, but failed to get the interface"); } else { CALL_PRIVILEGE cp; ITCallInfo * pCall; // Get the call hr = pNotify->get_Call( &pCall ); pNotify->Release(); if ( SUCCEEDED(hr) ) { // Check to see if we own the call hr = pCall->get_Privilege( &cp ); if ( FAILED(hr) || (CP_OWNER != cp) ) { // Just ignore it if we don't own it pCall->Release(); pEvent->Release(); // We addrefed it CTAPIEventNotification::Event() return S_OK; } // Get the ITBasicCallControl interface and save it in our // member variable. hr = pCall->QueryInterface( IID_ITBasicCallControl, (void**)&m_pCall ); pCall->Release(); if ( SUCCEEDED(hr) ) { // Update UI ::EnableWindow( ::GetDlgItem( m_hDlg, IDC_ANSWER ), TRUE ); SetStatusMessage(L"Incoming Owner Call"); } } } break; } case TE_CALLSTATE: { // TE_CALLSTATE is a call state event. pEvent is // an ITCallStateEvent // Get the interface ITCallStateEvent * pCallStateEvent; hr = pEvent->QueryInterface( IID_ITCallStateEvent, (void **)&pCallStateEvent ); if ( FAILED(hr) ) { break; } // Get the CallState that we are being notified of. CALL_STATE cs; hr = pCallStateEvent->get_State( &cs ); pCallStateEvent->Release(); if ( FAILED(hr) ) { break; } // If it's offering to be answered, update our UI if (CS_OFFERING == cs) { if (m_fAutoAnswer) { ::PostMessage(m_hDlg, WM_COMMAND, IDC_ANSWER, 0); } else { SetStatusMessage(L"Click the Answer button"); } } else if (CS_DISCONNECTED == cs) { ::PostMessage(m_hDlg, WM_COMMAND, IDC_DISCONNECTED, 0); } else if (CS_CONNECTED == cs) { // Nothing to do -- we handle connection synchronously } break; } default: break; } pEvent->Release(); // We addrefed it CTAPIEventNotification::Event() return S_OK; }