📄 tapisend.cpp
字号:
break;;
}
}
//
// can't use this address. release it
//
pAddress->Release();
pAddress = NULL;
}
//
// done with the enumeration. release.
//
pEnumAddress->Release();
pEnumAddress = NULL;
//
// log a message if no address was found
//
if (NULL == *ppAddress)
{
LogError("FindAddress: no address found");
return E_FAIL;
}
LogMessage("FindAddress: completed");
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// GetAddressType
//
// convert a address type specified by pszRequestedAddressType
// to tapi LINEADDRESSTYPE_ constants (LINEADDRESSTYPE_PHONENUMBER,
// LINEADDRESSTYPE_IPADDRESS, etc).
//
// returns E_FAIL if the string does not correspond to a valid address type
//
///////////////////////////////////////////////////////////////////////////////
HRESULT GetAddressType(IN char *pszRequestedAddressType,
IN OUT long *pnAddressType)
{
//
// match address type specified by the user to one of the known
// address types
//
*pnAddressType = 0;
for (int i = 0; i < g_nNumberOfAddressTypes; i++)
{
if (0 == _stricmp(g_szAddressTypes[i], pszRequestedAddressType))
{
//
// get the address type constant corresponding to the string
//
*pnAddressType = g_nAddressTypeConstants[i];
LogMessage("GetAddressType: "
"matched address type [%s] to address type [%d]",
pszRequestedAddressType, *pnAddressType);
return S_OK;
}
}
LogError("GetAddressType: unrecognized address type [%s]",
pszRequestedAddressType);
return E_FAIL;
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateBSTRfromString
//
// create a bstr from a string supplied. the caller is responsible for
// freeng the returned string by calling SysFreeString.
//
// returns the allocated string or NULL if failed.
//
///////////////////////////////////////////////////////////////////////////////
BSTR CreateBSTRfromString(IN char *pszString)
{
//
// convert to wchar so we can create bstr
//
// allocate buffer for resulting string of wchars
//
size_t nStringLength = strlen(pszString) + 1;
WCHAR *pwsString = (WCHAR *)AllocateMemory(sizeof(WCHAR) * nStringLength);
if (NULL == pwsString)
{
LogError("CreateBSTRfromString: "
"failed to allocate memory for address string.");
return NULL;
}
//
// convert to wchar
//
int rc = MultiByteToWideChar(CP_ACP,
0,
pszString,
-1,
pwsString,
(int)nStringLength);
if (0 == rc)
{
LogError("CreateBSTRfromString: Failed to convert char to wchar");
FreeMemory(pwsString);
pwsString = NULL;
return NULL;
}
//
// create bstr
//
BSTR bstr = SysAllocString(pwsString);
//
// no longer needed, deallocate
//
FreeMemory(pwsString);
pwsString = NULL;
return bstr;
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateAndConnectCall
//
// make a call using the address object specified, to the address specified
//
// if successful, returns S_OK and connected call, error otherwise
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CreateAndConnectCall(IN ITAddress *pAddress,
IN char *pszDestinationAddress,
IN long nAddressType,
OUT ITBasicCallControl **ppCall)
{
HRESULT hr = E_FAIL;
//
// don't return garbage
//
*ppCall = NULL;
//
// create a call on the address
//
BSTR bstrDestinationAddress = CreateBSTRfromString(pszDestinationAddress);
ITBasicCallControl *pCall = NULL;
hr = pAddress->CreateCall(bstrDestinationAddress,
nAddressType,
TAPIMEDIATYPE_AUDIO,
&pCall);
SysFreeString (bstrDestinationAddress);
if (FAILED(hr))
{
LogError("CreateAndConnectCall: Failed to create a call");
return hr;
}
//
// call created. attempt to connect synchronously
//
LogMessage("CreateAndConnectCall: attempting a synchronous connect");
hr = pCall->Connect(VARIANT_TRUE);
if (S_OK != hr)
{
LogError("CreateAndConnectCall: failed to connect, hr = 0x%lx", hr);
pCall->Disconnect(DC_NORMAL);
//
// we don't need the call object if it failed to connect
//
pCall->Release();
pCall = NULL;
hr = E_FAIL;
}
else
{
//
// call is successful. return the call object
//
LogMessage("CreateAndConnectCall: call connected successfully");
*ppCall = pCall;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// Call
//
// make a call to the specified address on the first address object
// of the requested type that supports audio
//
// if successful, returns S_OK and connected call, error otherwise
//
///////////////////////////////////////////////////////////////////////////////
HRESULT Call(IN char *szDestinationAddress,
IN char *szAddressType,
OUT ITBasicCallControl **ppCall)
{
HRESULT hr = E_FAIL;
//
// we don't want to return garbage even if we fail
//
*ppCall = NULL;
//
// find address type
//
long nAddressType = 0;
hr = GetAddressType(szAddressType, &nAddressType);
if (FAILED(hr))
{
LogError("Call: failed to recognize address type %s", szAddressType);
return hr;
}
//
// find an address for this address type that supports audio
//
ITAddress *pAddress = NULL;
hr = FindAddress(nAddressType, &pAddress);
if (FAILED(hr))
{
LogError("Call: failed to find an address with audio for type %s",
szAddressType);
return hr;
}
//
// have the address. create and connect call
//
ITBasicCallControl *pCall = NULL;
hr = CreateAndConnectCall(pAddress,
szDestinationAddress,
nAddressType,
&pCall);
pAddress->Release();
pAddress = NULL;
if (FAILED(hr))
{
LogError("Call: Failed to create and connect call");
return hr;
}
//
// we have a connected call. return it.
//
*ppCall = pCall;
LogMessage("Call: succeeded.");
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// FindAudioStream
//
// given a call, return the first outgoing audio stream.
//
// returns S_OK if successful, error otherwise
//
///////////////////////////////////////////////////////////////////////////////
HRESULT FindAudioStream( IN ITBasicCallControl *pCall,
OUT ITStream **ppStream)
{
HRESULT hr = E_FAIL;
LogMessage("FindAudioStream: started");
//
// don't return garbage
//
*ppStream = NULL;
//
// enumerate streams on the call
//
//
// get the ITStreamControl interface for this call
//
ITStreamControl *pStreamControl = NULL;
hr = pCall->QueryInterface(IID_ITStreamControl,
(void **) &pStreamControl);
if (FAILED(hr))
{
LogError("FindAudioStream: failed to QI call for ITStreamControl");
return hr;
}
//
// enumerate the streams
//
IEnumStream *pEnumStreams = NULL;
hr = pStreamControl->EnumerateStreams(&pEnumStreams);
pStreamControl->Release();
pStreamControl = NULL;
if (FAILED(hr))
{
LogError("CreateAndSelectMST: failed to enumerate streams on call");
return hr;
}
//
// walk through the streams on the call
// return the first outgoing audio stream
//
while (TRUE)
{
ITStream *pStream = NULL;
hr = pEnumStreams->Next(1, &pStream, NULL);
if (S_OK != hr)
{
//
// no more streams
//
break;
}
//
// check the stream's direction
//
TERMINAL_DIRECTION td;
hr = pStream->get_Direction(&td);
if (FAILED(hr))
{
LogError("CreateAndSelectMST: Failed to get stream direction");
pStream->Release();
pStream = NULL;
//
// proceed to the next stream, if any
//
continue;
}
//
// is the stream of the right direction?
//
if (TD_CAPTURE != td)
{
//
// incoming stream. we need outgoing.
// release the stream and continue
//
pStream->Release();
pStream = NULL;
continue;
}
//
// check the stream's media type
//
long lMediaType = 0;
hr = pStream->get_MediaType(&lMediaType);
if (FAILED(hr))
{
LogError("CreateAndSelectMST: Failed to get media type");
pStream->Release();
pStream = NULL;
continue;
}
//
// Does this stream have the right media type?
// Streams are defined as having exactly one media type
// (not a bitmask).
//
if ( lMediaType == TAPIMEDIATYPE_AUDIO )
{
LogMessage("FindAudioStream: stream found");
//
// this is what we need, so stop looking
//
*ppStream = pStream;
break;
}
pStream->Release();
pStream = NULL;
} // while (walking through the call's streams)
//
// release stream enumeration
//
pEnumStreams->Release();
pEnumStreams = NULL;
//
// return the error code, depending on whether we found a stream or not
//
if (NULL == *ppStream)
{
LogMessage("FindAudioStream: didn't find an audio stream");
return E_FAIL;
}
LogMessage("FindAudioStream: succeded");
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateCaptureMediaStreamingTerminal
//
// create media streaming terminal for outgoing data
//
// returns the created terminal or NULL if failed
//
///////////////////////////////////////////////////////////////////////////////
ITTerminal *CreateCaptureMediaStreamingTerminal(IN ITBasicCallControl *pCall)
{
HRESULT hr = E_FAIL;
//
// get the call's call info so we can get the call's address
//
ITCallInfo *pCallInfo = NULL;
hr = pCall->QueryInterface(IID_ITCallInfo, (void**)&pCallInfo);
if (FAILED(hr))
{
LogError("CreateCaptureMediaStreamingTerminal: "
"failed to qi call for ITCallInfo");
return NULL;
}
//
// now we can get the address
//
ITAddress *pAddress = NULL;
hr = pCallInfo->get_Address(&pAddress);
pCallInfo->Release();
pCallInfo = NULL;
if (FAILED(hr))
{
LogError("CreateCaptureMediaStreamingTerminal: "
"failed to get call's address");
return NULL;
}
//
// get the terminal support interface
//
ITTerminalSupport *pTerminalSupport = NULL;
hr = pAddress->QueryInterface( IID_ITTerminalSupport,
(void **)&pTerminalSupport );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -