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

📄 tapiphonedlg.cpp

📁 具有语音自动应答功能的串口程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			{
				//
				// 如果没有 owner 权限,乎略这次拨入
				//
				pCall->Release();

				//
				// 注意:我们在 CTAPIEventNotification::Event() 中调用了 AddRef()
				//
				pEvent->Release(); 
				return S_OK;
			}

			//
			//用来获得乎叫方信息, 用于来电显示
			//
			BSTR bstrCallerName,	bstrCallerNum;
			BSTR bstrCallidName,	bstrCallidNum;
			BSTR bstrConnectName,	bstrConnectNum;

			CString strCallerName,	strCallerNum;
			CString strCallidName,	strCallidNum;
			CString strConnectName,	strConnectNum;
			 
			//The name of the caller. 
			pCall->get_CallInfoString(CIS_CALLERIDNAME, &bstrCallerName);
			strCallerName = bstrCallerName;
			 
			//The number of the caller. 
			pCall->get_CallInfoString(CIS_CALLERIDNUMBER, &bstrCallerNum);
			strCallerNum = bstrCallerNum;
			 
			//The name of the called location. 
			pCall->get_CallInfoString(CIS_CALLEDIDNAME, &bstrCallidName);
			strCallidName = bstrCallidName;
			 
			//The number of the called location. 
			pCall->get_CallInfoString(CIS_CALLEDIDNUMBER, &bstrCallidNum);
			strCallidNum = strCallidNum;
			 
			//The name of the connected location. 
			pCall->get_CallInfoString(CIS_CONNECTEDIDNAME, &bstrConnectName);
			strConnectName = bstrConnectName;
			 
			//The number of the connected location. 
			pCall->get_CallInfoString(CIS_CONNECTEDIDNUMBER, &bstrConnectNum);
			strConnectNum = bstrConnectNum;

			if( strCallidNum.IsEmpty() )
				m_valCallerNum = "呼叫方号码: 无法获得";
			else
				m_valCallerNum = "呼叫方号码: " + strCallidNum;
			UpdateData(FALSE);

			//
			// 获得 ITBasicCallControl 接口并把它保存在成员变量 ppCall 中
			//
			ITBasicCallControl * ppCall;

			hr = pCall->QueryInterface( IID_ITBasicCallControl,
										(void**)&ppCall );
			m_Tapi.m_pCall = ppCall;

			pCall->Release();
	                
			if ( SUCCEEDED(hr) )
			{
				//
				// 更新 UI
				//
				m_btPickup.EnableWindow();
				m_btDisconnect.EnableWindow();
	            SetStatusMessage("有电话呼入...");
			}//end if
		}
    }//end if
	return S_OK;
}//end function

/////////////////////////////////////////////////////////////////////////////////////
// DoCallState 
//
// 功能:处理 TE_STATE 事件,有某种状态改变时触发此事件,比如只有状态为 CS_OFFERING 
// 时才可以应答
/////////////////////////////////////////////////////////////////////////////////////
HRESULT CtapiPhoneDlg::DoCallState(IDispatch* pEvent)
{
	HRESULT				hr;
    CALL_STATE			cs;
    ITCallStateEvent *	pCallStateEvent;

    //
	// 获得接口 
	//
    hr = pEvent->QueryInterface( IID_ITCallStateEvent, (void **)&pCallStateEvent );

    if ( FAILED(hr) )
    {
        return E_FAIL;
    }

	//
	// 检测是否是同一个 Call - 如果不是,不处理这个事件
	//
	if(false == m_Tapi.SameCall(pCallStateEvent))
	{
		pCallStateEvent->Release();
		return hr;
	}

	//
    // 通过 ITCallStateEvent 获得当前状态
	//
    hr = pCallStateEvent->get_State( &cs );

    //
	// 释放接口
	//
    pCallStateEvent->Release();

    if ( FAILED(hr) )
    {
        return E_FAIL;
    }

    //
	// 如果当前状态是 offering,则应答电话,同时更新 UI
	//
    if (CS_OFFERING == cs)
    {
        if (m_AutoAnswer)	//如果选种自动应答
        {
			OnBnClickedBtnPickup();
        }
        else				//选择手动应答
        {
            SetStatusMessage("请点击接听按钮接听电话");
        }
	}
    else if (CS_DISCONNECTED == cs)
    {
		OnBnClickedBtnDisconnect();
		m_Tapi.ReleaseTheCall();
    }
    else if (CS_CONNECTED == cs)
    {
		//
        // 不作处理
		//
    }
    return S_OK;
}

