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.
 
 
 
 
 
 

1895 lines
56 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
//
/////////////////////////////////////////////////////////////////////////////////////////
// AVTapiCall.cpp : Implementation of CAVTapiCall
#include "stdafx.h"
#include "TapiDialer.h"
#include "AVTapi.h"
#include "AVTapiCall.h"
#include "CRTreeView.h"
#include "ConfRoom.h"
#include "CRMemWnd.h"
/////////////////////////////////////////////////////////////////////////////
// CAVTapiCall
CAVTapiCall::CAVTapiCall()
{
m_dwThreadID = 0;
m_pITControl = NULL;
m_pITTerminalPreview = NULL;
m_callState = CS_IDLE;
m_bCallLogged = false;
m_nCallType = AV_VOICE_CALL;
m_bstrName = NULL;
for ( int i = 0; i < NUM_USER_BSTR; i++ )
m_bstrUser[i] = NULL;
m_bstrDisplayableAddress = NULL;
m_bstrOriginalAddress = NULL;
m_dwAddressType = 0;
m_nCallLogType = CL_CALL_OUTGOING;
m_lCallID = 0;
m_bKillMe = false;
m_bResolvedAddress = false;
m_bPreviewStreaming = false;
m_bRcvVideoStreaming = false;
m_bMustDisconnect = false;
SYSTEMTIME st;
GetLocalTime( &st );
SystemTimeToVariantTime( &st, &m_dateStart );
}
void CAVTapiCall::FinalRelease()
{
ATLTRACE(_T(".enter.CAVTapiCall::FinalRelease().\n"));
#ifdef _DEBUG
if ( !m_bCallLogged )
ATLTRACE(_T(".warning.CAVTapiCall::FinalRelease() -- call not logged.\n") );
#endif _DEBUG
m_bKillMe = true;
// Insure that the Video windows have been destroyed
short i = 0;
IVideoWindow *pVideoWindow;
while ( SUCCEEDED(get_IVideoWindow(i, (IDispatch **) &pVideoWindow)) )
{
ATLTRACE(_T(".1.CAVTapiCall::FinalRelease() hiding term #%d.\n"), i );
// CAVTapi::SetVideoWindowProperties( pVideoWindow, NULL, false );
pVideoWindow->Release();
i++;
}
// Video preview
if ( SUCCEEDED(get_IVideoWindowPreview((IDispatch **) &pVideoWindow)) )
{
ATLTRACE(_T(".1.CAVTapiCall::FinalRelease() hiding preview.\n") );
CAVTapi::SetVideoWindowProperties( pVideoWindow, NULL, false );
pVideoWindow->Release();
}
m_atomList.Lock( CAtomicList::LIST_WRITE );
RELEASE_LIST( m_lstParticipants );
m_atomList.Unlock( CAtomicList::LIST_WRITE );
RELEASE_CRITLIST( m_lstStreamingVideo, m_critLstStreamingVideo );
RELEASE( m_pITControl );
RELEASE( m_pITTerminalPreview );
#ifdef _DEBUG
// Clean out the list of terminal streams
USES_CONVERSION;
TERMINALLIST::iterator j, jEnd = m_lstTerminals.end();
for ( j = m_lstTerminals.begin(); j != jEnd; j++ )
{
BSTR bstrName = NULL;
(*j)->get_Name( &bstrName );
(*j)->AddRef();
DWORD dwRet = (*j)->Release();
ATLTRACE(_T(".1.CAVTapiCall::FinalRelease() -- terminal ref @ %d, %s.\n"), dwRet - 1, OLE2CT(bstrName) );
SysFreeString( bstrName );
}
#endif
RELEASE_CRITLIST( m_lstTerminals, m_critTerminals );
// Shutdown thread
if ( m_dwThreadID )
{
PostThreadMessage( m_dwThreadID, WM_THREADINSTRUCTION, TI_QUIT, 0 );
Sleep(0);
}
SysFreeString( m_bstrDisplayableAddress );
SysFreeString( m_bstrOriginalAddress );
SysFreeString( m_bstrName );
for ( i = 0; i < NUM_USER_BSTR; i++ )
SysFreeString( m_bstrUser[i] );
ATLTRACE(_T(".exit.CAVTapiCall::FinalRelease().\n"));
CComObjectRootEx<CComMultiThreadModel>::FinalRelease();
}
STDMETHODIMP CAVTapiCall::get_lCallID(long * pVal)
{
Lock();
*pVal = m_lCallID;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_lCallID(long newVal)
{
Lock();
m_lCallID = newVal;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_callState(CALL_STATE * pVal)
{
Lock();
*pVal = m_callState;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_callState(CALL_STATE newVal)
{
DWORD dwAddressType = 0;
Lock();
m_callState = newVal;
dwAddressType = m_dwAddressType;
if ( m_callState == CS_CONNECTED )
m_bMustDisconnect = true;
Unlock();
// Notify conf room of state change (might be it's call)
if ( dwAddressType == LINEADDRESSTYPE_SDP )
{
CErrorInfo er( IDS_ER_THREAD_MSG_PROCESS, IDS_ER_CALL_ENTERCONFROOM );
er.set_hr( NotifyConfRoomState((long *) &er) );
// PostMessage( 0, CAVTapiCall::TI_NOTIFYCONFROOMSTATE );
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_ITBasicCallControl(ITBasicCallControl **ppVal)
{
HRESULT hr = E_FAIL;
Lock();
if ( m_pITControl )
hr = m_pITControl->QueryInterface( IID_ITBasicCallControl, (void **) ppVal );
else
*ppVal = NULL;
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::put_ITBasicCallControl(ITBasicCallControl *newVal)
{
HRESULT hr = S_OK;
Lock();
RELEASE( m_pITControl );
if ( newVal )
hr = newVal->QueryInterface( IID_ITBasicCallControl, (void **) &m_pITControl );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_ITTerminalPreview(ITTerminal **ppVal)
{
HRESULT hr = E_FAIL;
Lock();
if ( m_pITTerminalPreview )
hr = m_pITTerminalPreview->QueryInterface( IID_ITTerminal, (void **) ppVal );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::put_ITTerminalPreview(ITTerminal * newVal)
{
HRESULT hr = S_OK;
Lock();
RELEASE( m_pITTerminalPreview );
if ( newVal )
hr = newVal->QueryInterface( IID_ITTerminal, (void **) &m_pITTerminalPreview );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_IVideoWindowPreview(IDispatch **ppVal)
{
HRESULT hr = E_FAIL;
Lock();
if ( m_pITTerminalPreview )
hr = m_pITTerminalPreview->QueryInterface( IID_IVideoWindow, (void **) ppVal );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_ITCallInfo(ITCallInfo **ppVal)
{
HRESULT hr = E_FAIL;
Lock();
if ( m_pITControl )
hr = m_pITControl->QueryInterface( IID_ITCallInfo, (void **) ppVal );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_ITParticipantControl(ITParticipantControl **ppVal)
{
HRESULT hr = E_FAIL;
Lock();
if ( m_pITControl )
hr = m_pITControl->QueryInterface( IID_ITParticipantControl, (void **) ppVal );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_ITAddress(ITAddress **ppVal)
{
Lock();
if ( !m_pITControl )
{
Unlock();
return E_PENDING;
}
HRESULT hr;
ITCallInfo *pInfo;
if ( SUCCEEDED(hr = m_pITControl->QueryInterface(IID_ITCallInfo, (void **) &pInfo)) )
{
hr = pInfo->get_Address( ppVal );
pInfo->Release();
}
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_ITCallHub(ITCallHub **ppVal)
{
HRESULT hr = E_PENDING;
Lock();
// Register for call hub notifications
ITCallInfo *pCallInfo;
if ( SUCCEEDED(hr = get_ITCallInfo(&pCallInfo)) )
{
hr = pCallInfo->get_CallHub( ppVal );
pCallInfo->Release();
}
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_IBasicVideo(IDispatch **ppVal)
{
_ASSERT( FALSE ); // implement please
return E_FAIL;
}
STDMETHODIMP CAVTapiCall::get_bKillMe(BOOL *pVal)
{
Lock();
*pVal = m_bKillMe;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_bKillMe(BOOL newVal)
{
Lock();
m_bKillMe = newVal;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_nCallLogType(CallLogType * pVal)
{
Lock();
*pVal = m_nCallLogType;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_nCallLogType(CallLogType newVal)
{
Lock();
m_nCallLogType = newVal;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::CheckKillMe()
{
Lock();
HRESULT hr = (m_bKillMe) ? E_ABORT : S_OK;
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::AddTerminal(ITTerminal *pITTerminal)
{
_ASSERT( pITTerminal );
DWORD dwCount = pITTerminal->AddRef();
ATLTRACE(_T(".CAVTapiCall::AddTerminal() -- ref count at %ld.\n"), dwCount );
m_critTerminals.Lock();
m_lstTerminals.push_back( pITTerminal );
m_critTerminals.Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::RemoveTerminal(ITTerminal *pITTerminal)
{
_ASSERT( pITTerminal );
m_critTerminals.Lock();
m_lstTerminals.remove( pITTerminal );
m_critTerminals.Unlock();
DWORD dwCount = pITTerminal->Release();
ATLTRACE(_T(".CAVTapiCall::AddTerminal() -- ref count at %ld.\n"), dwCount );
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_dwAddressType(DWORD * pVal)
{
Lock();
*pVal = m_dwAddressType;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_dwAddressType(DWORD newVal)
{
Lock();
m_dwAddressType = newVal;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::Disconnect( VARIANT_BOOL bKill )
{
// Signal that this call can be disconnected
if ( bKill )
put_bKillMe( TRUE );
HRESULT hr;
ITBasicCallControl *pITControl = NULL;
if ( (hr = get_ITBasicCallControl(&pITControl)) == S_OK )
{
// Different disconnects based on the call state
switch ( m_callState )
{
case CS_OFFERING: hr = pITControl->Disconnect( DC_REJECTED ); break;
case CS_INPROGRESS: hr = pITControl->Disconnect( DC_NOANSWER ); break;
// Before attempting to disconnect, make sure we haven't already done it
case CS_IDLE:
case CS_DISCONNECTED:
case CS_CONNECTED:
Lock();
if ( !m_bMustDisconnect )
{
Unlock();
break;
}
m_bMustDisconnect = false;
Unlock();
hr = pITControl->Disconnect( DC_NORMAL );
break;
case CS_HOLD:
case CS_QUEUED: hr = E_FAIL; break;
}
pITControl->Release();
}
// Force the disconnect
if ( FAILED(hr) )
{
ATLTRACE(_T(".error.CAVTapiCall::Disconnect(0x%08lx) -- requested on call that has no ITBasicCallControl.\n"), hr );
_ASSERT( false );
// Fake disconnect
put_bKillMe( TRUE );
put_callState( CS_DISCONNECTED );
// Log the call
CallLogType nType;
get_nCallLogType( &nType );
if ( nType != CL_CALL_CONFERENCE )
Log( nType );
// Now remove ourselves from the call list
CAVTapi *pAVTapi;
if ( SUCCEEDED(_Module.GetAVTapi(&pAVTapi)) )
{
long lCallID;
get_lCallID(&lCallID);
if ( lCallID )
{
pAVTapi->fire_CloseCallControl( lCallID );
pAVTapi->RemoveAVTapiCall( NULL );
}
(dynamic_cast<IUnknown *> (pAVTapi))->Release();
}
}
return hr;
}
STDMETHODIMP CAVTapiCall::NotifyConfRoomState(long *pErrorInfo)
{
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
// Notify the conference room of this update
IConfRoom *pConfRoom;
if ( SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
CALL_STATE nState;
get_callState( &nState );
// If the call has just connected, enumerate the participants
if ( nState == CS_CONNECTED )
{
Lock();
m_nCallLogType = CL_CALL_CONFERENCE;
Unlock();
EnumParticipants();
}
pConfRoom->NotifyStateChange( dynamic_cast<IAVTapiCall *> (this) );
pConfRoom->Release();
}
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_bstrDisplayableAddress(BSTR * pVal)
{
Lock();
HRESULT hr = SysReAllocString( pVal, m_bstrDisplayableAddress );
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_bstrDisplayableAddress(BSTR newVal)
{
Lock();
HRESULT hr = SysReAllocString( &m_bstrDisplayableAddress, newVal );
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_bstrOriginalAddress(BSTR *pVal)
{
Lock();
HRESULT hr = SysReAllocString( pVal, m_bstrOriginalAddress );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::put_bstrOriginalAddress(BSTR newVal)
{
Lock();
HRESULT hr = SysReAllocString( &m_bstrOriginalAddress, newVal );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_bstrName(BSTR * pVal)
{
Lock();
HRESULT hr = SysReAllocString( pVal, m_bstrName );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::put_bstrName(BSTR newVal)
{
Lock();
HRESULT hr = SysReAllocString( &m_bstrName, newVal );
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_bstrUser(short nIndex, BSTR * pVal)
{
// Validate parameters
_ASSERT( pVal );
_ASSERT( (nIndex >= 0) && (nIndex < NUM_USER_BSTR) );
if ( !pVal ) return E_POINTER;
if ( (nIndex < 0) || (nIndex >= NUM_USER_BSTR) )
return E_INVALIDARG;
Lock();
HRESULT hr = SysReAllocString( pVal, m_bstrUser[nIndex] );
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_bstrUser(short nIndex, BSTR newVal)
{
// Validate index
_ASSERT( (nIndex >= 0) && (nIndex < NUM_USER_BSTR) );
if ( (nIndex < 0) || (nIndex >= NUM_USER_BSTR) )
return E_INVALIDARG;
Lock();
HRESULT hr = SysReAllocString( &m_bstrUser[nIndex], newVal );
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::TerminalArrival(ITTerminal *pTerminal)
{
DWORD dwAddressType;
LONG lMediaType;
TERMINAL_DIRECTION nDir;
HRESULT hr = S_OK;
get_dwAddressType(&dwAddressType);
pTerminal->get_MediaType(&lMediaType);
pTerminal->get_Direction(&nDir);
ITCallInfo *pCallInfo;
hr = get_ITCallInfo(&pCallInfo);
if ( SUCCEEDED(hr) )
{
ITAddress *pAddress;
hr = get_ITAddress(&pAddress);
if ( SUCCEEDED(hr) )
{
ITStreamControl *pStreamControl;
hr = pCallInfo->QueryInterface( IID_ITStreamControl, (void **) &pStreamControl );
if ( SUCCEEDED(hr) )
{
// What media types does the address support
long lSupportedMediaTypes = 0;
ITMediaSupport *pMediaSupport;
if ( SUCCEEDED(pAddress->QueryInterface(IID_ITMediaSupport, (void **) &pMediaSupport)) )
{
pMediaSupport->get_MediaTypes( &lSupportedMediaTypes );
pMediaSupport->Release();
}
// Skip if the address doesn't support the media type
if ( lMediaType & lSupportedMediaTypes )
{
CAVTapi *pAVTapi;
if ( SUCCEEDED(_Module.GetAVTapi(&pAVTapi)) )
{
hr = pAVTapi->SelectTerminalOnStream(pStreamControl, lMediaType, nDir, pTerminal, this);
if ( SUCCEEDED(hr) )
{
// Do we need to allocate a preview window
if ( (lMediaType == TAPIMEDIATYPE_VIDEO) && (nDir == TD_CAPTURE) )
{
ITTerminalSupport *pTerminalSupport;
BSTR bstrTerminalClass = NULL;
LPOLESTR psz = NULL;
STRING_FROM_IID(CLSID_VideoWindowTerm, bstrTerminalClass);
hr = pAddress->QueryInterface(IID_ITTerminalSupport, (void **) &pTerminalSupport);
if ( SUCCEEDED(hr) )
{
ITTerminal *pPreviewTerminal = NULL;
hr = pTerminalSupport->CreateTerminal(bstrTerminalClass, TAPIMEDIATYPE_VIDEO, TD_RENDER, &pPreviewTerminal);
{
hr = pAVTapi->SelectTerminalOnStream( pStreamControl, TAPIMEDIATYPE_VIDEO, TD_CAPTURE, pPreviewTerminal, this );
pPreviewTerminal->Release();
}
}
if ( (dwAddressType & LINEADDRESSTYPE_SDP) != NULL )
{
IConfRoom *pConfRoom;
if ( SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
if (pConfRoom->IsConfRoomConnected() == S_OK)
pConfRoom->put_CallState(CS_CONNECTED);
pConfRoom->Release();
}
}
SysFreeString(bstrTerminalClass);
pTerminalSupport->Release();
}
}
}
}
pStreamControl->Release();
}
pAddress->Release();
}
pCallInfo->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::TerminalRemoval(ITTerminal *pTerminal)
{
DWORD dwAddressType;
LONG lMediaType;
TERMINAL_DIRECTION nDir;
HRESULT hr = S_OK;
get_dwAddressType(&dwAddressType);
pTerminal->get_MediaType(&lMediaType);
pTerminal->get_Direction(&nDir);
ITCallInfo *pCallInfo;
hr = get_ITCallInfo(&pCallInfo);
if ( SUCCEEDED(hr) )
{
ITAddress *pAddress;
hr = get_ITAddress(&pAddress);
if ( SUCCEEDED(hr) )
{
ITStreamControl *pStreamControl;
hr = pCallInfo->QueryInterface( IID_ITStreamControl, (void **) &pStreamControl );
if ( SUCCEEDED(hr) )
{
// What media types does the address support
long lSupportedMediaTypes = 0;
ITMediaSupport *pMediaSupport;
if ( SUCCEEDED(pAddress->QueryInterface(IID_ITMediaSupport, (void **) &pMediaSupport)) )
{
pMediaSupport->get_MediaTypes( &lSupportedMediaTypes );
pMediaSupport->Release();
}
// Skip if the address doesn't support the media type
if ( lMediaType & lSupportedMediaTypes )
{
CAVTapi *pAVTapi;
if ( SUCCEEDED(_Module.GetAVTapi(&pAVTapi)) )
{
hr = pAVTapi->UnselectTerminalOnStream(pStreamControl, lMediaType, nDir, pTerminal, this);
if ( SUCCEEDED(hr) )
{
// Do we need to remove a preview window
if ( (lMediaType == TAPIMEDIATYPE_VIDEO) && (nDir == TD_CAPTURE) )
{
ITTerminal *pPreviewTerminal = NULL;
hr = get_ITTerminalPreview( &pPreviewTerminal );
if ( SUCCEEDED(hr) )
{
BSTR bstrTerminalClass = NULL;
LPOLESTR psz = NULL;
STRING_FROM_IID(CLSID_VideoWindowTerm, bstrTerminalClass);
hr = pAVTapi->UnselectTerminalOnStream( pStreamControl, TAPIMEDIATYPE_VIDEO, TD_CAPTURE, pPreviewTerminal, this );
SysFreeString(bstrTerminalClass);
pPreviewTerminal->Release();
}
if ( (dwAddressType & LINEADDRESSTYPE_SDP) != NULL )
{
IConfRoom *pConfRoom;
if ( SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
if (pConfRoom->IsConfRoomConnected() == S_OK)
pConfRoom->put_CallState(CS_CONNECTED);
pConfRoom->Release();
}
}
}
}
ITTerminalSupport *pTerminalSupport;
hr = pAddress->QueryInterface(IID_ITTerminalSupport, (void **) &pTerminalSupport);
if ( SUCCEEDED(hr) )
{
ITTerminal *pDefaultTerminal = NULL;
hr = pTerminalSupport->GetDefaultStaticTerminal( lMediaType, nDir, &pDefaultTerminal );
if ( SUCCEEDED(hr) )
{
TerminalArrival(pDefaultTerminal);
pDefaultTerminal->Release();
}
pTerminalSupport->Release();
}
}
}
pStreamControl->Release();
}
pAddress->Release();
}
pCallInfo->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::get_bstrCallerID(BSTR * pVal)
{
Lock();
CComBSTR bstrRet( m_bstrName );
BSTR bstrAddr = (m_bstrDisplayableAddress) ? m_bstrDisplayableAddress : m_bstrOriginalAddress;
// Only add if the address is different then the name!
if ( bstrAddr && (SysStringLen(bstrAddr) > 0) && (!m_bstrName || wcscmp(m_bstrName, bstrAddr)) )
{
// Add new line if necessary
if ( bstrRet.Length() > 0 )
bstrRet.Append( L"\n" );
bstrRet.Append( bstrAddr );
}
// Do user variables...
for ( int i = 0; i < NUM_USER_BSTR; i++ )
{
if ( m_bstrUser[i] && (SysStringLen(m_bstrUser[i]) > 0) )
{
if ( bstrRet.Length() > 0 )
bstrRet.Append( L"\n" );
bstrRet.Append( m_bstrUser[i] );
}
}
Unlock();
// Use unknown if we have no caller ID
if ( !bstrRet.Length() )
{
USES_CONVERSION;
TCHAR szText[255];
LoadString( _Module.GetResourceInstance(), IDS_UNKNOWN, szText, ARRAYSIZE(szText) );
bstrRet = szText;
}
return SysReAllocString( pVal, bstrRet );
}
STDMETHODIMP CAVTapiCall::get_dwThreadID(DWORD * pVal)
{
Lock();
*pVal = m_dwThreadID;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_dwThreadID(DWORD newVal)
{
Lock();
m_dwThreadID = newVal;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::PostMessage(long msg, WPARAM wParam)
{
ATLTRACE(_T(".enter.CAVTapiCall::PostMesage(%ld, %ld).\n"), msg, wParam );
HRESULT hr = E_FAIL;
Lock();
// Always kill call with this instruction
if ( wParam == TI_DISCONNECT )
m_bKillMe = true;
// Do we have a thread running for this call?
if ( m_dwThreadID )
{
AddRef();
if ( PostThreadMessage(m_dwThreadID, (msg) ? msg : WM_THREADINSTRUCTION, wParam, (LPARAM) this) )
{
hr = S_OK;
}
else
{
Release();
hr = E_FAIL;
}
}
else if ( wParam == TI_DISCONNECT )
{
// No thread running, should we disconnect?
hr = Disconnect( TRUE );
}
Unlock();
ATLTRACE(_T(".exit.CAVTapiCall::PostMessage().\n"));
return hr;
}
////////////////////////////////////////////////////////////////////
// Message loop for dialing and answer threads
//
bool CAVTapiCall::WaitWithMessageLoop()
{
DWORD dwRet;
MSG msg;
bool bExit = false;
while( !bExit )
{
dwRet = MsgWaitForMultipleObjects(1, &_Module.m_hEventThreadWakeUp, FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == WAIT_OBJECT_0)
return true; // The event was signaled
if (dwRet != WAIT_OBJECT_0 + 1)
break; // Something else happened
// There is one or more window message available. Dispatch them
while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
{
CErrorInfo er;
er.set_Operation( IDS_ER_THREAD_MSG_PROCESS );
IAVTapiCall *pAVCall = (IAVTapiCall *) msg.lParam;
bool bRelease = true;
switch ( msg.message )
{
case WM_THREADINSTRUCTION:
switch( msg.wParam )
{
// Terminate thread
case TI_QUIT:
bExit = true;
break;
// Disconnect call
case TI_REJECT:
case TI_DISCONNECT:
er.set_Details( IDS_ER_CALL_DISCONNECT );
er.set_hr( pAVCall->Disconnect( TRUE ) );
break;
// Enter the conference room
case TI_NOTIFYCONFROOMSTATE:
er.set_Details( IDS_ER_CALL_ENTERCONFROOM );
er.set_hr( pAVCall->NotifyConfRoomState((long *) &er) );
break;
// Set QOS on conference room participants
case TI_REQUEST_QOS:
{
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
IConfRoom *pConfRoom;
if ( SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
pConfRoom->SetQOSOnParticipants();
pConfRoom->Release();
}
}
}
break;
// Recieving user to user information
case TI_USERUSERINFO:
pAVCall->HandleUserUserInfo();
break;
case TI_STREAM_ACTIVE:
pAVCall->put_StreamActive( true );
break;
case TI_STREAM_INACTIVE:
pAVCall->put_StreamActive( false );
break;
case TI_RCV_VIDEO_ACTIVE:
pAVCall->put_RcvVideoStreaming( true );
break;
case TI_RCV_VIDEO_INACTIVE:
pAVCall->put_RcvVideoStreaming( false );
break;
}
break;
// Call state changed
case WM_CALLSTATE:
if ( msg.wParam )
{
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
long lCallID;
pAVCall->get_lCallID( &lCallID );
pAVTapi->fire_SetCallState( lCallID, (ITCallStateEvent *) msg.wParam, pAVCall );
}
((ITCallStateEvent *) msg.wParam)->Release();
}
break;
// Participant being added to list of participants
case WM_ADDPARTICIPANT:
if ( msg.wParam )
{
ITParticipant *p = (ITParticipant *) msg.wParam;
pAVCall->AddParticipant( p );
pAVCall->NotifyParticipantChangeConfRoom( p, AV_PARTICIPANT_JOIN );
p->Release();
}
break;
// Participant being removed from the list of participants
case WM_REMOVEPARTICIPANT:
if ( msg.wParam )
{
ITParticipant *p = (ITParticipant *) msg.wParam;
pAVCall->RemoveParticipant( p );
pAVCall->NotifyParticipantChangeConfRoom( p, AV_PARTICIPANT_LEAVE );
p->Release();
}
break;
// Participant's information changing
case WM_UPDATEPARTICIPANT:
if ( msg.wParam )
{
ITParticipant *p = (ITParticipant *) msg.wParam;
pAVCall->UpdateParticipant( p );
pAVCall->NotifyParticipantChangeConfRoom( p, AV_PARTICIPANT_UPDATE );
p->Release();
}
break;
/////////////////////////////////////////////////////////////
// Participant being mapped or unmapped from conference
case WM_STREAM_EVENT:
if ( msg.wParam )
{
ATLTRACE(_T(".1.CAVTapiCall::WaitWithMessageLoop() -- WM_STREAM_EVENT.\n"));
CComPtr<IAVTapi> pAVTapi;
ITParticipantEvent *pParticipantEvent = (ITParticipantEvent *) msg.wParam;
PARTICIPANT_EVENT nEvent;
ITSubStream *pITSubStream;
if ( SUCCEEDED(pParticipantEvent->get_Event(&nEvent)) &&
SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) &&
SUCCEEDED(pParticipantEvent->get_SubStream(&pITSubStream)) )
{
IConfRoom *pConfRoom;
if (SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
IVideoFeed *pFeed;
if ( SUCCEEDED(pConfRoom->FindVideoFeedFromSubStream(pITSubStream, &pFeed)) )
{
ITParticipant *pParticipant;
if ( SUCCEEDED(pParticipantEvent->get_Participant(&pParticipant)) )
{
pFeed->put_ITParticipant( (nEvent == PE_SUBSTREAM_MAPPED) ? pParticipant : NULL );
pAVCall->OnStreamingChanged( pFeed, (bool) (nEvent == PE_SUBSTREAM_MAPPED) );
pParticipant->Release();
}
pFeed->Release();
}
pConfRoom->Release();
}
pITSubStream->Release();
}
pParticipantEvent->Release();
}
break;
// Terminal is streaming video
case WM_CME_STREAMSTART:
if ( msg.wParam )
{
pAVCall->OnStreamingChanged( (IVideoFeed *) msg.wParam, true );
((IVideoFeed *) msg.wParam)->Release();
}
break;
// Terminal has stopped streaming video
case WM_CME_STREAMSTOP:
if ( msg.wParam )
{
pAVCall->OnStreamingChanged( (IVideoFeed *) msg.wParam, false );
((IVideoFeed *) msg.wParam)->Release();
}
break;
default:
// Normal dispatch
TranslateMessage(&msg);
DispatchMessage(&msg);
bRelease = false;
break;
}
// Release the AVTapiCall interface
if ( bRelease && pAVCall ) pAVCall->Release();
// Anything signaled?
if (WaitForSingleObject(_Module.m_hEventThreadWakeUp, 0) == WAIT_OBJECT_0)
return true; // Event is now signaled.
}
}
return false;
}
STDMETHODIMP CAVTapiCall::get_IVideoWindow(short nInd, IDispatch **ppVal )
{
return GetTerminalInterface( IID_IVideoWindow, TAPIMEDIATYPE_VIDEO, TD_RENDER, (void **) ppVal, nInd );
}
STDMETHODIMP CAVTapiCall::get_ITBasicAudioTerminal(ITBasicAudioTerminal **ppVal)
{
return GetTerminalInterface( IID_ITBasicAudioTerminal, TAPIMEDIATYPE_AUDIO, TD_CAPTURE, (void **) ppVal, 0 );
}
HRESULT CAVTapiCall::GetTerminalInterface( REFIID riid, long nMediaType, TERMINAL_DIRECTION nTD, void **ppVoid, short nInd )
{
USES_CONVERSION;
_ASSERT( ppVoid );
*ppVoid = NULL;
HRESULT hr = E_FAIL;
long nType;
bool bBreak = false;
// $CRIT - enter
m_critTerminals.Lock();
TERMINALLIST::iterator i, iEnd = m_lstTerminals.end();
for ( i = m_lstTerminals.begin(); i != iEnd; i++ )
{
TERMINAL_DIRECTION nCurTD;
if ( SUCCEEDED(hr = (*i)->get_Direction(&nCurTD)) && (nCurTD == nTD) &&
SUCCEEDED(hr = (*i)->get_MediaType(&nType)) && (nType == nMediaType) )
{
if ( !nInd )
{
hr = (*i)->QueryInterface( riid, ppVoid );
bBreak = true;
}
else
{
nInd--;
}
}
// Found a video window...
if ( bBreak ) break;
// Prepare for next loop
hr = E_NOINTERFACE;
}
// $CRIT - exit
m_critTerminals.Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_dwCaps(DWORD * pVal)
{
*pVal = 0;
// Check audio capabilities for call
ITBasicAudioTerminal *pBasicAudio;
if ( SUCCEEDED(get_ITBasicAudioTerminal(&pBasicAudio)) )
{
*pVal += CALL_CAPS_FULLDUPLEX_AUDIO;
pBasicAudio->Release();
}
// Check video capture capabilities for call
ITTerminal *pITTerminal;
TERMINAL_STATE nState;
if ( SUCCEEDED(GetTerminalInterface(IID_ITTerminal, TAPIMEDIATYPE_VIDEO, TD_CAPTURE, (void **) &pITTerminal, 0 )) )
{
if ( SUCCEEDED(pITTerminal->get_State(&nState)) && (nState == TS_INUSE) )
*pVal += CALL_CAPS_VIDEO_CAPTURE;
pITTerminal->Release();
}
// Check video render capabilities for call
if ( SUCCEEDED(GetTerminalInterface(IID_ITTerminal, TAPIMEDIATYPE_VIDEO, TD_RENDER, (void **) &pITTerminal, 0 )) )
{
if ( SUCCEEDED(pITTerminal->get_State(&nState)) && (nState == TS_INUSE) )
*pVal += CALL_CAPS_VIDEO_RENDER;
pITTerminal->Release();
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::Log( CallLogType nType )
{
CComPtr<IAVTapi> pAVTapi;
if ( FAILED(_Module.get_AVTapi(&pAVTapi)) ) return E_PENDING;
DATE dateEnd;
SYSTEMTIME st;
GetLocalTime( &st );
SystemTimeToVariantTime( &st, &dateEnd );
HRESULT hr = E_ABORT;
Lock();
if ( !m_bCallLogged )
{
// Request that the app log the call
hr = pAVTapi->fire_LogCall( m_lCallID, m_nCallLogType, m_dateStart, dateEnd, m_bstrOriginalAddress, m_bstrName );
m_bCallLogged = true;
}
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::ResolveAddress()
{
HRESULT hr = E_ACCESSDENIED;
CComPtr<IAVGeneralNotification> pAVGen;
Lock();
// We don't resolve conference names!
if ( !m_bResolvedAddress && (m_dwAddressType != LINEADDRESSTYPE_SDP) )
{
BSTR bstrName = NULL;
BSTR bstrUser1 = NULL;
BSTR bstrUser2 = NULL;
if ( !m_bResolvedAddress && SUCCEEDED(hr = _Module.get_AVGenNot(&pAVGen)) )
{
if ( SUCCEEDED(hr = pAVGen->fire_ResolveAddress(m_bstrOriginalAddress, &bstrName, &bstrUser1, &bstrUser2)) )
m_bResolvedAddress = true;
if ( bstrName && (SysStringLen(bstrName) > 0) )
SysReAllocString( &m_bstrName, bstrName );
if ( bstrUser1 && (SysStringLen(bstrUser1) > 0) )
SysReAllocString( &m_bstrUser[0], bstrUser1 );
if ( bstrUser2 && (SysStringLen(bstrUser2) > 0) )
SysReAllocString( &m_bstrUser[1], bstrUser2 );
}
// Clean-up
SysFreeString( bstrName );
SysFreeString( bstrUser1 );
SysFreeString( bstrUser2 );
}
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::PopulateTreeView( IConfRoomTreeView *pTreeView )
{
_ASSERT( pTreeView );
if ( !pTreeView ) return E_POINTER;
CComPtr<IAVGeneralNotification> pAVGen;
if ( FAILED(_Module.get_AVGenNot(&pAVGen)) )
return E_UNEXPECTED;
USES_CONVERSION;
HWND hWnd;
TCHAR szText[255];
pTreeView->get_hWnd( &hWnd );
if ( IsWindow(hWnd) )
{
// Populate list
SendMessage( hWnd, WM_SETREDRAW, FALSE, 0 );
// Add Me
LoadString( _Module.GetResourceInstance(), IDS_CONFROOM_ME, szText, ARRAYSIZE(szText) );
BSTR bstrTemp = NULL;
bstrTemp = SysAllocString( T2COLE(szText) );
pAVGen->fire_UpdateConfParticipant( UPDATE_ADD, NULL, bstrTemp );
SysFreeString( bstrTemp );
// Walk list adding participants
m_atomList.Lock( CAtomicList::LIST_READ );
PARTICIPANTLIST::iterator i, iEnd = m_lstParticipants.end();
for ( i = m_lstParticipants.begin(); i != iEnd; i++ )
{
BSTR bstrTemp = NULL;
(*i)->get_bstrDisplayName( CParticipant::NAMESTYLE_PARTICIPANT, &bstrTemp );
ATLTRACE(_T("CAVTapiCall::PopulateTreeView() Added Participant %s\n"),OLE2CT(bstrTemp));
pAVGen->fire_UpdateConfParticipant( UPDATE_ADD, *i, bstrTemp );
SysFreeString(bstrTemp);
}
m_atomList.Unlock( CAtomicList::LIST_READ );
SendMessage( hWnd, WM_SETREDRAW, true, 0 );
InvalidateRect( hWnd, NULL, true );
// Insure that tree view has something selected!
IConfRoom *pConfRoom;
if ( SUCCEEDED(pTreeView->get_ConfRoom(&pConfRoom)) )
{
ITParticipant *pParticipant = NULL;
pConfRoom->get_TalkerParticipant( &pParticipant );
pConfRoom->SelectTalker( pParticipant, true );
RELEASE( pParticipant );
pConfRoom->Release();
}
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// ForceCallerIDUpdate
//
// Forces an update of the caller ID on the slide window. Uses the CAVTapi::fire_SetCallerID
// method to force the update
//
STDMETHODIMP CAVTapiCall::ForceCallerIDUpdate()
{
HRESULT hr;
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(hr = _Module.get_AVTapi(&pAVTapi)) )
{
BSTR bstrCallerID = NULL;
long lCallID;
get_bstrCallerID( &bstrCallerID );
get_lCallID( &lCallID );
hr = pAVTapi->fire_SetCallerID( lCallID, bstrCallerID );
SysFreeString( bstrCallerID );
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::NotifyStreamEvent(CALL_MEDIA_EVENT cme)
{
return S_OK;
}
STDMETHODIMP CAVTapiCall::GetVideoFeedCount(short * pnCount)
{
if ( !pnCount ) return E_POINTER;
*pnCount = 0;
// Figure out how many video terminals we need to add
IVideoWindow *pVideo = NULL;
while ( get_IVideoWindow(*pnCount, (IDispatch **) &pVideo) == S_OK )
{
pVideo->Release();
(*pnCount)++;
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::get_bResolved(VARIANT_BOOL * pVal)
{
Lock();
*pVal = m_bResolvedAddress;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_bResolved(VARIANT_BOOL newVal)
{
Lock();
m_bResolvedAddress = (bool) (newVal != 0);
Unlock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Participant functions
//
STDMETHODIMP CAVTapiCall::AddParticipant(ITParticipant * pParticipant)
{
ATLTRACE(_T(".enter.CAVTapiCall::AddParticipant(%p).\n"), pParticipant );
_ASSERT( pParticipant );
if ( !pParticipant ) return E_POINTER;
// First see if the partipant exists
m_atomList.Lock( CAtomicList::LIST_WRITE );
IParticipant *pFind;
if ( SUCCEEDED(FindParticipant(pParticipant, &pFind)) )
{
pFind->Release();
m_atomList.Unlock( CAtomicList::LIST_WRITE );
return S_OK;
}
// Didn't find it, add to the list
IParticipant *pNew = new CComObject<CParticipant>;
if ( pNew )
{
pNew->AddRef();
pNew->put_ITParticipant( pParticipant );
m_lstParticipants.push_back( pNew );
}
m_atomList.Unlock( CAtomicList::LIST_WRITE );
// Notify of adding the participant to the tree view
CComPtr<IAVGeneralNotification> pAVGen;
if ( pNew && SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
{
#ifdef _DEBUG
pNew->AddRef();
ATLTRACE(_T(".1.CAVTapiCall::AddParticipant() refcount - %p @ %ld.\n"), pNew, pNew->Release() );
#endif
BSTR bstrName = NULL;
pNew->get_bstrDisplayName( CParticipant::NAMESTYLE_PARTICIPANT, &bstrName );
pAVGen->fire_UpdateConfParticipant( UPDATE_ADD, pNew, bstrName );
SysFreeString( bstrName );
}
return (pNew) ? S_OK : E_OUTOFMEMORY;
}
STDMETHODIMP CAVTapiCall::RemoveParticipant(ITParticipant * pParticipant)
{
ATLTRACE(_T(".enter.CAVTapiCall::RemoveParticipant(%p).\n"), pParticipant );
HRESULT hr = E_FAIL;
m_atomList.Lock( CAtomicList::LIST_WRITE );
PARTICIPANTLIST::iterator i, iEnd = m_lstParticipants.end();
for ( i = m_lstParticipants.begin(); i != iEnd; i++ )
{
ITParticipant *pMyParticipant;
if ( SUCCEEDED((*i)->get_ITParticipant(&pMyParticipant)) )
{
if ( pMyParticipant == pParticipant )
{
#ifdef _DEBUG
(*i)->AddRef();
ATLTRACE(_T(".1.CAVTapiCall::RemoveParticipant() refcount - %p @ %ld.\n"), (*i), (*i)->Release() );
#endif
// Notify of removing the participant from the tree view
CComPtr<IAVGeneralNotification> pAVGen;
if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
pAVGen->fire_UpdateConfParticipant( UPDATE_REMOVE, (*i), NULL );
// Release from list
(*i)->Release();
m_lstParticipants.erase( i );
hr = S_OK;
}
pMyParticipant->Release();
if ( SUCCEEDED(hr) ) break;
}
}
m_atomList.Unlock( CAtomicList::LIST_WRITE );
return hr;
}
STDMETHODIMP CAVTapiCall::UpdateParticipant(ITParticipant * pITParticipant)
{
HRESULT hr = E_FAIL;
IParticipant *p;
if ( SUCCEEDED(FindParticipant(pITParticipant, &p)) )
{
CComPtr<IAVGeneralNotification> pAVGen;
if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
{
#ifdef _DEBUG
p->AddRef();
ATLTRACE(_T(".1.CAVTapiCall::RemoveParticipant() refcount - %p @ %ld.\n"), p, p->Release() );
#endif
BSTR bstrName = NULL;
p->get_bstrDisplayName( CParticipant::NAMESTYLE_PARTICIPANT, &bstrName );
hr = pAVGen->fire_UpdateConfParticipant( UPDATE_MODIFY, p, bstrName );
SysFreeString( bstrName );
}
p->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::EnumParticipants()
{
ATLTRACE(_T(".enter.CAVTapiCall::EnumParticipants().\n") );
HRESULT hr;
ITParticipantControl *pITParticipantControl;
if ( SUCCEEDED(hr = get_ITParticipantControl(&pITParticipantControl)) )
{
IEnumParticipant *pEnum;
if ( SUCCEEDED(pITParticipantControl->EnumerateParticipants(&pEnum)) )
{
// Clear out the list of participants for now
m_atomList.Lock( CAtomicList::LIST_WRITE );
RELEASE_LIST( m_lstParticipants );
ITParticipant *pParticipant = NULL;
while ( (pEnum->Next(1, &pParticipant, NULL) == S_OK) && pParticipant )
{
IParticipant *pNew = new CComObject<CParticipant>;
if ( pNew )
{
ATLTRACE(_T(".1.CAVTapiCall::EnumParticipants() -- adding participant %p.\n"), pParticipant );
// Add the participant to the list
pNew->AddRef();
pNew->put_ITParticipant( pParticipant );
m_lstParticipants.push_back( pNew );
}
RELEASE( pParticipant );
}
pEnum->Release();
m_atomList.Unlock( CAtomicList::LIST_WRITE );
}
// Clean up
pITParticipantControl->Release();
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::IsMyParticipant(ITParticipant * pParticipant)
{
HRESULT hr = S_FALSE;
IParticipant *p;
if ( SUCCEEDED(FindParticipant(pParticipant, &p)) )
{
hr = S_OK;
p->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::IsSameCallHub(ITCallHub * pCallHub)
{
HRESULT hr = S_FALSE;
ITCallHub *pMyCallHub;
if ( SUCCEEDED(get_ITCallHub(&pMyCallHub)) )
{
if ( pMyCallHub == pCallHub )
hr = S_OK;
pMyCallHub->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::NotifyParticipantChangeConfRoom(ITParticipant * pParticipant, AV_PARTICIPANT_EVENT nEvent )
{
#ifdef _DEBUG
if ( pParticipant )
{
pParticipant->AddRef();
ATLTRACE(_T(".1.NotifyParticipantChangConfRoom() -- ref count %p @ %ld.\n"), pParticipant, pParticipant->Release() );
}
#endif
// Notify conference room so that it can re-layout the windows
DWORD dwAddressType;
get_dwAddressType( &dwAddressType );
if ( dwAddressType == LINEADDRESSTYPE_SDP )
{
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
IConfRoom *pConfRoom;
if ( SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
// Notify the conference room of the change to the participant
pConfRoom->NotifyParticipantChange( dynamic_cast<IAVTapiCall *> (this), pParticipant, nEvent );
pConfRoom->Release();
}
}
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::GetDisplayNameForParticipant(ITParticipant * pParticipant, BSTR *pbstrName )
{
HRESULT hr = E_FAIL;
*pbstrName = NULL;
// Look for a IParticipant that matches
IParticipant *p;
if ( SUCCEEDED(FindParticipant(pParticipant, &p)) )
{
hr = p->get_bstrDisplayName( CParticipant::NAMESTYLE_PARTICIPANT, pbstrName );
p->Release();
}
if ( FAILED(hr) )
{
ATLTRACE(_T(".warning.CAVTapiCall::GetDisplayNameForParticipant() failed to find participant.\n"));
// Use default name...
USES_CONVERSION;
TCHAR szText[255];
//
// We have to initialize szText
//
_tcscpy( szText, _T(""));
LoadString( _Module.GetResourceInstance(), IDS_PARTICIPANT, szText, ARRAYSIZE(szText) );
*pbstrName = SysAllocString( T2COLE(szText) );
}
return hr;
}
STDMETHODIMP CAVTapiCall::UpdateCallerIDFromParticipant()
{
// Update caller ID based on participant information we have
HRESULT hr = S_FALSE;
Lock();
if ( !m_bstrName || !SysStringLen(m_bstrName) )
{
SysFreeString( m_bstrName );
m_bstrName = NULL;
// Fetch information on first participant in the list
m_atomList.Lock( CAtomicList::LIST_READ );
if ( !m_lstParticipants.empty() )
{
(*m_lstParticipants.begin())->get_bstrDisplayName( CParticipant::NAMESTYLE_NULL, &m_bstrName );
// Should we update the caller ID for the object?
if ( m_bstrName )
hr = S_OK;
}
m_atomList.Unlock( CAtomicList::LIST_READ );
}
Unlock();
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Streaming code
//
STDMETHODIMP CAVTapiCall::OnStreamingChanged(IVideoFeed * pFeed, VARIANT_BOOL bStreaming)
{
// Notify that the partcipant has either started or stopped streaming
ITParticipant *pParticipant;
if ( SUCCEEDED(pFeed->get_ITParticipant(&pParticipant)) )
{
NotifyParticipantChangeConfRoom( pParticipant, (bStreaming) ? AV_PARTICIPANT_STREAMING_START : AV_PARTICIPANT_STREAMING_STOP );
pParticipant->Release();
}
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_StreamActive(VARIANT_BOOL bActive )
{
USES_CONVERSION;
HRESULT hr = E_FAIL;
// Notify the application of the streaming event.
Lock();
m_bPreviewStreaming = (bool) (bActive != 0);
Unlock();
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
{
// Force conference room to be re-layed out
DWORD dwAddressType;
get_dwAddressType( &dwAddressType );
if ( dwAddressType == LINEADDRESSTYPE_SDP )
{
IConfRoom *pConfRoom;
if ( SUCCEEDED(pAVTapi->get_ConfRoom(&pConfRoom)) )
{
pConfRoom->Layout( true, true );
pConfRoom->Release();
// Notify that we need to update the conference me participant
CComPtr<IAVGeneralNotification> pAVGen;
if ( SUCCEEDED(_Module.get_AVGenNot(&pAVGen)) )
{
TCHAR szText[255];
LoadString( _Module.GetResourceInstance(), IDS_CONFROOM_ME, szText, ARRAYSIZE(szText) );
BSTR bstrTemp = NULL;
bstrTemp = SysAllocString( T2COLE(szText) );
pAVGen->fire_UpdateConfParticipant( UPDATE_MODIFY, NULL, bstrTemp );
SysFreeString( bstrTemp );
}
}
}
long lCallID;
get_lCallID( &lCallID );
hr = pAVTapi->fire_AddCurrentAction( lCallID, (bActive) ? CM_ACTIONS_NOTIFY_PREVIEW_START : CM_ACTIONS_NOTIFY_PREVIEW_STOP, NULL );
}
return hr;
}
STDMETHODIMP CAVTapiCall::put_RcvVideoStreaming(VARIANT_BOOL bActive)
{
HRESULT hr = E_FAIL;
// Notify the application of the streaming event.
Lock();
m_bRcvVideoStreaming = (bool) (bActive != 0);
Unlock();
long lCallID;
get_lCallID( &lCallID );
CComPtr<IAVTapi> pAVTapi;
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
hr = pAVTapi->fire_AddCurrentAction( lCallID, (bActive) ? CM_ACTIONS_NOTIFY_STREAMSTART : CM_ACTIONS_NOTIFY_STREAMSTOP, NULL );
return hr;
}
STDMETHODIMP CAVTapiCall::IsPreviewStreaming()
{
HRESULT hr = S_FALSE;
IVideoWindow *pVideo;
if ( SUCCEEDED(get_IVideoWindowPreview((IDispatch **) &pVideo)) )
{
Lock();
if ( m_bPreviewStreaming ) hr = S_OK;
Unlock();
pVideo->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::IsRcvVideoStreaming()
{
Lock();
HRESULT hr = (m_bRcvVideoStreaming) ? S_OK : S_FALSE;
Unlock();
return hr;
}
STDMETHODIMP CAVTapiCall::get_RcvVideoStreaming(VARIANT_BOOL * pVal)
{
Lock();
*pVal = m_bRcvVideoStreaming;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::GetCallerIDInfo(ITCallInfo * pCallInfo)
{
BSTR bstrTemp = NULL, bstrTemp2 = NULL;
// Name
pCallInfo->get_CallInfoString( CIS_CALLERIDNAME, &bstrTemp );
if ( bstrTemp && SysStringLen(bstrTemp) )
put_bstrName( bstrTemp );
SysFreeString( bstrTemp );
bstrTemp = NULL;
// Number
pCallInfo->get_CallInfoString( CIS_CALLERIDNUMBER, &bstrTemp );
if ( bstrTemp && SysStringLen(bstrTemp) )
put_bstrDisplayableAddress( bstrTemp );
SysFreeString( bstrTemp );
bstrTemp = NULL;
// Redirecting
// $FIXUP ... should add these as well
ForceCallerIDUpdate();
return S_OK;
}
STDMETHODIMP CAVTapiCall::HandleUserUserInfo()
{
HRESULT hr;
ITCallInfo *pCallInfo;
if ( SUCCEEDED(hr = get_ITCallInfo(&pCallInfo)) )
{
long nSize = 0;
void *pbUU;
hr = pCallInfo->GetCallInfoBuffer( CIB_USERUSERINFO, (DWORD*)&nSize, (BYTE**)&pbUU );
if ( SUCCEEDED(hr) )
{
ATLTRACE(_T(".1.CAVTapiCall::HandleUserUserInfo() -- recieved data.\n"));
long lCallID;
get_lCallID( &lCallID );
CComPtr<IAVTapi> pAVTapi;
if ( FAILED(_Module.get_AVTapi(&pAVTapi)) ||
FAILED(pAVTapi->fire_NotifyUserUserInfo(lCallID, (ULONG_PTR) pbUU)) )
{
ATLTRACE(_T(".error.CAVTapiCall::HandleUserUserInfo() -- failed to notify client.\n"));
CoTaskMemFree( pbUU );
}
}
pCallInfo->Release();
}
return hr;
}
STDMETHODIMP CAVTapiCall::get_nCallType(AVCallType * pVal)
{
Lock();
*pVal = m_nCallType;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::put_nCallType(AVCallType newVal)
{
_ASSERT( (newVal >= 0) && (newVal < AV_CALLTYPE_MAX) );
Lock();
m_nCallType = (AVCallType) newVal;
Unlock();
return S_OK;
}
STDMETHODIMP CAVTapiCall::FindParticipant(ITParticipant * pParticipant, IParticipant * * ppFound)
{
_ASSERT( ppFound );
*ppFound = NULL;
m_atomList.Lock( CAtomicList::LIST_READ );
PARTICIPANTLIST::iterator i, iEnd = m_lstParticipants.end();
for ( i = m_lstParticipants.begin(); i != iEnd; i++ )
{
ITParticipant *pMyParticipant;
if ( SUCCEEDED((*i)->get_ITParticipant(&pMyParticipant)) )
{
if ( pMyParticipant == pParticipant )
{
*ppFound = (*i);
(*ppFound)->AddRef();
}
pMyParticipant->Release();
if ( *ppFound ) break;
}
}
m_atomList.Unlock( CAtomicList::LIST_READ );
return (*ppFound) ? S_OK : E_FAIL;
}