/*
* WengoPhone, a voice over Internet phone
* Copyright (C) 2004-2006 Wengo
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//#include "IWebcamDriver.h"
#include "DirectXWebcamDriver.h"
#include "pixertool/directx-pixertool.h"
//#include <list>
//#include <string>
#include <comutil.h>
#pragma comment(lib, "comsupp.lib")
//#include <util/Logger.h>
using namespace std;
#define SAFE_RELEASE_POINTER(x) { if (x) x->Release(); x = NULL; }
#define SAFE_RELEASE(x) { if (x) x.Release(); x = NULL; }
//CComBSTR aaa("aaa");
HRESULT AddDevicesToList(HWND hlist)
{
HRESULT hr;
//create an enumerator
CComPtr<ICreateDevEnum> pCreateDevEnum;
pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum);
if ( !pCreateDevEnum)
{
return S_FALSE;
}
//enumerate video capture devices
CComPtr<IEnumMoniker > pEnumMoniker;
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
if (!pEnumMoniker)
{
return S_FALSE;
}
pEnumMoniker->Reset();
//go through and find all video capture device(s)
ULONG cFetched;
IMoniker *pM;
while (hr = pEnumMoniker->Next(1, &pM, &cFetched), hr == S_OK)
{
CComPtr<IPropertyBag> pBag;
hr = pM->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)
{
USES_CONVERSION;
if (hlist)
::SendMessage(hlist, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>((LPCTSTR)W2T(var.bstrVal)));
SysFreeString( var.bstrVal);
}
}
pM->Release();
}
if (hlist)
::SendMessage(hlist, CB_SETCURSEL, 0, 0);
return S_OK;
}
HRESULT AddDevicesToList(std::list<std::wstring>& cam_list)
{
HRESULT hr;
std::wstring strCamDevice =L"";
//create an enumerator
CComPtr<ICreateDevEnum> pCreateDevEnum;
pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum);
if ( !pCreateDevEnum)
{
return S_FALSE;
}
//enumerate video capture devices
CComPtr<IEnumMoniker > pEnumMoniker;
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
if (!pEnumMoniker)
{
return S_FALSE;
}
pEnumMoniker->Reset();
//go through and find all video capture device(s)
ULONG cFetched;
IMoniker *pM;
while (hr = pEnumMoniker->Next(1, &pM, &cFetched), hr == S_OK)
{
CComPtr<IPropertyBag> pBag;
hr = pM->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)
{
USES_CONVERSION;
strCamDevice= (LPCTSTR)W2T(var.bstrVal);
SysFreeString( var.bstrVal);
cam_list.push_back(strCamDevice);
}
}
pM->Release();
}
return S_OK;
}
HRESULT FindMyCaptureDevice (IBaseFilter **pF, BSTR bstrName)
{
HRESULT hr= E_FAIL;
CComPtr< IBaseFilter > pFilter;
CComPtr<ICreateDevEnum > pSysDevEnum;
CComPtr<IEnumMoniker> pEnumCat = NULL;
//create the system enumerator
pSysDevEnum.CoCreateInstance (CLSID_SystemDeviceEnum);
if (!pSysDevEnum)
{
return E_FAIL;
}
//Obtain a class enumerator for the video compressor category
pSysDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
if (!pEnumCat )
{
return E_FAIL;
}
pEnumCat->Reset();
while (true) {
CComPtr <IMoniker > pMoniker;
ULONG cFetched;
CComPtr<IPropertyBag > pProp;
HRESULT hr_work = pEnumCat->Next (1, &pMoniker, &cFetched);
if (hr_work != S_OK)
{
break;
}
hr = pMoniker->BindToStorage (0, 0, IID_IPropertyBag, (void **)&pProp);
if (hr != S_OK)
{
continue;
}
VARIANT varName;
VariantInit( &varName);
hr = pProp->Read (L"FriendlyName", &varName, 0);
if (SUCCEEDED (hr) && wcscmp (bstrName, varName.bstrVal) == 0) {
hr = pMoniker->BindToObject (0, 0, IID_IBaseFilter, (void **)& pFilter);
break;
}
VariantClear( &varName);
pMoniker = NULL; //Release for the next loop;
}
if ( pFilter) {
*pF = pFilter;
(*pF)->AddRef(); //add ref on the way out.
}
return hr;
}
IAMStreamConfig *GetIAMStreamConfig (IBaseFilter * pFilter)
{
IEnumPins *pEnum= NULL;
HRESULT hr = pFilter->EnumPins(&pEnum);
if ( FAILED (hr))
return NULL;
IPin *pPin= NULL;
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
IAMStreamConfig *pIAMS = NULL;
hr = pPin->QueryInterface (IID_IAMStreamConfig, (void **)&pIAMS);
if ( SUCCEEDED (hr) )
{
return pIAMS;
}
pPin->Release();
}
pEnum->Release();
return NULL;
}
DirectXWebcamDriver::DirectXWebcamDriver(int flags,int nWidth,int nHeight)
: IWebcamDriver(flags)
{
Init();
_desiredWidth= nWidth;
_desiredHeight = nHeight;
_hSharedMemoryReadThread = NULL;
_hSharedMemoryReadFile = NULL;
_hSharedMemoryWriteFile = NULL;
_hSharedMemoryLock = NULL;
_isStartCaptured = FALSE;
}
DirectXWebcamDriver::~DirectXWebcamDriver()
{
UnInit();
}
void DirectXWebcamDriver::Init()
{
//FIXME does not work because of Qt4.1.2
//CoInitializeEx(NULL, COINIT_MULTITHREADED);
CoInitialize(NULL);
_isOpen = false;
_isCaptureGraphBuild = false;
_isRunning =false;
//_webcamDriver = driver;
_pGrabberF = NULL;
_pGrabber = NULL;
_pNu