/////////////////////////////////////////////////////////////////////////////////////
// DoCallMedia
//
// 功能:处理 TE_MEDIA 事件,TE_CALLMEDIA 触发 Media 事件,对应接口:ITCallMediaEvent
/////////////////////////////////////////////////////////////////////////////////////
HRESULT CtapiPhoneDlg::DoCallMedia(
					IN IDispatch * pEvent)
{

    CALL_MEDIA_EVENT    cme = CME_STREAM_INACTIVE;
    ITCallMediaEvent  * pCallMediaEvent = NULL;

	//
	// 检测当前 Call 是否有效
	//
	if(NULL == m_Tapi.m_pCall)
	{
		return E_UNEXPECTED;
	}

    //
	// 获得接口
	//
    HRESULT hr = pEvent->QueryInterface( IID_ITCallMediaEvent, (void **)&pCallMediaEvent );
	if(FAILED(hr))
	{
        MessageBox("ITCallMediaEvent, 获取接口失败!");
		return hr;
	}

    //
	// 获得我们检测到的 MediaEvent 具体类型
	//
    hr = pCallMediaEvent->get_Event( &cme );
	if(FAILED(hr))
	{
		pCallMediaEvent->Release();
		MessageBox("ITCallMediaEvent, but failed to get_Event");
		return hr;
	}

    switch ( cme ) 
    {
		// 
		// 这是我们需要处理的唯一的事件
		//
        case CME_STREAM_ACTIVE:    
        {
            //
            // 获得当前活动的终端
            //    
            ITTerminal * pTerminal = NULL;
            hr = m_Tapi.GetTerminalFromStreamEvent(pCallMediaEvent, &pTerminal);

            if ( FAILED(hr) )  
			{
				MessageBox("ITCallMediaEvent: GetTerminalFromStreamEvent failed");
				m_Tapi.m_pCall->Disconnect(DC_NORMAL);
				break; 
			}

            //
            // 根据终端的方向进行处理
            //
            TERMINAL_DIRECTION td;
            hr = pTerminal->get_Direction( &td);
			//
			// 释放接口
			//
            pTerminal->Release(); 

            if ( FAILED(hr) ) 
            { 
	            MessageBox("ITCallMediaEvent: get_Direction failed");
				m_Tapi.m_pCall->Disconnect(DC_NORMAL);
                break; 
            }

			//
			// 方向是 TD_CAPTURE:播放声音文件
			//
            if ( TD_CAPTURE == td && NULL != m_Tapi.m_pPlayFileTerm) 
            {
				ITMediaControl* pITMC = NULL;
				
				hr = m_Tapi.m_pPlayFileTerm->QueryInterface(IID_ITMediaControl, (void**)&pITMC);
				//
				// 获得 ITMediaControl,开始发送媒体流
				//
				if(FAILED(hr))
				{
					MessageBox("ITCallMediaEvent: m_pPlayFileTerm QI for ITMediaControl failed");
					m_Tapi.m_pCall->Disconnect(DC_NORMAL);
					break;
				}
				//
				// 开始发送
				//
				hr = pITMC->Start();
				
				pITMC->Release();
				if(SUCCEEDED(hr))
				{
					SetStatusMessage("正在播放音频文件... ");
				}
				else
				{
		            MessageBox("ITCallMediaEvent: ITMediaControl::Start() failed");
					m_Tapi.m_pCall->Disconnect(DC_NORMAL);
				}
			}
        
            break;
        }
    
        default:
            break;
    }

    //
	// 释放接口
	//
    pCallMediaEvent->Release();

	return hr;
}

