/*++ Copyright (c) 1998-1999 Microsoft Corporation Module Name: phonemsp.cpp Abstract: Implements an MSP object for addresses that have phone terminals this makes the MSP abstraction in the address object much easier, since there will be no special cases for phone devices/terminals Author: mquinton - 9/24/98 Notes: Revision History: --*/ #include "stdafx.h" //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::Initialize // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::Initialize( MSP_HANDLE hEvent ) { HRESULT hr = S_OK; LOG((TL_TRACE, "Initialize - enter")); Lock(); m_hEvent = (HANDLE)hEvent; #if DBG m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif Unlock(); LOG((TL_TRACE, "Initialize - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::Shutdown // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::Shutdown() { HRESULT hr = E_NOTIMPL; LOG((TL_TRACE, "Shutdown - enter")); LOG((TL_TRACE, "Shutdown - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::CreateMSPCall // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::CreateMSPCall( MSP_HANDLE hCall, DWORD dwReserved, DWORD dwMediaType, IUnknown * pOuterUnknown, IUnknown ** ppStreamControl ) { HRESULT hr; CComAggObject * pPhoneMSPCall; ITPhoneMSPCallPrivate * pPhoneMSPCallPrivate; LOG((TL_TRACE, "CreateMSPCall - enter")); pPhoneMSPCall = new CComAggObject(pOuterUnknown); if ( NULL == pPhoneMSPCall ) { } // // save the aggregated interface in // the msppointer // pPhoneMSPCall->QueryInterface( IID_IUnknown, (void **)ppStreamControl ); // // get to the real object // hr = (*ppStreamControl)->QueryInterface( IID_ITPhoneMSPCallPrivate, (void **)&pPhoneMSPCallPrivate ); // // initialize it // hr = pPhoneMSPCallPrivate->Initialize( this ); Lock(); AddCall( *ppStreamControl ); Unlock(); pPhoneMSPCallPrivate->Release(); LOG((TL_TRACE, "CreateMSPCall - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::ShutdownMSPCall // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::ShutdownMSPCall( IUnknown * pStreamControl ) { HRESULT hr = S_OK; LOG((TL_TRACE, "ShutdownMSPCall - enter")); Lock(); RemoveCall( pStreamControl ); Unlock(); LOG((TL_TRACE, "ShutdownMSPCall - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::ReceiveTSPData // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::ReceiveTSPData( IUnknown * pMSPCall, BYTE * pBuffer, DWORD dwSize ) { HRESULT hr = S_OK; DWORD dwCommand; ITPhoneMSPCallPrivate * pCall; LOG((TL_TRACE, "ReceiveTSPData - enter")); if ( NULL == pMSPCall ) { LOG((TL_ERROR, "ReceiveTSPData - null call")); return E_INVALIDARG; } dwCommand = *((LPDWORD)(pBuffer)); hr = pMSPCall->QueryInterface( IID_ITPhoneMSPCallPrivate, (void**)&pCall ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "ReceiveTSPData - bad call")); return E_FAIL; } LOG((TL_INFO, "ReceiveTSPData - command %d", dwCommand)); switch (dwCommand) { case 1: // Start Streaming hr = pCall->OnConnect(); break; case 2: // Stop Streaming hr = pCall->OnDisconnect(); break; default: LOG((TL_ERROR, "ReceiveTSPData - invalid command ")); hr = E_FAIL; break; } pCall->Release(); LOG((TL_TRACE, "ReceiveTSPData - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::GetEvent // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::GetEvent( DWORD * pdwSize, byte * pEventBuffer ) { HRESULT hr = E_NOTIMPL; LOG((TL_TRACE, "GetEvent - enter")); LOG((TL_TRACE, "GetEvent - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CPhoneMSP::InitializeTerminals( HPHONEAPP hPhoneApp, DWORD dwAPIVersion, DWORD dwPhoneDevice, CAddress * pAddress ) { LPPHONECAPS pPhoneCaps = NULL; HRESULT hr; BOOL bSucceeded = FALSE; ITStream * pStream; LOG((TL_TRACE, "InitializeTerminals - enter")); // // get the phone caps // hr = PhoneGetDevCapsWithAlloc( hPhoneApp, dwPhoneDevice, dwAPIVersion, &pPhoneCaps ); if (S_OK != hr) { if (NULL != pPhoneCaps) { ClientFree( pPhoneCaps ); } LOG((TL_ERROR, "CreatePhoneTerminals - PhoneGetDevCaps failed - %lx", hr )); return hr; } // // check the hook switch devs // if (0 == pPhoneCaps->dwHookSwitchDevs) { LOG((TL_ERROR, "CreatePhoneTerminal - no hook switch devs!" )); ClientFree( pPhoneCaps ); return E_UNEXPECTED; } // // create terminal devices for each hook switch dev // need to create an audio in and audio out terminal // for each // ITTerminal * pTerminal; if (pPhoneCaps->dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HANDSET) { hr = CTerminal::Create( hPhoneApp, dwPhoneDevice, pPhoneCaps, PHONEHOOKSWITCHDEV_HANDSET, TD_RENDER, dwAPIVersion, &pTerminal ); if (SUCCEEDED(hr)) { bSucceeded = TRUE; AddTerminal( pTerminal ); pTerminal->Release(); } hr = CTerminal::Create( hPhoneApp, dwPhoneDevice, pPhoneCaps, PHONEHOOKSWITCHDEV_HANDSET, TD_CAPTURE, dwAPIVersion, &pTerminal ); if (SUCCEEDED(hr)) { bSucceeded = TRUE; AddTerminal( pTerminal ); pTerminal->Release(); } } if (pPhoneCaps->dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HEADSET) { hr = CTerminal::Create( hPhoneApp, dwPhoneDevice, pPhoneCaps, PHONEHOOKSWITCHDEV_HEADSET, TD_RENDER, dwAPIVersion, &pTerminal ); if (SUCCEEDED(hr)) { bSucceeded = TRUE; AddTerminal( pTerminal ); pTerminal->Release(); } hr = CTerminal::Create( hPhoneApp, dwPhoneDevice, pPhoneCaps, PHONEHOOKSWITCHDEV_HEADSET, TD_CAPTURE, dwAPIVersion, &pTerminal ); if (SUCCEEDED(hr)) { bSucceeded = TRUE; AddTerminal( pTerminal ); pTerminal->Release(); } } if (pPhoneCaps->dwHookSwitchDevs & PHONEHOOKSWITCHDEV_SPEAKER) { hr = CTerminal::Create( hPhoneApp, dwPhoneDevice, pPhoneCaps, PHONEHOOKSWITCHDEV_SPEAKER, TD_RENDER, dwAPIVersion, &pTerminal ); if (SUCCEEDED(hr)) { bSucceeded = TRUE; AddTerminal( pTerminal ); pTerminal->Release(); } hr = CTerminal::Create( hPhoneApp, dwPhoneDevice, pPhoneCaps, PHONEHOOKSWITCHDEV_SPEAKER, TD_CAPTURE, dwAPIVersion, &pTerminal ); if (SUCCEEDED(hr)) { bSucceeded = TRUE; AddTerminal( pTerminal ); pTerminal->Release(); } } // // free memory // if (NULL != pPhoneCaps) { ClientFree( pPhoneCaps ); } if ( !bSucceeded ) { LOG((TL_WARN, "No phone terminals created")); return E_FAIL; } LOG((TL_TRACE, "InitializeTerminals - exit")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CPhoneMSP::VerifyTerminal( ITTerminal * pTerminal ) { int iReturn; Lock(); iReturn = m_TerminalArray.Find( pTerminal ); Unlock(); if ( -1 == iReturn ) { return TAPI_E_INVALIDTERMINAL; } return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSP::AddTerminal( ITTerminal * pTerminal ) { Lock(); m_TerminalArray.Add( pTerminal ); Unlock(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // called in lock // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSP::AddCall( IUnknown * pCall ) { m_CallArray.Add( pCall ); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // called in lock // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSP::RemoveCall( IUnknown * pCall ) { m_CallArray.Remove( pCall ); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSP::FinalRelease() { LOG((TL_TRACE, "FinalRelease - enter")); #if DBG ClientFree( m_pDebug ); #endif m_TerminalArray.Shutdown(); m_CallArray.Shutdown(); LOG((TL_TRACE, "FinalRelease - exit")); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::get_StaticTerminals // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::get_StaticTerminals( VARIANT * pVariant ) { HRESULT hr = S_OK; IDispatch * pDisp; LOG((TL_TRACE, "get_StaticTerminals - enter")); if (TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) ) { LOG((TL_ERROR, "get_StaticTerminals - bad pointer")); return E_POINTER; } CComObject< CTapiCollection< ITTerminal > > * p; CComObject< CTapiCollection< ITTerminal > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_StaticTerminals - could not create collection" )); return E_OUTOFMEMORY; } Lock(); // initialize hr = p->Initialize( m_TerminalArray ); Unlock(); if (S_OK != hr) { LOG((TL_ERROR, "get_StaticTerminals - could not initialize collection" )); delete p; return hr; } // // get the IDispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_StaticTerminals - could not get IDispatch interface" )); delete p; return hr; } // // put it in the variant // VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp; LOG(( TL_TRACE, "get_StaticTerminals - exit - return %lx", hr )); LOG((TL_TRACE, "get_StaticTerminals - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::EnumerateStaticTerminals // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::EnumerateStaticTerminals(IEnumTerminal ** ppEnumTerminal) { HRESULT hr = S_OK; LOG((TL_TRACE, "EnumerateStaticTerminals - enter")); if (TAPIIsBadWritePtr(ppEnumTerminal, sizeof( IEnumTerminal * ) ) ) { LOG((TL_ERROR, "EnumerateStaticTerminals - bad pointer")); return E_POINTER; } // // create the enumerator // CComObject< CTapiEnum< IEnumTerminal, ITTerminal, &IID_IEnumTerminal > > * p; hr = CComObject< CTapiEnum< IEnumTerminal, ITTerminal, &IID_IEnumTerminal > > ::CreateInstance( &p ); if (S_OK != hr) { LOG((TL_ERROR, "EnumerateStaticTerminals - could not create enum" )); return hr; } Lock(); // // initialize it with our terminal array // p->Initialize( m_TerminalArray ); Unlock(); // // return it // *ppEnumTerminal = p; LOG(( TL_TRACE, "EnumerateStaticTerminals - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::get_DynamicTerminalClasses // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::get_DynamicTerminalClasses(VARIANT * pVariant) { HRESULT hr = S_OK; CComObject< CTerminalClassCollection > * p; IDispatch * pDisp = NULL; TerminalClassPtrList classlist; LOG((TL_TRACE, "get_DynamicTerminalClasses - enter")); if (TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) ) { LOG((TL_ERROR, "get_DynamicTerminalClasses - bad pointer")); return E_POINTER; } classlist.clear(); // // create the object // CComObject< CTerminalClassCollection >::CreateInstance( &p ); // // init it // hr = p->Initialize( classlist ); // // get the IDispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_dynamicterminalclasses - could not get the IDispatch interface" )); delete p; return hr; } // // put it in the variant // VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp; LOG(( TL_TRACE, "get_DynamicTerminalClasses - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::EnumerateDynamicTerminalClasses // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::EnumerateDynamicTerminalClasses( IEnumTerminalClass ** ppTerminalClassEnumerator ) { HRESULT hr = S_OK; TerminalClassPtrList termlist; LOG((TL_TRACE, "EnumerateDynamicTerminalClasses - enter")); if (TAPIIsBadWritePtr( ppTerminalClassEnumerator, sizeof(IEnumTerminalClass *) ) ) { LOG((TL_ERROR, "EnumerateDynamicTerminalClasses - bad pointer")); return E_POINTER; } termlist.clear(); // // create the enumerator // CComObject< CTerminalClassEnum > * p; CComObject< CTerminalClassEnum >::CreateInstance( &p ); if (NULL == p) { LOG((TL_TRACE, "_EnumDynTermClasses - create enum failed - return %lx", hr )); return hr; } // // init it // hr = p->Initialize( termlist ); if (!SUCCEEDED( hr )) { LOG((TL_TRACE, "_EnumDynTermClasses - init enum failed - return %lx", hr )); delete p; return hr; } *ppTerminalClassEnumerator = p; LOG(( TL_TRACE, "EnumerateDynamicTerminalClasses - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::CreateTerminal // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::CreateTerminal( BSTR TerminalClass, long lMediaType, TERMINAL_DIRECTION TerminalDirection, ITTerminal ** ppTerminal ) { HRESULT hr = TAPI_E_NOTSUPPORTED; LOG((TL_TRACE, "CreateTerminal - enter")); LOG(( TL_TRACE, "CreateTerminal - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CPhoneMSP::GetDefaultStaticTerminal // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSP::GetDefaultStaticTerminal( long lMediaType, TERMINAL_DIRECTION Dir, ITTerminal ** ppTerminal ) { HRESULT hr = S_OK; int iSize, iCount; LOG((TL_TRACE, "GetDefaultStaticTerminal - enter")); if ( TAPIIsBadWritePtr( ppTerminal, sizeof (ITTerminal *) ) ) { LOG((TL_TRACE, "GetDefaultStaticTerminal - bad pointer")); return E_POINTER; } Lock(); iSize = m_TerminalArray.GetSize(); for ( iCount = 0; iCount < iSize; iCount++ ) { TERMINAL_DIRECTION td; long lTermMediaType; hr = m_TerminalArray[iCount]->get_Direction( &td ); if ( SUCCEEDED(hr) ) { hr = m_TerminalArray[iCount]->get_MediaType( &lTermMediaType ); if ( SUCCEEDED(hr) ) { if ( ( td == Dir ) && ( lTermMediaType == lMediaType ) ) { *ppTerminal = m_TerminalArray[iCount]; (*ppTerminal)->AddRef(); Unlock(); LOG(( TL_TRACE, "GetDefaultStaticTerminal - exit - return S_OK" )); return S_OK; } } } } Unlock(); hr = TAPI_E_INVALIDTERMINAL; LOG(( TL_TRACE, "GetDefaultStaticTerminal - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CreateStream // // dwMediaType - mediatype of new stream // // td - direction of new stream // // ppStream - returned stream // // always fails - phone terminals don't handle this type of // functionality // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::CreateStream( long dwMediaType, TERMINAL_DIRECTION td, ITStream ** ppStream ) { HRESULT hr = TAPI_E_NOTSUPPORTED; LOG((TL_TRACE, "CreateStream - enter")); LOG((TL_TRACE, "CreateStream - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // RemoveStream // // pStream - stream to remove // // always fail - phone terminals don't handle this type of // functionality. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::RemoveStream( ITStream * pStream ) { HRESULT hr = TAPI_E_NOTSUPPORTED; LOG((TL_TRACE, "RemoveStream - enter")); LOG((TL_TRACE, "RemoveStream - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // EnumerateStreams // // ppEnumStream - returned enumerator // // enumerates the streams available. this should always be // audio in and audio out // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::EnumerateStreams( IEnumStream ** ppEnumStream ) { HRESULT hr = S_OK; LOG((TL_TRACE, "EnumerateStreams - enter")); if (TAPIIsBadWritePtr(ppEnumStream, sizeof( IEnumStream * ) ) ) { LOG((TL_ERROR, "EnumerateStreams - bad pointer")); return E_POINTER; } // // create the enumerator // CComObject< CTapiEnum< IEnumStream, ITStream, &IID_IEnumStream > > * p; hr = CComObject< CTapiEnum< IEnumStream, ITStream, &IID_IEnumStream > > ::CreateInstance( &p ); if (S_OK != hr) { LOG((TL_ERROR, "EnumerateStreams - could not create enum" )); return hr; } Lock(); // // initialize it with our Stream array // p->Initialize( m_StreamArray ); Unlock(); // // return it // *ppEnumStream = p; LOG((TL_TRACE, "EnumerateStreams - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get_Streams // // pStreams - returned collection // // collection of streams - like enumeratestreams // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::get_Streams( VARIANT * pStreams ) { HRESULT hr = S_OK; IDispatch * pDisp; LOG((TL_TRACE, "get_Streams - enter")); if (TAPIIsBadWritePtr( pStreams, sizeof(VARIANT) ) ) { LOG((TL_ERROR, "get_Streams - bad pointer")); return E_POINTER; } CComObject< CTapiCollection< ITStream > > * p; CComObject< CTapiCollection< ITStream > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_Streams - could not create collection" )); return E_OUTOFMEMORY; } Lock(); // initialize hr = p->Initialize( m_StreamArray ); Unlock(); if (S_OK != hr) { LOG((TL_ERROR, "get_Streams - could not initialize collection" )); delete p; return hr; } // // get the IDispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_Streams - could not get IDispatch interface" )); delete p; return hr; } // // put it in the variant // VariantInit(pStreams); pStreams->vt = VT_DISPATCH; pStreams->pdispVal = pDisp; LOG((TL_TRACE, "get_Streams - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::Initialize( CPhoneMSP * pPhoneMSP ) { HRESULT hr; ITStream * pStream; ITPhoneMSPCallPrivate * pCallPrivate; hr = QueryInterface( IID_ITPhoneMSPCallPrivate, (void**)&pCallPrivate ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "Initialize - out of memory" )); return E_OUTOFMEMORY; } m_t3Phone.hPhone = NULL; m_t3Phone.pMSPCall = pCallPrivate; m_pPhoneMSP = pPhoneMSP; hr = CStream::InternalCreateStream( TAPIMEDIATYPE_AUDIO, TD_RENDER, pCallPrivate, &pStream ); if ( !SUCCEEDED(hr) ) { pCallPrivate->Release(); LOG((TL_ERROR, "Initialize - out of memory" )); return E_OUTOFMEMORY; } AddStream( pStream ); pStream->Release(); hr = CStream::InternalCreateStream( TAPIMEDIATYPE_AUDIO, TD_CAPTURE, pCallPrivate, &pStream ); if ( !SUCCEEDED(hr) ) { pCallPrivate->Release(); LOG((TL_ERROR, "Initialize - out of memory" )); return E_OUTOFMEMORY; } AddStream( pStream ); pStream->Release(); pCallPrivate->Release(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSPCall::FinalRelease() { m_StreamArray.Shutdown(); m_TerminalArray.Shutdown(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSPCall::AddStream( ITStream * pStream ) { Lock(); m_StreamArray.Add( pStream ); Unlock(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSPCall::AddTerminal( ITTerminalPrivate * pTerminal ) { Lock(); m_TerminalArray.Add( pTerminal ); pTerminal->SetMSPCall( this ); if ( PHONEMSP_CONNECTED == m_State ) { } Unlock(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSPCall::RemoveTerminal( ITTerminalPrivate * pTerminal ) { BOOL bRemoved; Lock(); bRemoved = m_TerminalArray.Remove( pTerminal ); if ( bRemoved && (PHONEMSP_DISCONNECTED == m_State) ) { pTerminal->SetMSPCall( NULL ); } Unlock(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::OnConnect() { HRESULT hr = S_OK; int iSize, iCount; DWORD dwHookSwitchDev = 0; HPHONEAPP hPhoneApp = NULL; DWORD dwPhoneID = 0; DWORD dwAPIVersion; LOG((TL_TRACE, "OnConnect - enter")); Lock(); m_State = PHONEMSP_CONNECTED; iSize = m_TerminalArray.GetSize(); if ( 0 == iSize ) { Unlock(); return S_OK; } for ( iCount = 0; iCount < iSize; iCount++ ) { DWORD dwHoldHookSwitchDev; m_TerminalArray[iCount]->GetHookSwitchDev( &dwHoldHookSwitchDev ); dwHookSwitchDev |= dwHoldHookSwitchDev; } m_TerminalArray[0]->GetHPhoneApp( &hPhoneApp ); m_TerminalArray[0]->GetPhoneID( &dwPhoneID ); m_TerminalArray[0]->GetAPIVersion( &dwAPIVersion ); if (m_t3Phone.hPhone == NULL) { hr = PhoneOpen( hPhoneApp, dwPhoneID, &m_t3Phone, dwAPIVersion, PHONEPRIVILEGE_OWNER ); if ( !SUCCEEDED(hr) ) { } } ASYNCEVENTMSG Msg; Msg.Msg = PRIVATE_PHONESETHOOKSWITCH; Msg.TotalSize = sizeof (ASYNCEVENTMSG); Msg.hDevice = (ULONG_PTR) this; Msg.Param1 = PHONEHOOKSWITCHMODE_MICSPEAKER; Msg.Param2 = dwHookSwitchDev; AddRef(); QueueCallbackEvent( &Msg ); Unlock(); LOG((TL_TRACE,hr, "OnConnect - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::OnDisconnect() { HRESULT hr = S_OK; LOG((TL_TRACE, "OnDisconnect - enter")); Lock(); if (m_t3Phone.hPhone != NULL) { hr = PhoneClose(m_t3Phone.hPhone); m_t3Phone.hPhone = NULL; } m_State = PHONEMSP_DISCONNECTED; Unlock(); LOG((TL_TRACE,hr, "OnDisconnect - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::SelectTerminal( ITTerminalPrivate * pTerminal ) { ITTerminal * pITTerminal; HRESULT hr; hr = pTerminal->QueryInterface( IID_ITTerminal, (void**) &pITTerminal ); if ( SUCCEEDED(hr) ) { hr = m_pPhoneMSP->VerifyTerminal( pITTerminal ); pITTerminal->Release(); if ( SUCCEEDED(hr) ) { AddTerminal( pTerminal ); } } return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CPhoneMSPCall::UnselectTerminal( ITTerminalPrivate * pTerminal ) { RemoveTerminal( pTerminal ); return S_OK; } STDMETHODIMP CPhoneMSPCall::GetGain(long *pVal, DWORD dwHookSwitch) { HRESULT hr; hr = PhoneGetGain( m_t3Phone.hPhone, dwHookSwitch, (DWORD *)pVal ); if ( ((long)hr) > 0 ) { hr = WaitForPhoneReply( hr ); } return hr; } STDMETHODIMP CPhoneMSPCall::PutGain(long newVal, DWORD dwHookSwitch) { HRESULT hr; hr = PhoneSetGain( m_t3Phone.hPhone, dwHookSwitch, newVal ); if ( ((long)hr) > 0 ) { hr = WaitForPhoneReply( hr ); } return hr; } STDMETHODIMP CPhoneMSPCall::GetVolume(long *pVal, DWORD dwHookSwitch) { HRESULT hr; hr = PhoneGetVolume( m_t3Phone.hPhone, dwHookSwitch, (DWORD *)pVal ); if ( ((long)hr) > 0 ) { hr = WaitForPhoneReply( hr ); } return hr; } STDMETHODIMP CPhoneMSPCall::PutVolume(long newVal, DWORD dwHookSwitch) { HRESULT hr; hr = PhoneSetVolume( m_t3Phone.hPhone, dwHookSwitch, newVal ); if ( ((long)hr) > 0 ) { hr = WaitForPhoneReply( hr ); } return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CPhoneMSPCall::HandlePrivateHookSwitch( PASYNCEVENTMSG pParams ) { CPhoneMSPCall * pMSPCall; HRESULT hr; pMSPCall = (CPhoneMSPCall *)(pParams->hDevice); hr = PhoneSetHookSwitch( pMSPCall->m_t3Phone.hPhone, pParams->Param2, pParams->Param1 ); if ( SUCCEEDED(hr) ) { hr = WaitForPhoneReply(hr); } pMSPCall->Release(); }