?? tapieventprocess.cpp
字號:
//
V_VT(&varPlaylist) = VT_ARRAY | VT_VARIANT;
V_ARRAY(&varPlaylist) = pPlayListArray;
//
// 最后,現(xiàn)在可以調(diào)用 put_PlayList 把 varPlaylist 放入到播放列表里了
//
hr = pMediaPlayback->put_PlayList(varPlaylist);
if(FAILED(hr))
{
AfxMessageBox("PutPlayList: put_PlayList failed");
delete pvarArrayEntry;
return E_OUTOFMEMORY;
}
//
//釋放內(nèi)存
//
delete pvarArrayEntry;
pMediaPlayback->Release();
VariantClear(&varPlaylist);
return hr;
}
///////////////////////////////////////////////////////////////////
// StartRecord
//
//
// 功能:錄音
// 說明:只有 WinXP 下才支持
///////////////////////////////////////////////////////////////////
HRESULT CTapi::StartRecord()
{
HRESULT hr;
hr = CreateAndSelectFileRecordTerminal();
if(FAILED(hr))
{
//
// 致命錯誤 - 無法繼續(xù)下去 - 切斷此次通話
//
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))
{
//
// 致命錯誤 - 無法繼續(xù)下去 - 切斷此次通話
//
AfxMessageBox("ITFileTerminalEvent, but failed to QI ITMediaControl");
m_pCall->Disconnect(DC_NORMAL);
return hr;
}
hr = pITMC->Start();
pITMC->Release();
if(FAILED(hr))
{
//
// 致命錯誤 - 無法繼續(xù)下去 - 切斷此次通話
//
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. 創(chuàng)建錄音文件終端,
// 2. 并對其指定錄音文件名,
// 3. 對當(dāng)前輸入媒體流選擇音軌終端
///////////////////////////////////////////////////////////////////
HRESULT CTapi::CreateAndSelectFileRecordTerminal()
{
//
// 檢測當(dāng)前 m_pCall 是否有效
//
if (NULL == m_pCall)
{
AfxMessageBox("CreateAndSelectFileRecordTerminal: m_pCall 無效,可能當(dāng)前沒有通話");
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;
}
//
// 確保錄音終端在這之前已經(jīng)釋放
//
if(NULL != m_pRecordFileTerm)
{
m_pRecordFileTerm->Release();
m_pRecordFileTerm = NULL;
}
//
// QI for ITBasicCallControl2 - 準(zhǔn)備請求終端
//
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);
//
// 釋放內(nèi)存
//
::CoTaskMemFree(bstrCLSID);
pITBCC2->Release();
if(FAILED(hr))
{
pStreamControl->Release();
AfxMessageBox("CreateAndSelectFileRecordTerminal: RequestTerminal failed");
return hr;
}
//
// 獲得 ITMediaRecord 接口,然后可以調(diào)用 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;
}
//
// 為受到的每一個消息建立不同的文件,一文件名后面的數(shù)字來區(qū)分
//
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;
}
//
// 設(shè)置文件名
//
hr = pITMediaRec->put_FileName(bstrFileName);
//
// 釋放內(nèi)存
//
::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;
//
// 遍歷媒體流,創(chuàng)建我們需要的
//
ITStream* pStream = NULL;
while (S_OK == pEnumStreams->Next(1, &pStream, NULL))
{
if ( (S_OK==CheckStreamMT(pStream,lMediaTypes))
&& (S_OK==CheckStreamDir(pStream,TD_RENDER)))
{
//
// 我們已經(jīng)有了錄音文件終端,下面要創(chuàng)建音軌終端
//
ITTerminal* pRecordingTrack = NULL;
//
// 檢測媒體類型
//
long lStreamMediaType=0;
hr = pStream->get_MediaType(&lStreamMediaType);
if (FAILED(hr))
{
pStream->Release();
pStream=NULL;
continue;
}
//
// 創(chuàng)建音軌終端
//
hr = pMTRecTerminal->CreateTrackTerminal(lStreamMediaType, TD_RENDER, &pRecordingTrack);
if (FAILED(hr))
{
pStream->Release();
pStream=NULL;
break;
}
//
// 讓當(dāng)前媒體流選擇音軌終端
//
hr = pStream->SelectTerminal(pRecordingTrack);
//
// 釋放內(nèi)存
//
pStream->Release();
pStream=NULL;
pRecordingTrack->Release();
pRecordingTrack=NULL;
if (FAILED(hr))
{
break;
}
lMediaTypes^=lStreamMediaType;
if(lMediaTypes==0)
{
//
// 我們已經(jīng)為所有媒體類型選擇了終端,任務(wù)完成!
//
break;
}
}
//
// 釋放內(nèi)存
//
if(pStream!=NULL)
{
pStream->Release();
pStream = NULL;
}
} // while (enumerating streams on the call)
//
//釋放內(nèi)存
//
pMTRecTerminal->Release();
pEnumStreams->Release();
//
// 檢測我們是否已經(jīng)為所有媒體選擇了終端
//
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;
}
//
//釋放內(nèi)存
//
pCallInfo->Release();
if(NULL != pIUnkCallInfo)
{
pIUnkCallInfo->Release();
}
if(NULL != pIUnkCallControl)
{
pIUnkCallControl->Release();
}
return bIsEqual;
}
else
{
return false;
}
}
//////////////////////////////////////////////////////////////////
//
// GetTerminalFromStreamEvent
//
// 功能:從 MediaEvent 事件中獲得媒體流,然后,再由媒體流獲得終端
// 如果對應(yīng)的終端存在,則返回 NULL
//////////////////////////////////////////////////////////////////
HRESULT CTapi::GetTerminalFromStreamEvent(
IN ITCallMediaEvent * pCallMediaEvent,
OUT ITTerminal ** ppTerminal )
{
HRESULT hr;
*ppTerminal = NULL;
//
// 獲得這一事件當(dāng)中的媒體流
//
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;
}
//
// 進(jìn)一步檢測,注意這里不可能有大于一個終端,因為我們對每一各媒體流只選擇
// 過一個終端
//
ITTerminal * pExtraTerminal;
hr = pEnumTerminal->Next(1, &pExtraTerminal, NULL);
pEnumTerminal->Release();
if ( hr == S_OK ) // 大于一個終端,不可能出現(xiàn)的情況
{
pExtraTerminal->Release();
(*ppTerminal)->Release();
*ppTerminal = NULL;
return E_UNEXPECTED;
}
return S_OK;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -