📄 mstapi3.cpp
字号:
// enumerate the addresses
hr = tapi->EnumerateAddresses( &pEnumAddress );
if (FAILED(hr)) {
logger->error("EnumerateAddresses() failed: hr=%08X.", hr);
return hr;
}
while (TRUE) {
hr = pEnumAddress->Next( 1, &pAddress, NULL );
if(FAILED(hr)) {
logger->error("pEnumAddress->Next() failed: hr=%08X.", hr);
break;
}
if(hr == S_FALSE) {
logger->info("pEnumAddress done.");
break;
}
BSTR bstrAddrName;
hr = pAddress->get_AddressName(&bstrAddrName);
if(FAILED(hr)) {
logger->error("Cannot retrieve address name: hr=%08X.", hr);
continue;
}
addresses.insert(AddressMap::value_type(bstrAddrName, pAddress));
char addressName[256];
sprintf(addressName, "%S", bstrAddrName);
logger->info("Address %s added.", addressName);
SysFreeString(bstrAddrName);
// does the address support audio?
if (AddressSupportsMediaType(pAddress, TAPIMEDIATYPE_AUDIO)) {
// If it does then we'll listen.
long lRegister;
hr = ListenOnThisAddress(pAddress, &lRegister);
if (FAILED(hr)) {
logger->error("Listen failed on address %s.", addressName);
} else {
callNotificationRegisters.push_back(lRegister);
logger->info("Listener registered on address %s with register %ld.", addressName, lRegister);
}
} else {
logger->info("Not listening on address %s...", addressName);
}
pAddress->Release();
}
pEnumAddress->Release();
return S_OK;
}
///////////////////////////////////////////////////////////////////
// ListenOnThisAddress
//
// We call RegisterCallNotifications to inform TAPI that we want
// notifications of calls on this address. We already resistered
// our notification interface with TAPI, so now we are just telling
// TAPI that we want calls from this address to trigger events on
// our existing notification interface.
//
///////////////////////////////////////////////////////////////////
HRESULT MSTapi3::ListenOnThisAddress(ITAddress* pAddress, long* pRegister) {
//
// RegisterCallNotifications takes a media type bitmap indicating
// the set of media types we are interested in. We know the
// address supports audio, but let's add in video as well
// if the address supports it.
//
long lMediaTypes = TAPIMEDIATYPE_AUDIO;
if(AddressSupportsMediaType(pAddress, TAPIMEDIATYPE_VIDEO)) {
lMediaTypes |= TAPIMEDIATYPE_VIDEO;
}
HRESULT hr;
hr = tapi->RegisterCallNotifications(
pAddress,
VARIANT_TRUE,
VARIANT_TRUE,
lMediaTypes,
gulAdvise,
pRegister
);
return hr;
}
/////////////////////////////////////////////////////////////////
// IsVideoCaptureStream
//
// Returns true if the stream is for video capture
/////////////////////////////////////////////////////////////////
BOOL MSTapi3::IsVideoCaptureStream(ITStream * pStream) {
TERMINAL_DIRECTION tdStreamDirection;
long lStreamMediaType;
if ( FAILED( pStream ->get_Direction(&tdStreamDirection) ) ) { return FALSE; }
if ( FAILED( pStream ->get_MediaType(&lStreamMediaType) ) ) { return FALSE; }
return (tdStreamDirection == TD_CAPTURE) &&
(lStreamMediaType == TAPIMEDIATYPE_VIDEO);
}
/////////////////////////////////////////////////////////
// GetVideoRenderTerminal
//
// Creates a dynamic terminal for the Video Render mediatype / direction
//
/////////////////////////////////////////////////////////
HRESULT MSTapi3::GetVideoRenderTerminal(
ITAddress * pAddress,
ITTerminal ** ppTerminal
)
{
//
// Construct a BSTR for the correct IID.
//
LPOLESTR lpTerminalClass;
HRESULT hr;
hr = StringFromIID(CLSID_VideoWindowTerm, &lpTerminalClass);
if (SUCCEEDED(hr)) {
BSTR bstrTerminalClass;
bstrTerminalClass = SysAllocString ( lpTerminalClass );
CoTaskMemFree( lpTerminalClass );
if ( bstrTerminalClass == NULL ) {
hr = E_OUTOFMEMORY;
}
else {
// Get the terminal support interface
ITTerminalSupport * pTerminalSupport;
hr = pAddress->QueryInterface(IID_ITTerminalSupport, (void **)&pTerminalSupport);
if (SUCCEEDED(hr)) {
// Create the video render terminal.
hr = pTerminalSupport->CreateTerminal(bstrTerminalClass,
TAPIMEDIATYPE_VIDEO,
TD_RENDER,
ppTerminal);
pTerminalSupport->Release();
}
SysFreeString( bstrTerminalClass );
}
}
return hr;
}
/////////////////////////////////////////////////////////////////
// EnablePreview
//
// Selects a video render terminal on a video capture stream,
// thereby enabling video preview.
/////////////////////////////////////////////////////////////////
HRESULT MSTapi3::EnablePreview(ITAddress* pAddress, ITStream* pStream) {
ITTerminal* pTerminal;
HRESULT hr = GetVideoRenderTerminal(pAddress, &pTerminal);
if(FAILED(hr)) {
logger->error("GetVideoRenderTerminal() failed: hr=%08X.", hr);
} else {
hr = pStream->SelectTerminal(pTerminal);
pTerminal->Release();
}
return hr;
}
/////////////////////////////////////////////////////////
// GetTerminal
//
// Creates the default terminal for the passed-in stream.
/////////////////////////////////////////////////////////
HRESULT MSTapi3::GetTerminal(ITAddress* pAddress, ITStream* pStream, ITTerminal** ppTerminal) {
// Determine the media type and direction of this stream.
HRESULT hr;
long lMediaType;
TERMINAL_DIRECTION dir;
hr = pStream->get_MediaType( &lMediaType );
if ( FAILED(hr) ) return hr;
hr = pStream->get_Direction( &dir );
if ( FAILED(hr) ) return hr;
// Since video render is a dynamic terminal, the procedure for creating it is different.
if (( lMediaType == TAPIMEDIATYPE_VIDEO) && (dir == TD_RENDER)) {
return GetVideoRenderTerminal(pAddress, ppTerminal);
}
// For all other terminals we use GetDefaultStaticTerminal.
// First, get the terminal support interface.
ITTerminalSupport * pTerminalSupport;
hr = pAddress->QueryInterface( IID_ITTerminalSupport, (void **)&pTerminalSupport);
if (SUCCEEDED(hr)) {
// get the default terminal for this MediaType and direction
hr = pTerminalSupport->GetDefaultStaticTerminal(lMediaType, dir, ppTerminal);
pTerminalSupport->Release();
}
return hr;
}
/////////////////////////////////////////////////////////////////
// SelectTerminalsOnCall
//
// Selects a given terminal on the first compatible stream that exists on the given call.
/////////////////////////////////////////////////////////////////
HRESULT MSTapi3::SelectTerminalsOnCall(ITAddress* pAddress, ITBasicCallControl* pCall) {
// get the ITStreamControl interface for this call
ITStreamControl* pStreamControl;
HRESULT hr = pCall->QueryInterface(IID_ITStreamControl, (void **) &pStreamControl);
if (FAILED(hr)) {
logger->error("Interface ITStreamControl not supported: hr=%08X", hr);
} else {
// enumerate the streams
IEnumStream * pEnumStreams;
hr = pStreamControl->EnumerateStreams(&pEnumStreams);
pStreamControl->Release();
if(FAILED(hr)){
logger->error("EnumerateStreams() failed: hr=%08X", hr);
} else {
// for each stream
ITStream* pStream;
while (S_OK == pEnumStreams->Next(1, &pStream, NULL)) {
ITTerminal* pTerminal;
// Find out the media type and direction of this stream, and
// create the default terminal for this media type and direction.
hr = GetTerminal(pAddress, pStream, &pTerminal);
if(FAILED(hr)) {
logger->error("GetTerminal() failed: hr=%08X", hr);
} else {
// Select the terminal on the stream.
hr = pStream->SelectTerminal(pTerminal);
if (FAILED(hr)) {
logger->error("SelectTerminal() failed: hr=%08X", hr);
} else {
// Also enable preview on the video capture stream.
if (IsVideoCaptureStream( pStream )) {
EnablePreview(pAddress, pStream);
}
}
pTerminal->Release();
}
pStream->Release();
}
pEnumStreams->Release();
}
}
return hr;
}
//////////////////////////////////////////////////////////////
// AddressSupportsMediaType
//
// Finds out if the given address supports the given media
// type, and returns TRUE if it does.
//////////////////////////////////////////////////////////////
BOOL MSTapi3::AddressSupportsMediaType(ITAddress* pAddress, long lMediaType)
{
VARIANT_BOOL bSupport = VARIANT_FALSE;
ITMediaSupport * pMediaSupport;
if(SUCCEEDED(pAddress->QueryInterface(IID_ITMediaSupport, (void **)&pMediaSupport))) {
// does it support this media type?
pMediaSupport->QueryMediaType(lMediaType, &bSupport);
pMediaSupport->Release();
}
return (bSupport == VARIANT_TRUE);
}
int MSTapi3::reserveCall(wstring& address) {
logger->debug("reserveCall() called for %S", address.c_str());
currCallID++;
calls[currCallID] = NULL;
logger->debug("reserveCall() returning callID=%d for %S", currCallID, address.c_str());
return currCallID;
}
// returns the callID
int MSTapi3::putCall(ITBasicCallControl* pCallControl) {
currCallID++;
calls[currCallID] = pCallControl;
logger->debug("putCall(%d, %p).", currCallID, pCallControl);
return currCallID;
}
ITBasicCallControl* MSTapi3::getCallControl(int callID) {
CallMap::iterator it = calls.find(callID);
if(it != calls.end()) {
return (*it).second;
}
logger->warn("getCallControl(): No call found for callID=%d", callID);
return NULL;
}
void MSTapi3::removeCallControl(int callID) {
CallMap::iterator it = calls.find(callID);
if(it != calls.end()) {
ITBasicCallControl* pCallControl = (*it).second;
calls.erase(it);
if(pCallControl != NULL) {
pCallControl->Release();
logger->debug("CallControl released for callID=%d.", callID);
} else {
logger->debug("Call reserved but not initialized for callID=%d", callID);
}
} else {
logger->warn("removeCallControl(): No call found for callID=%d", callID);
}
}
int MSTapi3::getCallID(ITBasicCallControl* pCallControl) {
for(CallMap::reverse_iterator it = calls.rbegin(); it != calls.rend(); ++it) {
if((*it).second == pCallControl) {
int callID = (*it).first;
logger->debug("getCallID() found callID=%d", callID);
return callID;
}
}
logger->debug("getCallID(): callID not found.");
return -1;
}
// Returns -callID if this is a new call
int MSTapi3::getOrCreateCallID(ITBasicCallControl* pCallControl) {
for(CallMap::reverse_iterator it = calls.rbegin(); it != calls.rend(); ++it) {
if((*it).second == pCallControl) {
int callID = (*it).first;
logger->debug("getOrCreateCallID() found callID=%d", callID);
return callID;
}
}
int callID = putCall(pCallControl);
logger->debug("getOrCreateCallID(): call not found. Created new callID=%d.", callID);
return -callID;
}
ITAddress* MSTapi3::getITAddress(wstring& address) {
AddressMap::iterator it = addresses.find(address);
if(it == addresses.end()) {
logger->warn("Address %S not found", address);
return NULL;
}
ITAddress* pITAddress = (*it).second;
return pITAddress;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -