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

📄 tapieventprocess.cpp

📁 语音自动应答系统源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	//
    V_VT(&varPlaylist) = VT_ARRAY | VT_VARIANT;
    V_ARRAY(&varPlaylist) = pPlayListArray;

	//
	// 最后,现在可以调用 put_PlayList 把 varPlaylist 放入到播放列表里了
	//
    hr = pMediaPlayback->put_PlayList(varPlaylist);
    if(FAILED(hr))
    {
        AfxMessageBox("PutPlayList: put_PlayList failed");
		delete pvarArrayEntry;
        return E_OUTOFMEMORY;
    }

	//
	//释放内存
	//
	delete pvarArrayEntry;
    pMediaPlayback->Release();
	VariantClear(&varPlaylist);

    return hr;
}

///////////////////////////////////////////////////////////////////
// StartRecord
//
//
// 功能:录音
// 说明:只有 WinXP 下才支持
///////////////////////////////////////////////////////////////////
HRESULT CTapi::StartRecord()
{
	HRESULT hr;
	hr = CreateAndSelectFileRecordTerminal();
	if(FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
		m_pCall->Disconnect(DC_NORMAL);
		AfxMessageBox("CreateAndSelectFileRecordTerminal failed");
		return hr;
	}

	//
	// 获得 ITMediaControl 接口 - we need to call Start
	//
	ITMediaControl* pITMC = NULL;
	hr = m_pRecordFileTerm->QueryInterface(IID_ITMediaControl, (void**)&pITMC);
	if(FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
	    AfxMessageBox("ITFileTerminalEvent, but failed to QI ITMediaControl");
		m_pCall->Disconnect(DC_NORMAL);
		return hr;
	}

	hr = pITMC->Start();
	pITMC->Release();
	if(FAILED(hr))
	{
		//
		// 致命错误 - 无法继续下去 - 切断此次通话
		//
	    AfxMessageBox("ITFileTerminalEvent, but ITMediaControl::Start");
		m_pCall->Disconnect(DC_NORMAL);
		return hr;
	}


	//
	// 录音一分钟后自动停止
	//
	SetTimer(m_hWnd,Timer_ID, Max_Rec_Time, NULL);
	m_dwMessages++;
	KillTimer(m_hWnd,Timer_ID); 
	return S_OK;
}


///////////////////////////////////////////////////////////////////
// CheckStreamMT
//
// 检测输入的 pITStream 是否支持给定的媒体类型
//
///////////////////////////////////////////////////////////////////
HRESULT CTapi::CheckStreamMT(
			IN ITStream* pITStream,
			IN long mt)
{
	long mtStream = TAPIMEDIATYPE_AUDIO;
	HRESULT hr = E_FAIL;
	if(FAILED(hr=pITStream->get_MediaType(&mtStream)))
	{
		return hr;
	}
	if(!(mt&mtStream))
	{
		return S_FALSE;
	}
	else
	{
		return S_OK;
	}
}

///////////////////////////////////////////////////////////////////
// CheckStreamDir
//
// 检测输入的 pITStream 是否有给定的媒体流方向
//
///////////////////////////////////////////////////////////////////
HRESULT CTapi::CheckStreamDir(
			IN ITStream* pITStream,
			IN TERMINAL_DIRECTION td)
{
	TERMINAL_DIRECTION tdStream = TD_CAPTURE ;
	HRESULT hr =E_FAIL;
	if(FAILED(hr=pITStream->get_Direction(&tdStream)))
	{
		return hr;
	}
	if(td!=tdStream)
	{
		return S_FALSE;
	}
	else
	{
		return S_OK;
	}
}


///////////////////////////////////////////////////////////////////
// CreateAndSelectFileRecordTerminal
//
// 功能:
// 1. 创建录音文件终端,
// 2. 并对其指定录音文件名, 
// 3. 对当前输入媒体流选择音轨终端
///////////////////////////////////////////////////////////////////
HRESULT CTapi::CreateAndSelectFileRecordTerminal()
{

	//
    // 检测当前 m_pCall 是否有效
    //
    if (NULL == m_pCall) 
    {
        AfxMessageBox("CreateAndSelectFileRecordTerminal: m_pCall 无效,可能当前没有通话");
        return E_UNEXPECTED;
    }

    //
    // 获得 ITStreamControl 接口
    //
	ITStreamControl* pStreamControl = NULL;
    HRESULT hr = m_pCall->QueryInterface( IID_ITStreamControl, (void**)&pStreamControl );
    if (FAILED(hr))
    {
        AfxMessageBox("CreateAndSelectFileRecordTerminal: QI for ITStreamControl failed");
        return E_FAIL;
    }

	//
	// 确保录音终端在这之前已经释放
	//
	if(NULL != m_pRecordFileTerm)
	{
		m_pRecordFileTerm->Release();
		m_pRecordFileTerm = NULL;
	}

    //
	// QI for ITBasicCallControl2 - 准备请求终端
	//
	ITBasicCallControl2* pITBCC2 = NULL;
    hr = m_pCall->QueryInterface( IID_ITBasicCallControl2, (void**)&pITBCC2 );
	if(FAILED(hr))
	{
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: QI for ITBasicCallControl2 failed");
		return hr;
	}

	//
	// 为 ReqestTerminal 获得 CLSID
	//
	BSTR bstrCLSID = NULL;
	hr = StringFromCLSID(CLSID_FileRecordingTerminal, &bstrCLSID);
	if(FAILED(hr))
	{
		pITBCC2->Release();
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: StringFromCLSID failed");
		return hr;
	}
	//
	// 请求录音终端,需要输入 媒体类型 和 媒体流方向
	//
	hr = pITBCC2->RequestTerminal(bstrCLSID, 
									TAPIMEDIATYPE_AUDIO, 
									TD_RENDER, 
									&m_pRecordFileTerm);
	//
	// 释放内存
	//
	::CoTaskMemFree(bstrCLSID);
	pITBCC2->Release();
	if(FAILED(hr))
	{
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: RequestTerminal failed");
		return hr;
	}

    //
	// 获得 ITMediaRecord 接口,然后可以调用 put_FileName 来指定要录音的文件名
    //
	ITMediaRecord* pITMediaRec = NULL;
    hr = m_pRecordFileTerm->QueryInterface( IID_ITMediaRecord, (void**)&pITMediaRec );
	if(FAILED(hr))
	{
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: QI ITMediaRecord failed");
		return hr;
	}

	//
	// 为受到的每一个消息建立不同的文件,一文件名后面的数字来区分
	//
	CString RecFileName;
	CString tmp;
	tmp.Format("%d.", m_dwMessages);
	RecFileName = m_RecFileName + tmp + m_RecFileExt;
	BSTR bstrFileName = RecFileName.AllocSysString();
	
	if(NULL == bstrFileName)
	{
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: SysAllocString failed");
		return E_OUTOFMEMORY;
	}

	//
	// 设置文件名
	//
	hr = pITMediaRec->put_FileName(bstrFileName);
	
	//
	// 释放内存
	//
	::SysFreeString(bstrFileName);
	pITMediaRec->Release();
	
	if(FAILED(hr))
	{
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: put_FileName failed");
		return hr;
	}

    //
    // 获得 ITMultiTrackTerminal 接口
    //
	ITMultiTrackTerminal* pMTRecTerminal = NULL;
    hr = m_pRecordFileTerm->QueryInterface( IID_ITMultiTrackTerminal, (void**)&pMTRecTerminal );
	if(FAILED(hr))
	{
		pStreamControl->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: QI IID_ITMultiTrackTerminal failed");
		return hr;
	}

    //
    // 列举所有的媒体流
    //
    IEnumStream* pEnumStreams = NULL;
    hr = pStreamControl->EnumerateStreams(&pEnumStreams);
    pStreamControl->Release();

    if (FAILED(hr))
    {
		pMTRecTerminal->Release();
		AfxMessageBox("CreateAndSelectFileRecordTerminal: EnumerateStreams failed");
		return hr;
    }

	//
	// 只处理音频媒体类型
	//
	long lMediaTypes = TAPIMEDIATYPE_AUDIO;

    //
    // 遍历媒体流,创建我们需要的
    //
	ITStream* pStream = NULL;
    while (S_OK == pEnumStreams->Next(1, &pStream, NULL))
    {
        
        if ( (S_OK==CheckStreamMT(pStream,lMediaTypes))
				&& (S_OK==CheckStreamDir(pStream,TD_RENDER))) 
        {
            //
			// 我们已经有了录音文件终端,下面要创建音轨终端
            //
            ITTerminal* pRecordingTrack = NULL;

			//
			// 检测媒体类型
			//
			long lStreamMediaType=0;
			hr = pStream->get_MediaType(&lStreamMediaType);
            if (FAILED(hr))
            {
				pStream->Release();
				pStream=NULL;
                continue;

            }

			//
			// 创建音轨终端
			//
            hr = pMTRecTerminal->CreateTrackTerminal(lStreamMediaType, TD_RENDER, &pRecordingTrack);
			if (FAILED(hr))
            {
				pStream->Release();
				pStream=NULL;
                break;
            }

            //
			// 让当前媒体流选择音轨终端
			//
			hr = pStream->SelectTerminal(pRecordingTrack);

			//
			// 释放内存
			//
			pStream->Release();
			pStream=NULL;
            pRecordingTrack->Release();
			pRecordingTrack=NULL;

            if (FAILED(hr))
            {
                break;
            }

			lMediaTypes^=lStreamMediaType;

			if(lMediaTypes==0)
			{
	            // 
				// 我们已经为所有媒体类型选择了终端,任务完成!
				//
				break;
			}


        } 
		//
		// 释放内存
		//
		if(pStream!=NULL)
		{
			pStream->Release();
			pStream = NULL;
		}

    } // while (enumerating streams on the call)


	//
	//释放内存
	//
    pMTRecTerminal->Release();
	pEnumStreams->Release();
    
	//
	// 检测我们是否已经为所有媒体选择了终端
	//
    if (lMediaTypes==0)
    {
        return S_OK;
    }
    else
    {
		AfxMessageBox("CreateAndSelectFileRecordTerminal: no streams available");
        return E_FAIL;
    }
}


///////////////////////////////////////////////////////////////////
// SameCall
//
// 检测是否与 m_pCall 是同一个
//
///////////////////////////////////////////////////////////////////
bool CTapi::SameCall(ITCallStateEvent* pCallStateEvent)
{
	if(NULL == pCallStateEvent)
	{
		return false;
	}

	//
	// 获得 Call object
	//
	ITCallInfo* pCallInfo = NULL;
	HRESULT hr = pCallStateEvent->get_Call(&pCallInfo);

	if(NULL != pCallInfo &&  ( SUCCEEDED(hr) && NULL != m_pCall) )
	{
		bool bIsEqual = true;
		//
		// 比较两个 Call object 的 IUnknown 接口
		//
		IUnknown* pIUnkCallInfo = NULL;
		IUnknown* pIUnkCallControl = NULL;
		pCallInfo->QueryInterface(IID_IUnknown, (void**)&pIUnkCallInfo);
		m_pCall->QueryInterface(IID_IUnknown, (void**)&pIUnkCallControl);
		//
		//比较
		//
		if(pIUnkCallInfo != pIUnkCallControl)
		{
			bIsEqual = false;
		}

		//
		//释放内存
		//
		pCallInfo->Release();
		if(NULL != pIUnkCallInfo)
		{
			pIUnkCallInfo->Release();
		}
		if(NULL != pIUnkCallControl)
		{
			pIUnkCallControl->Release();
		}
		return bIsEqual;
	}
	else
	{
		return false;
	}
}


//////////////////////////////////////////////////////////////////
//
// GetTerminalFromStreamEvent 
//
// 功能:从 MediaEvent 事件中获得媒体流,然后,再由媒体流获得终端
// 如果对应的终端存在,则返回 NULL
//////////////////////////////////////////////////////////////////
HRESULT CTapi::GetTerminalFromStreamEvent( 
			IN ITCallMediaEvent * pCallMediaEvent,
            OUT ITTerminal ** ppTerminal )
{
    HRESULT hr;

	*ppTerminal = NULL;
    //
    // 获得这一事件当中的媒体流
    //
    ITStream * pStream;
    hr = pCallMediaEvent->get_Stream( &pStream );
    if ( FAILED(hr) || (pStream == NULL) ) return E_FAIL;

    //
    // 列举支持这一种媒体流的终端
    //
    IEnumTerminal * pEnumTerminal;
    hr = pStream->EnumerateTerminals( &pEnumTerminal );
    pStream->Release();
    if ( FAILED(hr) ) return hr;

    //
	// 获得第一个终端,如果没有找到,返回 E_FAIL 跳出这一事件的处理
    //
    hr = pEnumTerminal->Next(1, ppTerminal, NULL);
    if ( hr != S_OK )
    {
        pEnumTerminal->Release();
        return E_FAIL;
    }

    //
	// 进一步检测,注意这里不可能有大于一个终端,因为我们对每一各媒体流只选择
	// 过一个终端
    //

    ITTerminal * pExtraTerminal;
    hr = pEnumTerminal->Next(1, &pExtraTerminal, NULL);
    pEnumTerminal->Release();

    if ( hr == S_OK ) // 大于一个终端,不可能出现的情况
    {
        pExtraTerminal->Release();
        (*ppTerminal)->Release();
        *ppTerminal = NULL;
        return E_UNEXPECTED;
    }

    return S_OK;
}



⌨️ 快捷键说明

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