WindowsXP-SP1/enduser/netmeeting/core/h323.cpp

361 lines
8.2 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "precomp.h"
//
// H323UI.cpp
//
// ChrisPi
//
// Created: 03-04-96 (as audioui.cpp)
// Renamed: 02-20-97
//
#include <mmreg.h>
#include <mmsystem.h>
#include "h323.h"
#include <ih323cc.h>
#include <mperror.h>
PORT g_ListenPort; // port # that this app is listening on
static const char g_cszCreateStreamProviderEP[] = _TEXT("CreateStreamProvider");
// static member initialization:
CH323UI* CH323UI::m_spH323UI = NULL;
CH323UI::CH323UI() :
m_pH323CallControl(NULL),
m_pStreamProvider(NULL),
m_pConnEvent(NULL),
m_pConfAdvise(NULL),
m_uCaps(0),
m_uRef(1)
{
DebugEntry(CH323UI::CH323UI);
if (NULL == CH323UI::m_spH323UI)
{
m_spH323UI = this;
}
else
{
ERROR_OUT(("CH323UI class can only be constructed once for now!"));
}
DebugExitVOID(CH323UI::CH323UI);
}
CH323UI::~CH323UI()
{
DebugEntry(CH323UI::~CH323UI);
if (NULL != m_pH323CallControl)
{
m_pH323CallControl->Release();
m_pH323CallControl = NULL;
}
if(NULL != m_pStreamProvider)
{
m_pStreamProvider->Release();
m_pStreamProvider = NULL;
}
if (m_spH323UI == this)
{
m_spH323UI = NULL;
}
DebugExitVOID(CH323UI::~CH323UI);
}
ULONG CH323UI::AddRef()
{
m_uRef++;
return m_uRef;
}
ULONG CH323UI::Release()
{
m_uRef--;
if(m_uRef == 0)
{
delete this;
return 0;
}
return m_uRef;
}
STDMETHODIMP CH323UI::QueryInterface( REFIID iid, void ** ppvObject)
{
HRESULT hr = E_NOINTERFACE;
if(!ppvObject)
return hr;
*ppvObject = 0;
if((iid == IID_IH323ConfAdvise)
|| (iid == IID_IUnknown))
{
*ppvObject = (IH323ConfAdvise *)this;
hr = hrSuccess;
AddRef();
}
return (hr);
}
STDMETHODIMP CH323UI::GetMediaChannel (GUID *pmediaID,
BOOL bSendDirection, IMediaChannel **ppI)
{
ASSERT(m_pStreamProvider);
// delegate to the appropriate stream provider. For the time being
// there is only one provider that does both audio & video
// the assignment of media streams to channels should be under control of this
// (CH323UI) module and the related (i.e. CVideoPump) objects. There is no
// current way to for CH323UI to tell CVideoPump what the media stream interface
// pointer is, but the underlying CommChannel (CVideoPump::m_pCommChannel) has to
// remember this assignment for other reasons. For the time being, let CVideoPump
// get the assigned media stream from the CommChannel.
return (::GetConfObject())->GetMediaChannel(pmediaID,
bSendDirection, ppI);
}
HRESULT CH323UI::Init(HWND hwnd, HINSTANCE hInstance, UINT uCaps,
CH323ConnEvent *pConnEvent, IH323ConfAdvise *pConfAdvise)
{
DebugEntry(CH323UI::Init);
HINSTANCE hLibH323CC = NULL;
HINSTANCE hLibStream = NULL;
CREATEH323CC pfnCreateH323CC = NULL;
CREATE_SP pfnCreateStreamProvider =NULL;
HRESULT hr = E_FAIL;
ASSERT(uCaps & CAPFLAG_H323_CC);
m_uCaps = uCaps;
ASSERT(NULL == m_pH323CallControl);
//
// Initialize H323 call control
//
hLibH323CC = NmLoadLibrary(H323DLL);
if (hLibH323CC == NULL)
{
WARNING_OUT(("LoadLibrary(H323DLL) failed"));
hr = GetLastHR();
goto MyExit;
}
pfnCreateH323CC = (CREATEH323CC) ::GetProcAddress(hLibH323CC, SZ_FNCREATEH323CC);
if (pfnCreateH323CC == NULL)
{
ERROR_OUT(("GetProcAddress(CreateH323CC) failed"));
hr = GetLastHR();
goto MyExit;
}
hr = pfnCreateH323CC(&m_pH323CallControl, TRUE, uCaps);
if (FAILED(hr))
{
ERROR_OUT(("CreateH323CC failed, hr=0x%lx", hr));
goto MyExit;
}
hr = m_pH323CallControl->Initialize(&g_ListenPort);
if (FAILED(hr))
{
// Made this a warning because it is common (occurs on all machines
// without sound cards)
WARNING_OUT(("H323CallControlInitialize failed, hr=0x%lx", hr));
goto MyExit;
}
//
// If H323 AV streaming is allowed, initialize that too.
//
if (uCaps & CAPFLAGS_AV_STREAMS)
{
hLibStream = NmLoadLibrary(NACDLL);
if (hLibStream == NULL)
{
WARNING_OUT(("LoadLibrary(NACDLL) failed"));
hr = GetLastHR();
goto MyExit;
}
pfnCreateStreamProvider = (CREATE_SP) ::GetProcAddress(hLibStream, g_cszCreateStreamProviderEP);
if (pfnCreateStreamProvider == NULL)
{
ERROR_OUT(("GetProcAddress(CreateStreamProvider) failed"));
hr = GetLastHR();
goto MyExit;
}
hr = pfnCreateStreamProvider(&m_pStreamProvider);
if (FAILED(hr))
{
ERROR_OUT(("CreateStreamProvider failed, hr=0x%lx", hr));
goto MyExit;
}
hr = m_pStreamProvider->Initialize(hwnd, hInstance);
if (FAILED(hr))
{
// Made this a warning because it is common (occurs on all machines
// without sound cards)
WARNING_OUT(("m_pStreamProvider ->Initialize failed, hr=0x%lx", hr));
goto MyExit;
}
}
hr = m_pH323CallControl->RegisterConnectionNotify(CH323UI::ConnectionNotify);
if (FAILED(hr))
{
ERROR_OUT(("RegisterConnectionNotify failed, hr=0x%lx", hr));
goto MyExit;
}
// store the callback interfaces
m_pConnEvent = pConnEvent;
m_pConfAdvise = pConfAdvise;
MyExit:
if (FAILED(hr))
{
if(NULL != m_pStreamProvider)
{
m_pStreamProvider->Release();
m_pStreamProvider = NULL;
}
if(NULL != m_pH323CallControl)
{
// If there was an error during init, ensure that the nac
// object is released and the pointer is set to NULL
m_pH323CallControl->Release();
m_pH323CallControl = NULL;
}
}
DebugExitULONG(CH323UI::Init, hr);
return hr;
}
CREQ_RESPONSETYPE CH323UI::_ConnectionNotify( IH323Endpoint* pConn,
P_APP_CALL_SETUP_DATA lpvMNMData)
{
CREQ_RESPONSETYPE resp = CRR_REJECT;
HRESULT hr;
ASSERT(m_pConfAdvise);
hr = pConn->SetAdviseInterface (m_pConfAdvise);
if (FAILED(hr))
{
ERROR_OUT(("ConnectionNotify: couldn't SetAdviseInterface, hr=0x%lx\r", hr));
}
if (NULL != m_pConnEvent)
{
resp = m_pConnEvent->OnH323IncomingCall(pConn, lpvMNMData);
}
// BUGBUG: the caller is assuming that the callee will be doing the release
// this should be changed so that the caller does the release
pConn->Release();
return resp;
}
CREQ_RESPONSETYPE CALLBACK CH323UI::ConnectionNotify( IH323Endpoint* pConn,
P_APP_CALL_SETUP_DATA lpvMNMData)
{
DebugEntry(CH323UI::ConnectionNotify);
CREQ_RESPONSETYPE resp = CRR_REJECT;
if (pConn == NULL)
{
ERROR_OUT(("ConnectionNotify called with NULL pConn!"));
}
else
{
ASSERT(m_spH323UI);
resp = m_spH323UI->_ConnectionNotify(pConn, lpvMNMData);
}
DebugExitINT(CH323UI::ConnectionNotify, resp);
return resp;
}
VOID CH323UI::SetCaptureDevice(DWORD dwCaptureID)
{
// Select the proper capture device
HRESULT hr;
IVideoDevice *pVideoDevice = NULL;
if (m_pStreamProvider)
{
hr = m_pStreamProvider->QueryInterface(IID_IVideoDevice, (void **)&pVideoDevice);
if(FAILED(hr))
{
ERROR_OUT(("CH323UI::SetCaptureDevice failed"));
return;
}
if(pVideoDevice)
{
pVideoDevice->SetCurrCapDevID(dwCaptureID);
pVideoDevice->Release();
}
}
}
VOID CH323UI::SetBandwidth(DWORD dwBandwidth)
{
HRESULT hr = m_pH323CallControl->SetMaxPPBandwidth(dwBandwidth);
ASSERT(SUCCEEDED(hr));
}
// This (SetUserName) is not really sufficient for H.323 calls and gatekeeper
// registration. 2 items are needed (display name, H.323 ID)
// And a third is optional. (users phone number in E.164 form).
// This hack takes the single display name and sets BOTH the H323ID and user
// display name.
VOID CH323UI::SetUserName(BSTR bstrName)
{
HRESULT hr;
ASSERT(bstrName);
H323ALIASLIST AliasList;
H323ALIASNAME AliasName;
AliasName.aType = AT_H323_ID;
AliasList.wCount = 1;
AliasList.pItems = &AliasName;
AliasName.lpwData = bstrName;
AliasName.wDataLength = (WORD)SysStringLen(bstrName);// # of unicode chars, w/o NULL terminator
hr = m_pH323CallControl->SetUserAliasNames(&AliasList);
ASSERT(SUCCEEDED(hr));
hr = m_pH323CallControl->SetUserDisplayName(AliasName.lpwData);
ASSERT(SUCCEEDED(hr));
}
IMediaChannelBuilder* CH323UI::GetStreamProvider()
{
if (m_pStreamProvider)
{
m_pStreamProvider->AddRef();
}
return m_pStreamProvider;
}