///////////////////////////////////////////////////////////////////
// DoFileEvent
//
//
// TE_FILETERMINAL 文件终端事件.  pEvent: ITFileTerminalEvent
// 说明:只有 WinXP 下才支持
///////////////////////////////////////////////////////////////////
HRESULT CtapiPhoneDlg::DoFileEvent(
				IN IDispatch * pEvent)
{
			
	//
	// 检测当前 Call 是否有效
	//
	if(NULL == m_Tapi.m_pCall)
	{
		return E_UNEXPECTED;
	}

	ITFileTerminalEvent* pITFTEvent = NULL;
	HRESULT hr = pEvent->QueryInterface( IID_ITFileTerminalEvent,
									 reinterpret_cast<void **>(&pITFTEvent) );

	if (FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
        MessageBox("ITFileTerminalEvent, 获得接口失败!");
		m_Tapi.m_pCall->Disconnect(DC_NORMAL);
		return hr;
	}

	//
	// 获得状态 - ???????因为我们要确保声音文件未被其它程序使用
	//
	TERMINAL_MEDIA_STATE ftState = TMS_ACTIVE;
	hr = pITFTEvent->get_State(&ftState);
	if(FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
		pITFTEvent->Release();
        MessageBox("ITFileTerminalEvent, but failed to get_State");
		m_Tapi.m_pCall->Disconnect(DC_NORMAL);
		return hr;
	}

	//
	// 我们对 TMS_IDLE 感兴趣,因为我们要停止播放
	//
	if(ftState != TMS_IDLE)
	{
		pITFTEvent->Release();
		return hr;
	}
	//
	// 获得终端
	//
	ITTerminal *pTerminal = NULL;
	hr = pITFTEvent->get_Terminal(&pTerminal);
	//
	// 不再需要这个接口
	//
	pITFTEvent->Release();

	if(FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
        MessageBox("ITFileTerminalEvent, but failed to get_Terminal");
		m_Tapi.m_pCall->Disconnect(DC_NORMAL);
		return hr;
	}

    TERMINAL_DIRECTION td;
    hr = pTerminal->get_Direction( &td);
    pTerminal->Release(); 
	if(FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
        MessageBox("ITFileTerminalEvent, but failed to get_Direction");
		m_Tapi.m_pCall->Disconnect(DC_NORMAL);
		return hr;
	}
	if((td == TD_CAPTURE) && (NULL != m_Tapi.m_pPlayFileTerm))
	{
		SetStatusMessage("通话中...");
		//
		// unselect playback - 因为播放已经完成
		//
		ITBasicCallControl2 *pITBCC2 = NULL;
		hr = m_Tapi.m_pCall->QueryInterface(IID_ITBasicCallControl2, (void**)&pITBCC2);
		if(FAILED(hr))
		{
			//
			// 致命错误 - 无法继续下去 - 切断此次通话
			//
	        MessageBox("ITFileTerminalEvent, but failed to QI for ITBasicCallControl2");
			m_Tapi.m_pCall->Disconnect(DC_NORMAL);
			return hr;
		}
		//
		// 使用 ITBasicCallControl2 方法 - 要比列举媒体流、终端容易的多
		//
		hr = pITBCC2->UnselectTerminalOnCall( m_Tapi.m_pPlayFileTerm);
		m_Tapi.m_pPlayFileTerm->Release();
		m_Tapi.m_pPlayFileTerm = NULL;
		pITBCC2->Release();
		if(FAILED(hr))
		{
			//
			// 致命错误 - 无法继续下去 - 切断此次通话
			//
	        MessageBox("ITFileTerminalEvent, but failed to ITBasicCallControl2::UnselectTerminalOnCall");
			m_Tapi.m_pCall->Disconnect(DC_NORMAL);
			return hr;
		}
	}
	return hr;
}

/////////////////////////////////////////////////////////////////////////////////////
// DigitEvent
//
// 处理 TE_DIGITEVENT 事件,TE_DIGITEVENT 时触发,对应接口 ITDigitDetectionEvent
/////////////////////////////////////////////////////////////////////////////////////
HRESULT CtapiPhoneDlg::DoDigitEvent(IN IDispatch* pEvent)
{
	ITDigitDetectionEvent* pDigitEvent;

	//
	// 获得接口
	//
	pEvent->QueryInterface(IID_ITDigitDetectionEvent, (void**)&pDigitEvent);

	unsigned char dig;
	pDigitEvent->get_Digit(&dig);

	//
	// 跟据用户不同按键选择做出不同的回应
	//
	switch (dig)
	{
	case '1':
		// 播放声音1
		m_Tapi.PreparePlay(strFileName1);
		break;
	case '2':
		// 播放声间2
		m_Tapi.PreparePlay(strFileName2);
		break;
	case '3':
		// 留言
		m_Tapi.StartRecord();
	default:
		break;
	}
	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -