c++ 采集c++用derictshow 采集核心部分代码, 看不太懂,贴上来慢慢看// LivePlayer.cpp: implementation of
c++ 采集
c++用derictshow 采集核心部分代码, 看不太懂,贴上来慢慢看
// LivePlayer.cpp: implementation of the LivePlayer class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "LivePlayer.h"#include "mmsystem.h"//#include <qedit.h>BOOL bDeviceFound = FALSE;/*deinterlace 改为vmr7 模式wzj*///#define _VMR9_MODE//////////////////////////////////////////////////////////////////////// Construction/Destruction////////////////////////////////////////////////////////////////////// IVideoWindow * m_pVW=NULL; IMediaControl * m_pMC=NULL; IMediaEventEx * m_pME=NULL; IGraphBuilder * m_pGraph=NULL; ICaptureGraphBuilder2 * m_pCapture;LivePlayer::LivePlayer(){m_nStatus = Status_None;m_pVW = NULL;m_pMC = NULL;m_pME = NULL;m_pGraph = NULL;m_pCapture = NULL;}LivePlayer::~LivePlayer(){ReleaseDC(m_hWnd,m_hDC);}CString GetNow(){CTime ct = CTime::GetCurrentTime();return ct.Format("%Y-%m-%d %H:%M:%S");}ATOM LivePlayer::RegisterWindowClass(){WNDCLASSEX wcex; // Register the window classwcex.cbSize = sizeof(WNDCLASSEX);wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc = WndMainProc;wcex.cbClsExtra= 0;wcex.cbWndExtra= 0; wcex.hInstance = GetModuleHandle(NULL); wcex.lpszClassName = "_VideoCaptureClass"; wcex.lpszMenuName = NULL; wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hIcon = NULL;wcex.hIconSm= NULL;wcex.lpszMenuName= NULL; if(!RegisterClassEx(&wcex)) {//CoUninitialize();return 0; }return 1;//reg ok}LRESULT LivePlayer::MessageProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ switch (message) {case WM_TIMER:m_CurrentElement->nElapse--;if(m_CurrentElement->nElapse<= 0){if(PlayNext(m_CurrentElement->NextElement) == 1)//结束播放{//return 0;}}break;case WM_GRAPHNOTIFY:HandleGraphEvent();break;case WM_SIZE:ResizeVideoWindow();break;case WM_CLOSE:CloseInterfaces();break;case WM_RBUTTONUP:// PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam ); } // Pass this message to the video window for notification of system changes if (m_pVW) m_pVW->NotifyOwnerMessage((LONG_PTR) hWnd, message, wParam, lParam); return DefWindowProc (hWnd , message, wParam, lParam);}LRESULT CALLBACK LivePlayer::WndMainProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){LivePlayer* pLivePlayer = (LivePlayer*)GetWindowLong(hWnd,GWL_USERDATA);if(!IsBadReadPtr(pLivePlayer,sizeof(LivePlayer*))){return pLivePlayer->MessageProc(hWnd, message, wParam, lParam );}else{return DefWindowProc(hWnd, message, wParam, lParam );}}HRESULT LivePlayer::HandleGraphEvent(void){ LONG evCode, evParam1, evParam2; HRESULT hr=S_OK; if (!m_pME) return E_POINTER; while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1, (LONG_PTR *) &evParam2, 0))) { // // Free event parameters to prevent memory leaks associated with // event parameter data. While this application is not interested // in the received events, applications should always process them. // hr = m_pME->FreeEventParams(evCode, evParam1, evParam2); // Insert event processing code here, if desired } return hr;}HWND LivePlayer::CreatePlayer(int x,int y,int width,int height){ m_hWnd = CreateWindowEx(WS_EX_TOOLWINDOW,"_VideoCaptureClass","",WS_POPUP,x,y,width,height,NULL,NULL,GetModuleHandle(NULL),NULL);ASSERT(m_hWnd);SetWindowLong(m_hWnd,GWL_USERDATA,(long)this);m_hDC = GetDC(m_hWnd);SetStretchBltMode(m_hDC, HALFTONE);SetBrushOrgEx(m_hDC, 0,0, NULL);return m_hWnd;}long LivePlayer::Play(){ASSERT(m_hWnd);m_playTime = CTime::GetCurrentTime();SetTimer(m_hWnd,TIMER_COUNT,1000,NULL);if(m_nStatus == Status_Pause){if (m_pMC)m_pMC->Run();}else{HRESULT hr;ShowWindow(m_hWnd,SW_SHOW);hr = CaptureVideo();if (m_CurrentElement->nSwitchType == 1) //matrtix{if((m_CurrentElement->ElementInput <= 11) && (m_CurrentElement->ElementInput>=0))SendAscal_C2700(g_Matrix_TV1_C2_7000_Input_List[m_CurrentElement->ElementInput],atoi(MatrixOutputWindow));}}// Dicky 20120515SetMute(0);return 0;}long LivePlayer::PlayNext(ElementInfo* pNextElement){if(m_CurrentElement->NextElement == m_FirstElement){int nRet;nRet = playStatusCallBack((long)this,NULL,NULL,PlayStatus_LoopEnd,PlayLogLevel_Simple,"End a loop",&g_PluginType);if(nRet != PlayControl_Next) return 1;}if(pNextElement == m_CurrentElement){m_CurrentElement->nElapse = m_CurrentElement->nDuration;return 0;}//if need to switch//if deviceif(pNextElement->nSwitchType == 0){if(pNextElement->ElementName != m_CurrentElement->ElementName){Stop();m_CurrentElement = pNextElement;pNextElement->nElapse = pNextElement->nDuration;Play();}else{m_CurrentElement = pNextElement;pNextElement->nElapse = pNextElement->nDuration;}}//if matrix.if (pNextElement->nSwitchType == 1) //matrtix{if((pNextElement->ElementInput <= 11) && (pNextElement->ElementInput>=0)){SendAscal_C2700(g_Matrix_TV1_C2_7000_Input_List[pNextElement->ElementInput],atoi(MatrixOutputWindow));CString strSource;strSource.Format("Matrix Input %d,Code is:%d",pNextElement->ElementInput,g_Matrix_TV1_C2_7000_Input_List[pNextElement->ElementInput]);playStatusCallBack((long)this,(char*)(LPCSTR)m_playTime.Format("%Y-%m-%d %H:%M:%S"),(CC)GetNow(),PlayStatus_Play,PlayLogLevel_Simple,(CC)strSource,&g_PluginType);}}return 0;}long LivePlayer::Stop(){KillTimer(m_hWnd,TIMER_COUNT);playStatusCallBack((long)this,(char*)(LPCSTR)m_playTime.Format("%Y-%m-%d %H:%M:%S"),NULL,PlayStatus_Stop,PlayLogLevel_Simple,(char*)(LPCSTR)m_CurrentElement->ElementName,&g_PluginType);m_playTime = CTime::GetCurrentTime();CloseInterfaces();m_nStatus = Status_Stop;//Dicky 20120515SetMute(1);return 0;}long LivePlayer::Pause(){ if (m_pMC)m_pMC->Pause();m_nStatus = Status_Pause;KillTimer(m_hWnd,TIMER_COUNT);//Dicky 20120515SetMute(1);return 0;}HRESULT LivePlayer::GetInterfaces(void){ HRESULT hr; // Create the filter graph hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IGraphBuilder, (void **) &m_pGraph); if (FAILED(hr)) return hr; // Create the capture graph builder hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,IID_ICaptureGraphBuilder2, (void **) &m_pCapture); if (FAILED(hr)) return hr; // Obtain interfaces for media control and Video Window hr = m_pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &m_pMC); if (FAILED(hr)) return hr; hr = m_pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW); if (FAILED(hr)) return hr; hr = m_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) &m_pME); if (FAILED(hr)) return hr;//Set the window handle used to process graph events//hr = m_pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0); return hr;}void LivePlayer::CloseInterfaces(void){ // Stop previewing data if (m_pMC)// g_pMC->StopWhenReady();m_pMC->StopWhenReady(); // Stop receiving events if (m_pME) m_pME->SetNotifyWindow(NULL, WM_GRAPHNOTIFY, 0); // Relinquish ownership (IMPORTANT!) of the video window. // Failing to call put_Owner can lead to assert failures within // the video renderer, as it still assumes that it has a valid // parent window. if(m_pVW) { m_pVW->put_Visible(OAFALSE); m_pVW->put_Owner(NULL); } // Release DirectShow interfaces SAFE_RELEASE(m_pMC); SAFE_RELEASE(m_pME); SAFE_RELEASE(m_pVW); SAFE_RELEASE(m_pGraph); SAFE_RELEASE(m_pCapture);}void LivePlayer::MyFreeMediaType(AM_MEDIA_TYPE& mt){ if (mt.cbFormat != 0) { CoTaskMemFree((PVOID)mt.pbFormat); mt.cbFormat = 0; mt.pbFormat = NULL; } if (mt.pUnk != NULL) { // Unecessary because pUnk should not be used, but safest. mt.pUnk->Release(); mt.pUnk = NULL; }}HRESULT LivePlayer::ApplySetting(IBaseFilter * ppSrcFilter){IAMStreamConfig *pConfig;HRESULT hr;hr = m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,ppSrcFilter,IID_IAMStreamConfig,(void **)&pConfig);if( hr != NOERROR )hr = m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,ppSrcFilter,IID_IAMStreamConfig,(void **)&pConfig);if(hr == NOERROR){AM_MEDIA_TYPE *pmt; if(pConfig->GetFormat(&pmt) == S_OK) { // DV capture does not use a VIDEOINFOHEADERif(pmt->formattype == FORMAT_VideoInfo){VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;pvi->bmiHeader.biBitCount=24;if((strcmp(DeviceName,"Decklink Video Capture 01") == 0 ) && bDeviceFound){//MessageBox(0,0,DeviceName,0);}else if((strcmp(DeviceName,"Datapath VisionSD4+1 01") == 0 ) && bDeviceFound){//pvi->bmiHeader.biWidth = 1920; //pvi->bmiHeader.biHeight = 1080;}else if((strcmp(DeviceName,"Datapath VisionRGB-E1") == 0 ) && bDeviceFound){ //pvi->bmiHeader.biWidth = 1920; //pvi->bmiHeader.biHeight = 1080;}else if((strcmp(DeviceName,"Datapath VisionRGB-E1 01") == 0 ) && bDeviceFound){//pvi->bmiHeader.biWidth = 1920;//pvi->bmiHeader.biHeight = 1080;}else if((strcmp(DeviceName,"Datapath VisionRGB-E2 01") == 0 ) && bDeviceFound){//pvi->bmiHeader.biWidth = 1920;//pvi->bmiHeader.biHeight = 1080;}else{pvi->bmiHeader.biWidth = 360;//360;pvi->bmiHeader.biHeight = 288;//288;IAMAnalogVideoDecoder *m_pDecoder; ppSrcFilter->QueryInterface(IID_IAMAnalogVideoDecoder,(void **)&m_pDecoder);if(!m_pDecoder) return 0;int nSignalFormat = 0;switch(nSignalFormat){case 0:m_pDecoder->put_TVFormat(AnalogVideo_PAL_D);break;case 1:m_pDecoder->put_TVFormat(AnalogVideo_NTSC_M);break;case 2:m_pDecoder->put_TVFormat(AnalogVideo_SECAM_D);break;default :m_pDecoder->put_TVFormat(AnalogVideo_PAL_D);break;}SAFE_RELEASE(m_pDecoder);}hr = pConfig->SetFormat(pmt);}}MyFreeMediaType(*pmt); }SAFE_RELEASE(pConfig);return hr;}HRESULT LivePlayer::FindCaptureDevice(IBaseFilter ** ppSrcFilter){ HRESULT hr; IBaseFilter * pSrc = NULL; CComPtr <IMoniker> pMoniker =NULL; ULONG cFetched; if (!ppSrcFilter) return E_POINTER; // Create the system device enumerator ICreateDevEnum* pDevEnum =NULL; hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,IID_ICreateDevEnum, (void **) &pDevEnum); if (FAILED(hr)) { return hr; } // Create an enumerator for the video capture devices CComPtr <IEnumMoniker> pClassEnum = NULL; hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0); if (FAILED(hr)) { return hr; } // If there are no enumerators for the requested type, then // CreateClassEnumerator will succeed, but pClassEnum will be NULL. if (pClassEnum == NULL) { return E_FAIL; } // Use the first video capture device on the device list. // Note that if the Next() call succeeds but there are no monikers, // it will return S_FALSE (which is not a failure). Therefore, we // check that the return code is S_OK instead of using SUCCEEDED() macro./* Dicky remove this segment and resume the next right one This one can't play 2nd input Vision4+1, resume one can play again if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched))) { // Bind Moniker to a filter object hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc); if (FAILED(hr)) { return hr; } } else { return E_FAIL; }*/while(hr = pClassEnum->Next(1, &pMoniker, &cFetched), hr==S_OK){IPropertyBag *pBag;hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);if(SUCCEEDED(hr)) {VARIANT var;var.vt = VT_BSTR;hr = pBag->Read(L"FriendlyName", &var, NULL);if (hr == NOERROR) {CString strDeviceName;USES_CONVERSION;strDeviceName = W2T(var.bstrVal);playStatusCallBack((long)this,NULL,NULL,PlayStatus_None,PlayLogLevel_Professional,(char*)(LPCSTR)strDeviceName,NULL);strDeviceName.MakeLower();if (m_CurrentElement->ElementName == strDeviceName){pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc);bDeviceFound = TRUE;break;}SysFreeString(var.bstrVal);}pBag->Release();}}CString strInfo;if(bDeviceFound == FALSE){ pClassEnum->Reset();if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched))){// Bind Moniker to a filter objecthr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);if (FAILED(hr)){return hr;}}else{strInfo.Format("Device Not Found:%s use the default video capture failed",m_CurrentElement->ElementName);playStatusCallBack((long)this,NULL,NULL,PlayStatus_None,PlayLogLevel_Professional,(char*)(LPCSTR)strInfo,NULL);return E_FAIL;}strInfo.Format("\r\nDevice Not Found:%s,\r\nuse the default video capture successed",m_CurrentElement->ElementName);playStatusCallBack((long)this,NULL,NULL,PlayStatus_None,PlayLogLevel_Professional,(char*)(LPCSTR)strInfo,NULL);}else{strInfo.Format("Device Found:%s",m_CurrentElement->ElementName);playStatusCallBack((long)this,NULL,NULL,PlayStatus_None,PlayLogLevel_Professional,(char*)(LPCSTR)strInfo,NULL);}//deinterlace/*ISampleGrabber* m_pGrabber; hr = m_pGraph->AddFilter(pSrc, L"Capture Filter"); hr = CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void**)&m_pGrabber ); CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase(m_pGrabber); //设置视频格式 AM_MEDIA_TYPE mt; ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));mt.majortype = MEDIATYPE_Video;mt.subtype = MEDIASUBTYPE_RGB24; hr = m_pGrabber->SetMediaType(&mt); hr = m_pGraph->AddFilter( pGrabBase, L"Grabber" ); hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,pSrc,pGrabBase,NULL); if( FAILED(hr)) hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pSrc,pGrabBase,NULL); hr = m_pGrabber->GetConnectedMediaType( &mt ); mt.formattype = FORMAT_VideoInfo2; VIDEOINFOHEADER2 * vih = (VIDEOINFOHEADER2*) mt.pbFormat; vih->dwInterlaceFlags = AMINTERLACE_IsInterlaced | AMINTERLACE_DisplayModeBobOrWeave; hr = m_pGrabber->SetMediaType(&mt); hr = m_pGrabber->GetConnectedMediaType( &mt ); if (mt.cbFormat != 0) {CoTaskMemFree((PVOID)mt.pbFormat); mt.cbFormat = 0;mt.pbFormat = NULL;} if (mt.pUnk != NULL) { mt.pUnk->Release();mt.pUnk = NULL;}MyFreeMediaType(mt); IAMStreamConfig *pConfig; hr = m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,pSrc,IID_IAMStreamConfig,(void **)&pConfig); AM_MEDIA_TYPE *pmt; if( hr != NOERROR ) {hr = m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pSrc,IID_IAMStreamConfig,(void **)&pConfig); }{ pmt->formattype = FORMAT_VideoInfo2;if(pmt->formattype == FORMAT_VideoInfo2) { MessageBox(0,"Support",0,0);VIDEOINFOHEADER2 * pVI2; pVI2 = (VIDEOINFOHEADER2 *)pmt->pbFormat; if (pmt->cbFormat != 0) {CoTaskMemFree((PVOID)pmt->pbFormat);pmt->cbFormat = 0; pmt->pbFormat = NULL;}if (pmt->pUnk != NULL) {pmt->pUnk->Release(); pmt->pUnk = NULL; }pVI2->dwInterlaceFlags = AMINTERLACE_IsInterlaced | AMINTERLACE_DisplayModeBobOrWeave; pmt->pbFormat = (BYTE*)pVI2; hr = pConfig->SetFormat(pmt); }elseMessageBox(0,"UnSupport",0,0);} MyFreeMediaType(*pmt); // Copy the found filter pointer to the output parameter. // Do NOT Release() the reference, since it will still be used // by the calling function.*/*ppSrcFilter = pSrc; return hr;}void LivePlayer::ResizeVideoWindow(void){ // Resize the video preview window to match owner window size if (m_pVW) { RECT rc; // Make the preview video fill our window GetClientRect(m_hWnd, &rc); m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom); }}HRESULT LivePlayer::SetupVideoWindow(void){ HRESULT hr; // Set the video window to be a child of the main window hr = m_pVW->put_Owner((OAHWND)m_hWnd); if (FAILED(hr)) return hr; // Set video window style hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); if (FAILED(hr)) return hr; // Use helper function to position video window in client rect // of main application window ResizeVideoWindow(); // Make the video window visible, now that it is properly positioned hr = m_pVW->put_Visible(OATRUE); if (FAILED(hr)) return hr; return hr;}HRESULT LivePlayer::CaptureVideo(){ HRESULT hr; IBaseFilter *pSrcFilter=NULL; // Get DirectShow interfaces hr = GetInterfaces();if (FAILED(hr)){return hr;} hr = m_pCapture->SetFiltergraph(m_pGraph);if (FAILED(hr)){return hr;} hr = FindCaptureDevice(&pSrcFilter);//if (FAILED(hr)){return hr;} hr = m_pGraph->AddFilter(pSrcFilter, L"Video Capture");if (FAILED(hr)){pSrcFilter->Release();return hr;}#ifdef _VMR9_MODEIBaseFilter *pVMR9=NULL; hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&pVMR9); if (SUCCEEDED(hr)) hr = m_pGraph->AddFilter(pVMR9, L"Video Mixing Render 9"); hr = m_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW , &MEDIATYPE_Video,pSrcFilter, NULL, pVMR9);SAFE_RELEASE(pVMR9);#elsehr = m_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW , &MEDIATYPE_Video,pSrcFilter, NULL, NULL);#endifApplySetting(pSrcFilter); pSrcFilter->Release();hr = SetupVideoWindow();if (FAILED(hr)){return hr;} hr = m_pMC->Run();if (FAILED(hr)){return hr;} return S_OK;}IPin* LivePlayer::FindPin(IBaseFilter *pFilter, PIN_DIRECTION dir){IEnumPins* pEnumPins;IPin* pOutpin;PIN_DIRECTION pDir;pFilter->EnumPins(&pEnumPins);while (pEnumPins->Next(1,&pOutpin,NULL)==S_OK){pOutpin->QueryDirection(&pDir);if (pDir==dir){return pOutpin;}}return 0;}/* 设定音量*/bool LivePlayer::GetVolumeControl(HMIXER hmixer ,long componentType,long ctrlType,MIXERCONTROL* mxc){MIXERLINECONTROLS mxlc;MIXERLINE mxl;bool exist = false;mxl.cbStruct = sizeof(mxl);mxl.dwComponentType = componentType;if (componentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE){//获取录音麦克风设备 mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; // 得到录制总线中的连接数 mixerGetLineInfo( (HMIXEROBJ)hmixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); // 将连接数保存 DWORD dwConnections = mxl.cConnections; // 准备获取麦克风设备的ID DWORD dwLineID = 0; for ( DWORD i = 0; i < dwConnections; i++ ) { // 枚举每一个设备,当Source的ID等于当前的迭代记数 mxl.dwSource = i; // 根据SourceID获得连接的信息 MMRESULT mr = mixerGetLineInfo( (HMIXEROBJ)hmixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE ); // 判断函数执行错误 if ( mr != 0 ) { break; } // 如果当前设备类型是麦克风,则跳出循环。 if ( mxl.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE ) { exist = true; break; } } }else if(!mixerGetLineInfo((HMIXEROBJ)hmixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE)){ exist = true;}if (exist){ mxlc.cbStruct = sizeof(mxlc); mxlc.dwLineID = mxl.dwLineID; mxlc.dwControlType = ctrlType; mxlc.cControls = 1; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = mxc; if(mixerGetLineControls((HMIXEROBJ)hmixer,&mxlc,MIXER_GETLINECONTROLSF_ONEBYTYPE)) return 0; else return 1;}return 0;}bool LivePlayer::SetMuteValue(HMIXER hmixer ,MIXERCONTROL *mxc, bool mute){MIXERCONTROLDETAILS mxcd;MIXERCONTROLDETAILS_BOOLEAN mxcdMute;mxcdMute.fValue=mute;mxcd.hwndOwner = 0;mxcd.dwControlID = mxc->dwControlID;mxcd.cbStruct = sizeof(mxcd);mxcd.cbDetails = sizeof(mxcdMute);mxcd.paDetails = &mxcdMute;mxcd.cChannels = 1;mxcd.cMultipleItems = 0;if (mixerSetControlDetails((HMIXEROBJ)hmixer, &mxcd, MIXER_OBJECTF_HMIXER|MIXER_SETCONTROLDETAILSF_VALUE)) return 0;return 1;}/* WINAPI 设置设备静音 Dicky 20120515 dev =0,1,2,3 分别表示主音量,波形,MIDI ,LINE IN vol =0,1 分别表示取消静音,设置静音*/ bool LivePlayer::SetMute(bool vol){long device=MIXERLINE_COMPONENTTYPE_SRC_LINE;bool rc=false;MIXERCONTROL volCtrl;HMIXER hmixer;if(mixerOpen(&hmixer, 0, 0, 0, 0)) return 0;if(GetVolumeControl(hmixer,device,MIXERCONTROL_CONTROLTYPE_MUTE,&volCtrl))if(SetMuteValue(hmixer,&volCtrl,(bool)vol))rc=true;mixerClose(hmixer);return rc;} 