Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1172 lines
41 KiB

/////////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
//
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
//
// Other brand and product names used herein are trademarks of their respective owners.
//
// The entire program and user interface including the structure, sequence, selection,
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
// by "1" and "2," and each dialog message are protected by copyrights registered in
// the United States and by international treaties.
//
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
//
// Active Voice Corporation
// Seattle, Washington
// USA
//
/////////////////////////////////////////////////////////////////////////////////////////
// TapiNotification.cpp : Implementation of CTapiNotification
#include "stdafx.h"
#include "TapiDialer.h"
#include "AVTapi.h"
#include "AVTapiCall.h"
#include "TapiNotify.h"
/////////////////////////////////////////////////////////////////////////////
// CTapiNotification
CTapiNotification::CTapiNotification()
{
m_dwCookie = NULL;
m_pUnkCP = NULL;
m_lTapiRegister = 0;
}
void CTapiNotification::FinalRelease()
{
ATLTRACE(_T(".enter.CTapiNotification::FinalRelease().\n") );
Shutdown();
CComObjectRootEx<CComMultiThreadModel>::FinalRelease();
}
STDMETHODIMP CTapiNotification::Init(ITTAPI *pITTapi, long *pErrorInfo )
{
ATLTRACE(_T(".enter.CTapiNotification::Init(ref=%ld).\n"), m_dwRef);
_ASSERT( pErrorInfo );
_ASSERT( !m_pUnkCP && !m_dwCookie ); // should only initialize once
HRESULT hr = E_FAIL;
CErrorInfo *per = (CErrorInfo *) pErrorInfo;
Lock();
if ( !m_dwCookie && SUCCEEDED(hr = pITTapi->QueryInterface(IID_IUnknown, (void **) &m_pUnkCP)) )
{
// Register notification object
per->set_Details( IDS_ER_ATL_ADVISE );
if ( SUCCEEDED(hr = per->set_hr(AtlAdvise(pITTapi, GetUnknown(), IID_ITTAPIEventNotification, &m_dwCookie))) )
{
if ( FAILED(hr = ListenOnAllAddresses(pErrorInfo)) )
{
Unlock();
Shutdown();
Lock();
}
}
}
Unlock();
ATLTRACE(_T(".exit.CTapiNotification::Init(%lx, ref=%ld).\n"), hr, m_dwRef);
return hr;
}
STDMETHODIMP CTapiNotification::Shutdown()
{
ATLTRACE(_T(".enter.CTapiNotification::Shutdown(ref=%ld).\n"), m_dwRef);
Lock();
// Unregister with TAPI
CAVTapi *pAVTapi;
if ( m_lTapiRegister && SUCCEEDED(_Module.GetAVTapi(&pAVTapi)) )
{
if ( pAVTapi->m_pITTapi )
{
pAVTapi->m_pITTapi->UnregisterNotifications( m_lTapiRegister );
m_lTapiRegister = 0;
}
(dynamic_cast<IUnknown *> (pAVTapi))->Release();
}
// Unregister with connection point
if ( m_dwCookie )
{
AtlUnadvise( m_pUnkCP, IID_ITTAPIEventNotification, m_dwCookie );
m_dwCookie = 0;
}
// Release connection point unknown
RELEASE( m_pUnkCP );
Unlock();
ATLTRACE(_T(".exit.CTapiNotification::Shutdown(ref=%ld).\n"), m_dwRef);
return S_OK;
}
STDMETHODIMP CTapiNotification::ListenOnAllAddresses( long *pErrorInfo )
{
_ASSERT( pErrorInfo );
CErrorInfo *per = (CErrorInfo *) pErrorInfo;
per->set_Details( IDS_ER_SET_TAPI_NOTIFICATION );
// Make sure that TAPI is running
CAVTapi *pAVTapi;
if ( FAILED(_Module.GetAVTapi(&pAVTapi)) ) return per->set_hr(E_PENDING);
// Create the safe array
long lCount = 0;
HRESULT hr;
per->set_Details( IDS_ER_ENUM_VOICE_ADDRESSES );
IEnumAddress *pIEnumAddresses;
if ( SUCCEEDED(hr = per->set_hr(pAVTapi->m_pITTapi->EnumerateAddresses(&pIEnumAddresses))) )
{
ITAddress *pITAddress = NULL;
while ( (pIEnumAddresses->Next(1, &pITAddress, NULL) == S_OK) && pITAddress )
{
BSTR bstrAddressName;
#ifdef _DEBUG
USES_CONVERSION;
pITAddress->get_AddressName( &bstrAddressName );
#endif
ITMediaSupport *pITMediaSupport;
if ( SUCCEEDED(hr = pITAddress->QueryInterface(IID_ITMediaSupport, (void **) &pITMediaSupport)) )
{
// Address must support Audio In/Out (interactive voice)
long lMediaModes;
if ( SUCCEEDED(hr = pITMediaSupport->get_MediaTypes(&lMediaModes)) )
{
ATLTRACE(_T(".1.ListenOnAllAddresses() -- %s has mediamodes %lx.\n"), OLE2CT(bstrAddressName), lMediaModes );
lMediaModes &= TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO;
if ( lMediaModes )
{
per->set_Details( IDS_ER_REGISTER_CALL_TYPES );
if ( SUCCEEDED(hr = per->set_hr(pAVTapi->m_pITTapi->RegisterCallNotifications(pITAddress, FALSE, TRUE, lMediaModes, m_dwCookie, &m_lTapiRegister))) )
{
ATLTRACE(_T(".1.ListenOnAllAddresses() -- open %s as OWNER.\n"), OLE2CT(bstrAddressName) );
lCount++;
}
else if ( SUCCEEDED(hr = per->set_hr(pAVTapi->m_pITTapi->RegisterCallNotifications(pITAddress, TRUE, FALSE, lMediaModes, m_dwCookie, &m_lTapiRegister))) )
{
ATLTRACE(_T(".1.ListenOnAllAddresses() -- open %s as MONITOR.\n"), OLE2CT(bstrAddressName) );
lCount++;
}
else
{
ATLTRACE(_T(".error.ListenOnAllAddresses() -- open %s FAILED.\n"), OLE2CT(bstrAddressName) );
}
}
}
else
{
ATLTRACE(_T(".error.ListenOnAllAddresses() -- %s has GetMediaModes returned=%lx.\n"), OLE2CT(bstrAddressName), hr );
}
pITMediaSupport->Release();
}
else
{
ATLTRACE(_T(".error.ListenOnAllAddresses() -- %s has QueryInterfaceMediaModes returned=%lx.\n"), OLE2CT(bstrAddressName), hr );
}
pITAddress->Release();
#ifdef _DEBUG
SysFreeString( bstrAddressName );
#endif
}
pIEnumAddresses->Release();
}
// Only flag error if no drivers are found.
hr = S_OK;
if ( !lCount )
{
ATLTRACE(_T(".error.CTapiNotification::ListenOnAllAddresses() -- did not open any lines.\n"));
per->set_Details( IDS_ER_NO_LINES_OPEN );
hr = per->set_hr( E_FAIL );
}
(dynamic_cast<IUnknown *> (pAVTapi))->Release();
ATLTRACE(_T(".exit.CTapiNotification::ListenOnAllAddresses(0x%08lx).\n"), hr );
return hr;
}
STDMETHODIMP CTapiNotification::Event( TAPI_EVENT TapiEvent, IDispatch *pEvent )
{
CAVTapi *pAVTapi;
if ( FAILED(_Module.GetAVTapi(&pAVTapi)) ) return S_OK; // Tapi object doesnt exist
HRESULT hr = S_OK;
switch( TapiEvent )
{
// Notification of a new call
case TE_CALLNOTIFICATION: hr = CallNotification_Event( pAVTapi, pEvent ); break;
case TE_CALLSTATE: hr = CallState_Event( pAVTapi, pEvent ); break;
case TE_PRIVATE: hr = Private_Event( pAVTapi, pEvent ); break;
case TE_REQUEST: hr = Request_Event( pAVTapi, pEvent ); break;
case TE_CALLINFOCHANGE: hr = CallInfoChange_Event( pAVTapi, pEvent ); break;
case TE_CALLMEDIA: hr = CallMedia_Event( pAVTapi, pEvent ); break;
case TE_ADDRESS: hr = Address_Event( pAVTapi, pEvent ); break;
case TE_PHONEEVENT: hr = Phone_Event( pAVTapi, pEvent ); break;
case TE_TAPIOBJECT: hr = TapiObject_Event( pAVTapi, pEvent); break;
// Hmmm.....
default:
ATLTRACE(_T(".warning.CTapiNotification::Event(%d) event unhandled.\n"), TapiEvent );
break;
}
(dynamic_cast<IUnknown *> (pAVTapi))->Release();
return hr;
}
HRESULT CTapiNotification::CallNotification_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
HRESULT hr;
ITCallNotificationEvent *pCallNotify;
if ( SUCCEEDED(hr = pEvent->QueryInterface(IID_ITCallNotificationEvent, (void **) &pCallNotify)) )
{
ITCallInfo *pCallInfo;
if ( SUCCEEDED(hr = pCallNotify->get_Call(&pCallInfo)) )
{
//
// Handle the call in the old way
//
ITAddress *pITAddress;
if ( SUCCEEDED(hr = pCallInfo->get_Address(&pITAddress)) )
{
// Retrieve address type for caller info
long lAddressType;
if ( SUCCEEDED(hr = GetCallerAddressType(pCallInfo, (DWORD*)&lAddressType)) )
{
AVCallType nType = AV_VOICE_CALL;
long nSize = 0;
byte * pBuffer;
hr = pCallInfo->GetCallInfoBuffer( CIB_USERUSERINFO, (DWORD*)&nSize, &pBuffer );
if ( SUCCEEDED(hr) ) CoTaskMemFree( pBuffer );
// Simple check for now
if ( nSize == sizeof(MyUserUserInfo) ) nType = AV_DATA_CALL;
// Create new call notification dialog
IAVTapiCall *pAVCall;
if ( SUCCEEDED(hr = pAVTapi->fire_NewCall(pITAddress, lAddressType, 0, pCallInfo, nType, &pAVCall)) )
{
// Set the address type for the call
DWORD dwAddressType = LINEADDRESSTYPE_IPADDRESS;
GetCallerAddressType(pCallInfo, &dwAddressType);
pAVCall->put_dwAddressType( dwAddressType );
ATLTRACE(_T(".1.CTapiNotification::CallNotification_Event() -- address identified as %lx.\n"), dwAddressType );
// Retrieve the caller ID for this call
pAVCall->GetCallerIDInfo( pCallInfo );
// Automatically answer data calls
if ( nType == AV_DATA_CALL )
{
long lCallID;
pAVCall->get_lCallID( &lCallID );
pAVTapi->ActionSelected( lCallID, CM_ACTIONS_TAKECALL );
}
pAVCall->Release();
}
pITAddress->Release();
}
}
pCallInfo->Release();
}
pCallNotify->Release();
}
return hr;
}
HRESULT CTapiNotification::CallState_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
ATLTRACE(_T(".enter.CTapiNotification::CallState_Event().\n"));
HRESULT hr;
bool bReleaseEvent = true;
// Rummage through interfaces to get to the CallControl object
ITCallStateEvent *pITCallStateEvent;
if ( SUCCEEDED(hr = pEvent->QueryInterface(IID_ITCallStateEvent, (void **) &pITCallStateEvent)) )
{
#ifdef _DEBUG
CALL_STATE nState;
pITCallStateEvent->get_State(&nState);
ATLTRACE(_T(".1.CTapiNotification::CallState_Event(%d).\n"), nState);
#endif
ITCallInfo *pInfo;
if ( SUCCEEDED(hr = pITCallStateEvent->get_Call(&pInfo)) && pInfo )
{
ITBasicCallControl *pControl = NULL;
if ( SUCCEEDED(hr = pInfo->QueryInterface(IID_ITBasicCallControl, (void **) &pControl)) )
{
// Must be a call other than the one in the confroom
IAVTapiCall *pAVCall = pAVTapi->FindAVTapiCall( pControl );
if ( pAVCall )
{
if ( SUCCEEDED(pAVCall->PostMessage(WM_CALLSTATE, (WPARAM) pITCallStateEvent)) )
{
bReleaseEvent = false;
}
else
{
long lCallID = 0;
pAVCall->get_lCallID( &lCallID );
if ( lCallID )
hr = pAVTapi->fire_SetCallState( lCallID, pITCallStateEvent, pAVCall );
}
pAVCall->Release();
}
pControl->Release();
}
pInfo->Release();
}
// Only release in the case that the post thread message failed
if ( bReleaseEvent )
pITCallStateEvent->Release();
}
ATLTRACE(_T(".exit.CTapiNotification::CallState_Event().\n"));
return hr;
}
HRESULT CTapiNotification::CallMedia_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
USES_CONVERSION;
TCHAR szText[255], szDir[255], szMessage[512];
CALL_MEDIA_EVENT_CAUSE nCause;
BSTR bstrName = NULL;
TERMINAL_DIRECTION nDir;
CErrorInfo er;
ITCallMediaEvent *pMediaEvent;
if ( SUCCEEDED(pEvent->QueryInterface(IID_ITCallMediaEvent, (void **) &pMediaEvent)) )
{
CALL_MEDIA_EVENT cme;
if ( SUCCEEDED(pMediaEvent->get_Event(&cme)) && ((cme == CME_STREAM_ACTIVE) || (cme == CME_STREAM_INACTIVE)) )
{
switch ( cme )
{
// Notify the user of the terminal failing event
case CME_TERMINAL_FAIL:
{
ITTerminal *pTerminal;
if ( SUCCEEDED(pMediaEvent->get_Terminal(&pTerminal)) )
{
pTerminal->get_Name( &bstrName );
pTerminal->get_Direction( &nDir );
LoadString( _Module.GetResourceInstance(), (nDir == TD_CAPTURE) ? IDS_TD_CAPTURE : IDS_TD_RENDER, szDir, ARRAYSIZE(szDir) );
LoadString( _Module.GetResourceInstance(), IDS_ER_CALLMEDIA_STREAMFAIL, szText, ARRAYSIZE(szText) );
_sntprintf( szMessage, ARRAYSIZE(szMessage), szText, OLE2CT(bstrName), szDir );
SysReAllocString( &er.m_bstrOperation, T2COLE(szMessage) );
pMediaEvent->get_Cause( &nCause );
switch ( nCause )
{
case CMC_CONNECT_FAIL: er.set_Details( IDS_ER_CMC_CONNECT_FAIL ); break;
case CMC_REMOTE_REQUEST: er.set_Details( IDS_ER_CMC_REMOTE_REQUEST ); break;
case CMC_MEDIA_TIMEOUT: er.set_Details( IDS_ER_CMC_MEDIA_TIMEOUT ); break;
case CMC_MEDIA_RECOVERED: er.set_Details( IDS_ER_CMC_MEDIA_RECOVERED ); break;
case CMC_BAD_DEVICE: er.set_Details( IDS_ER_CMC_BADDEVICE ); break;
default: er.set_Details( IDS_ER_CMC_BADDEVICE ); break;
}
// flag and notify of the error
er.set_hr( E_FAIL );
pTerminal->Release();
}
}
break;
// Notify the user of the stream failing event.
case CME_STREAM_FAIL:
{
ITStream *pStream;
if ( SUCCEEDED(pMediaEvent->get_Stream(&pStream)) )
{
pStream->get_Name( &bstrName );
pStream->get_Direction( &nDir );
LoadString( _Module.GetResourceInstance(), (nDir == TD_CAPTURE) ? IDS_TD_CAPTURE : IDS_TD_RENDER, szDir, ARRAYSIZE(szDir) );
LoadString( _Module.GetResourceInstance(), IDS_ER_CALLMEDIA_STREAMFAIL, szText, ARRAYSIZE(szText) );
_sntprintf( szMessage, ARRAYSIZE(szMessage), szText, OLE2CT(bstrName), szDir );
SysReAllocString( &er.m_bstrOperation, T2COLE(szMessage) );
pMediaEvent->get_Cause( &nCause );
switch ( nCause )
{
case CMC_CONNECT_FAIL: er.set_Details( IDS_ER_CMC_CONNECT_FAIL ); break;
case CMC_REMOTE_REQUEST: er.set_Details( IDS_ER_CMC_REMOTE_REQUEST ); break;
case CMC_MEDIA_TIMEOUT: er.set_Details( IDS_ER_CMC_MEDIA_TIMEOUT ); break;
case CMC_MEDIA_RECOVERED: er.set_Details( IDS_ER_CMC_MEDIA_RECOVERED ); break;
case CMC_BAD_DEVICE: er.set_Details( IDS_ER_CMC_BADDEVICE ); break;
default: er.set_Details( IDS_ER_CMC_BADDEVICE ); break;
}
// flag and notify of the error
er.set_hr( E_FAIL );
pStream->Release();
}
}
break;
// Stream is starting or stopping here.
case CME_STREAM_ACTIVE:
case CME_STREAM_INACTIVE:
//
// We should initialize local variable
//
long lMediaType = 0;
TERMINAL_DIRECTION nDir = TD_CAPTURE;
ITStream *pITStream;
if ( SUCCEEDED(pMediaEvent->get_Stream(&pITStream)) )
{
pITStream->get_Direction( &nDir );
pITStream->get_MediaType( &lMediaType );
pITStream->Release();
}
// Only post message in the case of video preview!
if ( (lMediaType & TAPIMEDIATYPE_VIDEO) != 0 )
{
ITCallInfo *pCallInfo = NULL;
if ( SUCCEEDED(pMediaEvent->get_Call(&pCallInfo)) && pCallInfo )
{
IAVTapiCall *pAVCall;
if ( SUCCEEDED(pAVTapi->FindAVTapiCallFromCallInfo(pCallInfo, &pAVCall)) )
{
if ( nDir == TD_CAPTURE )
pAVCall->PostMessage( 0, (cme == CME_STREAM_ACTIVE) ? CAVTapiCall::TI_STREAM_ACTIVE : CAVTapiCall::TI_STREAM_INACTIVE );
else
pAVCall->PostMessage( 0, (cme == CME_STREAM_ACTIVE) ? CAVTapiCall::TI_RCV_VIDEO_ACTIVE : CAVTapiCall::TI_RCV_VIDEO_INACTIVE );
pAVCall->Release();
}
pCallInfo->Release();
}
}
break;
}
}
pMediaEvent->Release();
}
SysFreeString( bstrName );
return S_OK;
}
HRESULT CTapiNotification::Request_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
ITRequestEvent *pRequestEvent;
if ( SUCCEEDED(pEvent->QueryInterface(IID_ITRequestEvent, (void **) &pRequestEvent)) )
{
USES_CONVERSION;
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
BSTR bstrCalledParty = NULL, bstrAddress = NULL, bstrAppName = NULL, bstrComment = NULL;
pRequestEvent->get_CalledParty( &bstrCalledParty );
pRequestEvent->get_DestAddress( &bstrAddress );
pRequestEvent->get_AppName( &bstrAppName );
pRequestEvent->get_Comment( &bstrComment );
DWORD dwAddressType = _Module.GuessAddressType( OLE2CT(bstrAddress) );
// Work around for assisted telehpony
if ( (dwAddressType == LINEADDRESSTYPE_DOMAINNAME) &&
(SysStringLen(bstrAddress) > 1) &&
((bstrAddress[0] == _L('P')) || (bstrAddress[0] == _L('T'))) )
{
BSTR bstrTemp = SysAllocString( &bstrAddress[1] );
if ( bstrTemp )
{
dwAddressType = LINEADDRESSTYPE_PHONENUMBER;
SysFreeString( bstrAddress );
bstrAddress = bstrTemp;
}
}
pAVTapi->CreateCallEx( bstrCalledParty, bstrAddress, bstrAppName, bstrComment, dwAddressType );
SysFreeString( bstrCalledParty );
SysFreeString( bstrAddress );
SysFreeString( bstrAppName );
SysFreeString( bstrComment );
}
// Clean-up
pRequestEvent->Release();
}
return S_OK;
}
HRESULT CTapiNotification::CallInfoChange_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
USES_CONVERSION;
ITCallInfoChangeEvent *pCallInfoEvent;
if ( SUCCEEDED(pEvent->QueryInterface(IID_ITCallInfoChangeEvent, (void **) &pCallInfoEvent)) )
{
ITCallInfo *pCallInfo = NULL;
if ( SUCCEEDED(pCallInfoEvent->get_Call(&pCallInfo)) && pCallInfo )
{
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
CALLINFOCHANGE_CAUSE nCause;
pCallInfoEvent->get_Cause( &nCause );
ATLTRACE(_T(".1.CTapiNotification::CallInfoChange_Event() -- received %d.\n"), nCause );
IAVTapiCall *pAVCall;
if ( SUCCEEDED(pAVTapi->FindAVTapiCallFromCallInfo(pCallInfo, &pAVCall)) )
{
switch ( nCause )
{
case CIC_CALLID:
case CIC_RELATEDCALLID:
case CIC_CALLERID:
case CIC_CALLEDID:
case CIC_CONNECTEDID:
case CIC_REDIRECTIONID:
case CIC_REDIRECTINGID:
// What caller info has changed?
pAVCall->GetCallerIDInfo( pCallInfo );
break;
case CIC_CALLDATA:
break;
case CIC_USERUSERINFO:
pAVCall->PostMessage( NULL, CAVTapiCall::TI_USERUSERINFO );
break;
}
pAVCall->Release();
}
}
pCallInfo->Release();
}
pCallInfoEvent->Release();
}
return S_OK;
}
HRESULT CTapiNotification::Private_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
ITPrivateEvent *pPrivateEvent;
if ( SUCCEEDED(pEvent->QueryInterface(IID_ITPrivateEvent, (void **) &pPrivateEvent)) )
{
IDispatch *pDispatch;
if ( SUCCEEDED(pPrivateEvent->get_EventInterface(&pDispatch)))
{
// Is this a participant event for the conference room?
ITParticipantEvent *pParticipantEvent;
if ( SUCCEEDED(pDispatch->QueryInterface(IID_ITParticipantEvent, (void **) &pParticipantEvent)) )
{
PARTICIPANT_EVENT nEvent;
ITParticipant *pParticipant = NULL;
ITCallInfo *pCallInfo = NULL;
IAVTapiCall *pAVCall = NULL;
if ( SUCCEEDED(pParticipantEvent->get_Event(&nEvent)) &&
SUCCEEDED(pParticipantEvent->get_Participant(&pParticipant)) &&
SUCCEEDED(pPrivateEvent->get_Call(&pCallInfo)) &&
SUCCEEDED(pAVTapi->FindAVTapiCallFromCallInfo(pCallInfo, &pAVCall)) )
{
switch ( nEvent )
{
case PE_NEW_PARTICIPANT: // Participant joining
if ( SUCCEEDED(pAVCall->PostMessage(WM_ADDPARTICIPANT, (WPARAM) pParticipant)) )
pParticipant->AddRef();
break;
case PE_PARTICIPANT_LEAVE: // Participant leaving
if ( SUCCEEDED(pAVCall->PostMessage(WM_REMOVEPARTICIPANT, (WPARAM) pParticipant)) )
pParticipant->AddRef();
break;
case PE_INFO_CHANGE: // Participant info change
if ( SUCCEEDED(pAVCall->PostMessage(WM_UPDATEPARTICIPANT, (WPARAM) pParticipant)) )
pParticipant->AddRef();
break;
/////////////////////////////////////////////////
// video stream starting or stoping
case PE_SUBSTREAM_MAPPED:
case PE_SUBSTREAM_UNMAPPED:
if ( SUCCEEDED(pAVCall->PostMessage(WM_STREAM_EVENT, (WPARAM) pParticipantEvent)) )
pParticipantEvent->AddRef();
break;
}
}
RELEASE( pAVCall );
RELEASE( pCallInfo );
RELEASE( pParticipant );
pParticipantEvent->Release();
}
pDispatch->Release();
}
pPrivateEvent->Release();
}
return S_OK;
}
/*++
GetCallerAddressType
Description:
Used by CallNotification_Event to get the right caller address type,
instead ITCallInfo::get_CallInfoLong(CIL_CALEERADDRESSTYPE) that
returns failed
Parameters:
[in] ITCallInfo - the callinfo interface
[out] DWORD* - the caller address type
Return:
Success code
--*/
HRESULT CTapiNotification::GetCallerAddressType(
IN ITCallInfo* pCall,
OUT DWORD* pAddressType
)
{
//
// Validates parameters
//
if( NULL == pCall)
return E_INVALIDARG;
if( IsBadWritePtr(pAddressType, sizeof(DWORD)) )
return E_POINTER;
//
// Get the ITAddress interface
//
ITAddress* pTAddress = NULL;
HRESULT hr = pCall->get_Address(&pTAddress);
if( FAILED(hr) )
return E_UNEXPECTED;
//
// Get ITAddressCapabilities
//
ITAddressCapabilities* pTAddressCap = NULL;
hr = pTAddress->QueryInterface(IID_ITAddressCapabilities, (void**)&pTAddressCap);
pTAddress->Release(); //That's all, release ITAddress
if( FAILED(hr) )
return E_UNEXPECTED;
//
// Get the protocol
//
BSTR bstrProtocol;
hr = pTAddressCap->get_AddressCapabilityString(ACS_PROTOCOL, &bstrProtocol);
pTAddressCap->Release(); // That's all, release ITAddressCapabilities
if( FAILED(hr) )
return hr;
CLSID clsidProtocol;
hr = CLSIDFromString(bstrProtocol, &clsidProtocol);
SysFreeString(bstrProtocol);
if( FAILED(hr) )
{
return hr;
}
//
// OK, let's see what we got here
//
if( TAPIPROTOCOL_H323 == clsidProtocol )
{
// Internet call
*pAddressType = LINEADDRESSTYPE_IPADDRESS;
return S_OK;
}
else if ( TAPIPROTOCOL_Multicast == clsidProtocol )
{
// Conference
*pAddressType = LINEADDRESSTYPE_SDP;
return S_OK;
}
else if ( TAPIPROTOCOL_PSTN == clsidProtocol )
{
// Phone call
*pAddressType = LINEADDRESSTYPE_PHONENUMBER;
return S_OK;
}
//Badluck
return E_FAIL;
}
HRESULT CTapiNotification::Address_Event( CAVTapi *pAVTapi, IDispatch *pEvent )
{
USES_CONVERSION;
ITAddressEvent *pAddressEvent;
if ( SUCCEEDED(pEvent->QueryInterface(IID_ITAddressEvent, (void **) &pAddressEvent)) )
{
ADDRESS_EVENT ae;
if ( SUCCEEDED(pAddressEvent->get_Event(&ae)) &&
((ae == AE_NEWTERMINAL) || (ae == AE_REMOVETERMINAL) /*||
(ae == AE_NEWPHONE) || (ae == AE_REMOVEPHONE)*/) )
{
switch ( ae )
{
// A terminal has arrived via PNP
case AE_NEWTERMINAL:
{
ATLTRACE(_T(".1.CTapiNotification::Address_Event() -- received AE_NEWTERMINAL.\n"));
ITTerminal *pTerminal;
if ( SUCCEEDED(pAddressEvent->get_Terminal(&pTerminal)) )
{
ITAddress *pAddress;
if ( SUCCEEDED(pAddressEvent->get_Address(&pAddress)) )
{
IEnumCall * pEnumCall;
HRESULT hr;
ITCallInfo * pCallInfo;
IAVTapiCall * pAVTapiCall;
//
// enumerate the current calls
//
if ( SUCCEEDED(pAddress->EnumerateCalls( &pEnumCall )) )
{
//
// go through the list
//
while (TRUE)
{
hr = pEnumCall->Next( 1, &pCallInfo, NULL);
if (S_OK != hr)
{
break;
}
if ( SUCCEEDED( pAVTapi->FindAVTapiCallFromCallInfo(pCallInfo, &pAVTapiCall) ) )
{
pAVTapiCall->TerminalArrival(pTerminal);
pAVTapiCall->Release();
}
//
// release this reference
//
pCallInfo->Release();
}
pEnumCall->Release();
}
pAddress->Release();
}
pTerminal->Release();
}
}
break;
// A terminal has been removed via PNP
case AE_REMOVETERMINAL:
{
ATLTRACE(_T(".1.CTapiNotification::Address_Event() -- received AE_REMOVETERMINAL.\n"));
ITTerminal *pTerminal;
if ( SUCCEEDED(pAddressEvent->get_Terminal(&pTerminal)) )
{
ITAddress *pAddress;
if ( SUCCEEDED(pAddressEvent->get_Address(&pAddress)) )
{
IEnumCall * pEnumCall;
HRESULT hr;
ITCallInfo * pCallInfo;
IAVTapiCall * pAVTapiCall;
//
// enumerate the current calls
//
if ( SUCCEEDED(pAddress->EnumerateCalls( &pEnumCall )) )
{
//
// go through the list
//
while (TRUE)
{
hr = pEnumCall->Next( 1, &pCallInfo, NULL);
if (S_OK != hr)
{
break;
}
if ( SUCCEEDED( pAVTapi->FindAVTapiCallFromCallInfo(pCallInfo, &pAVTapiCall) ) )
{
pAVTapiCall->TerminalRemoval(pTerminal);
pAVTapiCall->Release();
}
//
// release this reference
//
pCallInfo->Release();
}
pEnumCall->Release();
}
pAddress->Release();
}
pTerminal->Release();
}
}
break;
}
}
pAddressEvent->Release();
}
return S_OK;
}
HRESULT CTapiNotification::Phone_Event(
IN CAVTapi *pAVTapi,
IN IDispatch *pEvent )
{
// We should have an USB phone
BOOL bUSBPresent = FALSE;
pAVTapi->USBIsPresent(&bUSBPresent);
if( !bUSBPresent )
{
return S_OK;
}
//
// We should have checked the USB checkbox
//
BOOL bUSBCheckbox = FALSE;
pAVTapi->USBGetDefaultUse( &bUSBCheckbox );
if( !bUSBCheckbox )
{
return S_OK;
}
// Get ITPhone event interface
ITPhoneEvent* pPhoneEvent = NULL;
HRESULT hr = E_FAIL;
hr = pEvent->QueryInterface( IID_ITPhoneEvent, (void**)&pPhoneEvent);
if( FAILED(hr) )
{
return hr;
}
// Get the subevent code
PHONE_EVENT PECode;
hr = pPhoneEvent->get_Event(&PECode);
if( FAILED(hr) )
{
pPhoneEvent->Release();
return hr;
}
// So let's see what happened
switch( PECode)
{
case PE_ANSWER:
{
pAVTapi->USBAnswer();
}
break;
case PE_HOOKSWITCH:
{
// Get the hook state
PHONE_HOOK_SWITCH_STATE HookState;
hr = pPhoneEvent->get_HookSwitchState(&HookState);
if( FAILED(hr) )
{
break;
}
PHONE_HOOK_SWITCH_DEVICE HookDevice;
hr = pPhoneEvent->get_HookSwitchDevice(&HookDevice);
if( FAILED(hr) )
{
break;
}
if( HookDevice != PHSD_HANDSET)
{
break;
}
switch( HookState )
{
case PHSS_OFFHOOK:
// +++ FIXBUF 100830 +++
// we popuup 'PlaceCall' dialog
// just when a key was pressed
//pAVTapi->USBMakeCall();
break;
case PHSS_ONHOOK:
pAVTapi->USBCancellCall( );
break;
default:
break;
}
}
break;
case PE_BUTTON:
{
// Get Key event
long lButton = 0;
hr = pPhoneEvent->get_ButtonLampId(&lButton);
if( FAILED(hr) )
{
break;
}
// Get the button state
PHONE_BUTTON_STATE ButtonState;
hr = pPhoneEvent->get_ButtonState(&ButtonState);
if( FAILED(hr) )
{
break;
}
switch( ButtonState )
{
case PBS_DOWN:
//
// We should popup the Dial Dialogbox
//
if( (0 <= lButton) && (lButton <= 10 ) )
{
// Just if the user pressed a digit key
// In USBMakeCall() method will check to see
// if there is no 'Placecall' dialog
// We allow also * key
pAVTapi->USBMakeCall();
}
break;
case PBS_UP:
//
// If the Dial dialog is opened, show the digit
// If the Phone is selected on a call
// send the digit
//
pAVTapi->USBKeyPress( lButton );
break;
default:
break;
}
}
break;
case PE_NUMBERGATHERED:
{
//
// We read the phone number from the
// 'PlaceCall' dialog box
//
pAVTapi->USBKeyPress( (long)PT_KEYPADPOUND );
}
break;
default:
break;
}
// Clean-up
pPhoneEvent->Release();
return S_OK;
}
HRESULT CTapiNotification::TapiObject_Event(
IN CAVTapi *pAVTapi,
IN IDispatch *pEvent
)
{
//
// Validates the event interface
//
if( NULL == pEvent)
{
return S_OK;
}
//
// Get ITTAPIObjectEvent interface
//
ITTAPIObjectEvent* pTapiEvent = NULL;
HRESULT hr = pEvent->QueryInterface(
IID_ITTAPIObjectEvent,
(void**)&pTapiEvent);
if( FAILED(hr) )
{
//
// We cannot get ITTAPIObjectEvent interface
//
return S_OK;
}
//
// Get the TAPIOBJECT_EVENT
//
TAPIOBJECT_EVENT toEvent = TE_ADDRESSCREATE;
hr = pTapiEvent->get_Event( &toEvent );
if( SUCCEEDED(hr) )
{
switch( toEvent )
{
case TE_PHONECREATE:
//
// A phone was added
//
if( pAVTapi)
{
//
// Get the ITTAPIObjectEvent2
//
ITTAPIObjectEvent2* pTapiEvent2 = NULL;
hr = pTapiEvent->QueryInterface(
IID_ITTAPIObjectEvent2, (void**)&pTapiEvent2);
if( SUCCEEDED(hr) )
{
//
// Get the phone object
//
ITPhone* pPhone = NULL;
hr = pTapiEvent2->get_Phone(&pPhone);
//
// Clean-up ITTAPIObjectEvent2
//
pTapiEvent2->Release();
//
// Initialize the new phone
//
if( SUCCEEDED(hr) )
{
pAVTapi->USBNewPhone(
pPhone);
//
// Clean-up phone
//
pPhone->Release();
}
}
}
break;
case TE_PHONEREMOVE:
//
// A phone was removed
//
if( pAVTapi)
{
//
// Get the ITTAPIObjectEvent2
//
ITTAPIObjectEvent2* pTapiEvent2 = NULL;
hr = pTapiEvent->QueryInterface(
IID_ITTAPIObjectEvent2, (void**)&pTapiEvent2);
if( SUCCEEDED(hr) )
{
//
// Get the phone object
//
ITPhone* pPhone = NULL;
hr = pTapiEvent2->get_Phone(&pPhone);
//
// Clean-up ITTAPIObjectEvent2
//
pTapiEvent2->Release();
//
// Initialize the new phone
//
if( SUCCEEDED(hr) )
{
pAVTapi->USBRemovePhone(
pPhone);
//
// Clean-up phone
//
pPhone->Release();
}
}
}
break;
default:
break;
}
}
//
// Clen-up ITTAPIObjectEvent interface
//
pTapiEvent->Release();
return S_OK;
}