📄 tapieventprocess.cpp
字号:
VARIANT_TRUE,
VARIANT_TRUE,
lMediaTypes,
0,
&lRegister
);
return hr;
}
/////////////////////////////////////////////////////////////////
// MakeTheCall
//
// 功能:设置并呼叫号码
/////////////////////////////////////////////////////////////////
HRESULT
CTapi::MakeTheCall(
IN DWORD dwAddressType,
IN PWCHAR szAddressToCall
)
{
HRESULT hr = S_OK;
BSTR bstrAddressToCall;
//
// 检测当前地址是否有效
//
if( m_pAddress == NULL)
return E_FAIL;
//
// 这里我们只要求支持声音即可
//
long lMediaTypes = TAPIMEDIATYPE_AUDIO;
//
// 因为我们在对线路侦听时,已经确定 m_Address 至少支持声音,
// 已经满足我们要求,不用另做检测
//
//
// 建立呼叫
//
bstrAddressToCall = SysAllocString( szAddressToCall );
hr = m_pAddress->CreateCall( bstrAddressToCall,
dwAddressType,
lMediaTypes,
&m_pCall);
SysFreeString ( bstrAddressToCall );
if ( FAILED(hr) )
{
AfxMessageBox("建立呼叫失败!");
return hr;
}
//
// 为当前呼叫选择终端
//
hr = SelectTerminalsOnCall(m_pAddress, m_pCall );
//
// 正式发出呼叫
//
hr = m_pCall->Connect( VARIANT_TRUE );
if ( FAILED(hr) )
{
m_pCall->Release();
m_pCall = NULL;
AfxMessageBox("无法连接!");
return hr;
}
return S_OK;
}
/////////////////////////////////////////////////////////
// GetTerminal
//
// 为输入 stream 创建默认的 terminal,并通过 ppTerminal 返回
//
/////////////////////////////////////////////////////////
HRESULT CTapi::GetTerminal(
ITAddress * pAddress,
ITStream * pStream,
ITTerminal ** ppTerminal
)
{
//
// 确定当前传入 stream 的 media type 和 direction
//
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;
//
// 这里我们人处理 Audio 流,对于 Video 流,我们不令做处理
// 因此只调用 GetDefaultStaticTerminal.
// 首先,获得 ITTerminalSupport 接口
//
ITTerminalSupport * pTerminalSupport;
hr = pAddress->QueryInterface( IID_ITTerminalSupport,
(void **)&pTerminalSupport);
if ( SUCCEEDED(hr) )
{
//
// 为这种 MediaType 和 Direction 获得默认的 Terminal
//
hr = pTerminalSupport->GetDefaultStaticTerminal(lMediaType,
dir,
ppTerminal);
pTerminalSupport->Release();
}
return hr;
}
/////////////////////////////////////////////////////////////////
// SelectTerminalOnCall
//
// 在给定的 call 上中的 stream 中选择一个适当的 terminal
/////////////////////////////////////////////////////////////////
HRESULT CTapi::SelectTerminalsOnCall(
ITAddress * pAddress,
ITBasicCallControl * pCall
)
{
HRESULT hr;
//
// 为当前 call 获得 ITStreamControl 接口
//
ITStreamControl * pStreamControl;
hr = pCall->QueryInterface(IID_ITStreamControl,
(void **) &pStreamControl);
if ( SUCCEEDED(hr) )
{
//
// 列举所有的 stream
//
IEnumStream * pEnumStreams;
hr = pStreamControl->EnumerateStreams(&pEnumStreams);
pStreamControl->Release();
if ( SUCCEEDED(hr) )
{
//
// 遍历所有的 stream
//
ITStream * pStream;
while ( S_OK == pEnumStreams->Next(1, &pStream, NULL) )
{
ITTerminal * pTerminal;
//
// 找出当前 stream 的 media type 和 direction,
// 并且为这种 media type 和 direction 创建默认的 terminal
//
hr = GetTerminal(pAddress,
pStream,
&pTerminal);
if ( SUCCEEDED(hr) )
{
//
// 对当前的 Stream 选择上面获得的 Terminal
//
hr = pStream->SelectTerminal(pTerminal);
pTerminal->Release();
}
pStream->Release();
}
pEnumStreams->Release();
}
}
return hr;
}
/////////////////////////////////////////////////////////////////
// PreparePlay
//
// 功能:播放给定的声音文件
/////////////////////////////////////////////////////////////////
HRESULT
CTapi::PreparePlay(CString strFileName)
{
//
// 检测当前的 call object 是否有效
//
if (NULL == m_pCall)
{
AfxMessageBox("AnswerTheCall: Call object 无效");
return E_UNEXPECTED;
}
//
// 如果 m_pPlayFileTerm 不是NULL,先释放之
//
if(NULL != m_pPlayFileTerm)
{
m_pPlayFileTerm->Release();
m_pPlayFileTerm = NULL;
}
//
// 为请求终端作准备 - 需要 ITBasicCallControl2 接口,只有在 TAPI3.1 中才支持
//
ITBasicCallControl2* pITBCC2 = NULL;
HRESULT hr = m_pCall->QueryInterface( IID_ITBasicCallControl2, (void**)&pITBCC2 );
if(FAILED(hr))
{
AfxMessageBox("AnswerTheCall: QI ITBasicCallControl2 failed");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
//
// 为请求终端作准备 - need CLSID BSTR
//
BSTR bstrCLSID = NULL;
hr = StringFromCLSID(CLSID_FilePlaybackTerminal, &bstrCLSID);
if(FAILED(hr))
{
pITBCC2->Release();
AfxMessageBox("AnswerTheCall: StringFromCLSID failed");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
//
//正式请求终端,需要媒体流类型和媒体流方向
//
hr = pITBCC2->RequestTerminal(bstrCLSID,
TAPIMEDIATYPE_AUDIO,
TD_CAPTURE,
&m_pPlayFileTerm);
//
//释放内存
//
::CoTaskMemFree(bstrCLSID);
if(FAILED(hr))
{
pITBCC2->Release();
AfxMessageBox("AnswerTheCall: RequestTerminal failed");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
//
// 为设置文件名作准备
//
BSTR bstrFileName = strFileName.AllocSysString();
if(NULL == bstrFileName)
{
m_pPlayFileTerm->Release();
m_pPlayFileTerm = NULL;
pITBCC2->Release();
AfxMessageBox("AnswerTheCall: SysAllocString for play list failed");
m_pCall->Disconnect(DC_NORMAL);
return E_OUTOFMEMORY;
}
//
// 为 m_pPlayFileTerm 设置文件名
//
hr = PutPlayList(m_pPlayFileTerm, bstrFileName);
//
// 释放内存
//
::SysFreeString(bstrFileName);
if(FAILED(hr))
{
m_pPlayFileTerm->Release();
m_pPlayFileTerm = NULL;
pITBCC2->Release();
AfxMessageBox("AnswerTheCall: PutPlayList failed");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
//
// 用 ITBasicCallControl2 选择终端
//
hr = pITBCC2->SelectTerminalOnCall(m_pPlayFileTerm);
if(FAILED(hr))
{
m_pPlayFileTerm->Release();
m_pPlayFileTerm = NULL;
pITBCC2->Release();
AfxMessageBox("AnswerTheCall: SelectTerminalOnCall failed");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
pITBCC2->Release();
return S_OK;
}
/////////////////////////////////////////////////////////////////////
// Answers the call
//
// 功能:应答电话,创建并选择播放的终端
/////////////////////////////////////////////////////////////////////
HRESULT
CTapi::AnswerTheCall()
{
HRESULT hr;
hr = PreparePlay(m_WelcomeFileName);
if( FAILED(hr) )
{
AfxMessageBox("无法找到" + m_WelcomeFileName + "文件或该文件不是合法的语音文件!");
return E_FAIL;
}
//
// 现在可以正式应答电话了
//
hr = m_pCall->Answer();
if(FAILED(hr))
{
m_pPlayFileTerm->Release();
m_pPlayFileTerm = NULL;
AfxMessageBox("AnswerTheCall: Answer failed");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
//
// 到此正常结束
//
// pITBCC2->Release();
return S_OK;
}
//////////////////////////////////////////////////////////////////////
// DisconnectTheCall
//
// 功能:挂断电话
//////////////////////////////////////////////////////////////////////
HRESULT CTapi::DisconnectTheCall()
{
HRESULT hr = S_OK;
if (NULL != m_pCall)
{
hr = m_pCall->Disconnect( DC_NORMAL );
//
// 暂时不要释放 m_pCall,因为这样做的话我们无法得到 Disconnected 消息
//
return hr;
}
return S_FALSE;
}
//////////////////////////////////////////////////////////////////////
// ReleaseTheCall
//
// 释放通话过程中所用到的 object
//
//////////////////////////////////////////////////////////////////////
void
CTapi::ReleaseTheCall()
{
// KillTimer(m_hWnd, TIMER_ID);
//
// 释放终端
//
if(NULL != m_pPlayFileTerm)
{
m_pPlayFileTerm->Release();
m_pPlayFileTerm = NULL;
}
if(NULL != m_pRecordFileTerm)
{
m_pRecordFileTerm->Release();
m_pRecordFileTerm = NULL;
}
//
// 释放 call object - 这样会同时释放所有的被选择过得终端
//
if (NULL != m_pCall)
{
m_pCall->Release();
m_pCall = NULL;
}
}
//////////////////////////////////////////////////////////////////
// PutPlayList
//
// 功能:将要播放的声音文件放入播放列表。调用了 put_PlayList
//////////////////////////////////////////////////////////////////
HRESULT CTapi::PutPlayList(
IN ITTerminal *pITTerminal,
IN BSTR bstrFileName)
{
//
// 检测输入的终端是否有效
//
if(NULL == pITTerminal)
{
AfxMessageBox("PutPlayList: playback terminal NULL");
return E_UNEXPECTED;
}
//
// 获得 ITMediaPlayback 接口
//
ITMediaPlayback* pMediaPlayback = NULL;
HRESULT hr = pITTerminal->QueryInterface(
IID_ITMediaPlayback,
(void**)&pMediaPlayback);
if(FAILED(hr))
{
AfxMessageBox("PutPlayList: QI ITMediaPlayback failed");
return hr;
}
//
// put_PlayList 函数需要用到的 VARIANT 变量
//
VARIANT varPlaylist;
VariantInit(&varPlaylist);
//
// 设置 SAFEARRAYBOUND
//
SAFEARRAYBOUND DimensionBounds;
DimensionBounds.lLbound = 1;
//
// 设置 playlist 中的文件数
//
DimensionBounds.cElements = 1;
//
// 把文件名置于 playlist 中的 index = 1处
//
long lArrayPos = 1;
//
// 用于存放文件名 - 用于把文件名加入到 SafeArray
//
VARIANT* pvarArrayEntry = new VARIANT;
if( pvarArrayEntry == NULL)
{
AfxMessageBox("PutPlayList: new VARIANT failed");
return E_OUTOFMEMORY;
}
VariantInit(pvarArrayEntry);
//
// 创建 SAFEARRAY
//
SAFEARRAY *pPlayListArray = NULL;
pPlayListArray = SafeArrayCreate( VT_VARIANT, 1, &DimensionBounds);
if( pPlayListArray == NULL)
{
AfxMessageBox("PutPlayList: SafeArrayCreate failed");
delete pvarArrayEntry;
return E_OUTOFMEMORY;
}
//
// 正式把存储在 pvarArrayEntry 中的文件名加入到 SafeArray 中
// 当我们需要加入多个元素到 SafeArray 中时,只需让 lArrayPos 加 1 即可
//
pvarArrayEntry->vt = VT_BSTR;
pvarArrayEntry->bstrVal = ::SysAllocString(bstrFileName);
SafeArrayPutElement( pPlayListArray, &lArrayPos, pvarArrayEntry);
VariantClear(pvarArrayEntry);
//
// 准备varPlaylist, 为调用 put_PlayList 作准备
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -