⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapieventprocess.cpp

📁 具有语音自动应答功能的串口程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                                           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 + -