windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/msvidctl/devices.h
2020-09-26 16:20:57 +08:00

380 lines
11 KiB
C++

//==========================================================================;
//
// Devices.h : Declaration of the CDevices
// Copyright (c) Microsoft Corporation 1999.
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef DEVICES_H_
#define DEVICES_H_
#include <vector>
#include <objectwithsiteimplsec.h>
#include "devseq.h"
#if 0
#define DEBUGREGISTRY
#endif
#ifdef DEBUGREGISTRY
#include <statreg.h>
#endif
void CtorStaticVWDevicesFwdSeqPMFs(void);
void DtorStaticVWDevicesFwdSeqPMFs(void);
template<class DEVICETYPECOLLECTIONINTERFACE,
class DEVICETYPEINTERFACE,
const CLSID* DEVICETYPE_CLSID,
int IDSPROGID,
int IDSDESC> class CTypedDevices;
template<class DEVICETYPECOLLECTIONINTERFACE, class DEVICETYPEINTERFACE, const CLSID* DEVICETYPE_CLSID, int IDSPROGID, int IDSDESC> class ATL_NO_VTABLE CTypedDevicesBase :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTypedDevices<DEVICETYPECOLLECTIONINTERFACE, DEVICETYPEINTERFACE, DEVICETYPE_CLSID, IDSPROGID, IDSDESC>, DEVICETYPE_CLSID>,
public ISupportErrorInfo,
public IObjectWithSiteImplSec<CTypedDevicesBase>,
public IDispatchImpl<DEVICETYPECOLLECTIONINTERFACE, &__uuidof(DEVICETYPECOLLECTIONINTERFACE), &LIBID_MSVidCtlLib>
{
public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CTypedDevicesBase)
COM_INTERFACE_ENTRY(DEVICETYPECOLLECTIONINTERFACE)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectWithSite)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
BEGIN_CATEGORY_MAP(CTypedDevicesBase)
IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
IMPLEMENTED_CATEGORY(CATID_PersistsToPropertyBag)
END_CATEGORY_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
{
static const IID* arr[] =
{
&__uuidof(DEVICETYPECOLLECTIONINTERFACE)
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
virtual ~CTypedDevicesBase() {}
};
class CDevEnum;
/////////////////////////////////////////////////////////////////////////////
// CTypedDevices
template<class DEVICETYPECOLLECTIONINTERFACE,
class DEVICETYPEINTERFACE,
const CLSID* DEVICETYPE_CLSID,
int IDSPROGID,
int IDSDESC> class CTypedDevices :
public CComObject<CTypedDevicesBase<DEVICETYPECOLLECTIONINTERFACE, DEVICETYPEINTERFACE, DEVICETYPE_CLSID, IDSPROGID, IDSDESC> >
{
typedef CComQIPtr<DEVICETYPECOLLECTIONINTERFACE> PQDEVICETYPECOLLECTIONINTERFACE;
typedef CComQIPtr<DEVICETYPEINTERFACE> PQDEVICETYPEINTERFACE;
PQDEVICETYPECOLLECTIONINTERFACE m_Collection;
bool m_fRO;
bool m_fValid;
public:
CTypedDevices(const DeviceCollection &Devices = DeviceCollection(), bool fRO = false, bool fValid = false) :
m_fRO(fRO), m_fValid(fValid) {
m_Devices.clear();
m_Devices.insert(m_Devices.end(), Devices.begin(), Devices.end());
}
CTypedDevices(bool fRO, bool fValid = false) :
m_Devices(DeviceCollection()), m_fRO(fRO), m_fValid(fValid) {}
CTypedDevices(const CTypedDevices &src) :
m_fRO(src.m_fRO), m_fValid(src.m_fValid) {
m_Devices.clear();
m_Devices.insert(m_Devices.end(), src.m_Devices.begin(), src.m_Devices.end());
}
CTypedDevices(const PQDEVICETYPECOLLECTIONINTERFACE& src) :
m_fRO(static_cast<CTypedDevices<DEVICETYPECOLLECTIONINTERFACE,
DEVICETYPEINTERFACE,
DEVICETYPE_CLSID,
IDSPROGID,
IDSDESC> *>(src.p)->m_fRO),
m_fValid(static_cast<CTypedDevices<DEVICETYPECOLLECTIONINTERFACE,
DEVICETYPEINTERFACE,
DEVICETYPE_CLSID,
IDSPROGID,
IDSDESC> *>(src.p)->m_fValid) {
m_Devices.clear();
m_Devices.insert(m_Devices.end(),
static_cast<CTypedDevices<DEVICETYPECOLLECTIONINTERFACE,
DEVICETYPEINTERFACE,
DEVICETYPE_CLSID,
IDSPROGID,
IDSDESC> *>(src.p)->m_Devices.begin(),
static_cast<CTypedDevices<DEVICETYPECOLLECTIONINTERFACE,
DEVICETYPEINTERFACE,
DEVICETYPE_CLSID,
IDSPROGID,
IDSDESC> *>(src.p)->m_Devices.end()
);
}
CTypedDevices<DEVICETYPECOLLECTIONINTERFACE, DEVICETYPEINTERFACE, DEVICETYPE_CLSID, IDSPROGID, IDSDESC> &operator=(const CTypedDevices<DEVICETYPECOLLECTIONINTERFACE, DEVICETYPEINTERFACE, DEVICETYPE_CLSID, IDSPROGID, IDSDESC> &rhs) {
if (this != &rhs) {
m_Devices.clear();
m_Devices.insert(m_Devices.end(), rhs.m_Devices.begin(), rhs.m_Devices.end());
m_fRO = rhs.m_fRO;
m_fValid = rhs.m_fValid;
}
}
virtual ~CTypedDevices() {
}
static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {
CRegObject ro;
return CObjRegHelp::RegisterAutomationClass(bRegister ? true : false,
ro,
IDS_PROJNAME,
IDSPROGID,
IDSDESC,
*DEVICETYPE_CLSID,
LIBID_MSVidCtlLib);
}
// IMSVidDevices
public:
inline bool IsRO() { return m_fRO; }
inline bool GetValid() { return m_fValid; }
inline void SetValid(bool fValid) { m_fValid = fValid; }
__declspec(property(get=GetValid, put=SetValid)) bool Valid;
DeviceCollection m_Devices;
// IMSVidDevices
STDMETHOD(get_Count)(LONG * lCount)
{
if (lCount == NULL)
return E_POINTER;
try {
*lCount = m_Devices.size();
} catch(...) {
return E_POINTER;
}
return NOERROR;
}
STDMETHODIMP get__NewEnum(IEnumVARIANT * * pD)
{
if (pD == NULL)
return E_POINTER;
PQEnumVARIANT temp;
try {
temp = new CDevEnum(PQDispatch(this), m_Devices);
} catch(...) {
return E_OUTOFMEMORY;
}
try {
*pD = temp.Detach();
} catch(...) {
return E_POINTER;
}
return NOERROR;
}
STDMETHOD(get_Item)(VARIANT v, DEVICETYPEINTERFACE * * pDB)
{
if (pDB == NULL)
return E_POINTER;
int idx;
CComVariant vidx;
try {
if (SUCCEEDED(vidx.ChangeType(VT_I4, &v))) {
idx = vidx.lVal;
} else {
return DISP_E_TYPEMISMATCH;
}
if (idx >= m_Devices.size()) {
return DISP_E_BADINDEX;
}
} catch(...) {
return E_UNEXPECTED;
}
try {
PQDevice pd(m_Devices[idx]);
if (!pd) {
return E_UNEXPECTED;
}
*pDB = PQDEVICETYPEINTERFACE(pd);
if (!*pDB) {
return E_UNEXPECTED;
}
(*pDB)->AddRef();
} catch(...) {
return E_POINTER;
}
return NOERROR;
}
STDMETHOD(Add)(DEVICETYPEINTERFACE * pDB)
{
if (m_fRO) {
return Error(IDS_E_ROCOLLECTION, __uuidof(DEVICETYPECOLLECTIONINTERFACE), E_ACCESSDENIED);
}
try {
PQDevice p(pDB);
try {
m_Devices.push_back(p);
} catch(...) {
return E_OUTOFMEMORY;
}
} catch(...) {
E_POINTER;
}
return NOERROR;
}
STDMETHOD(Remove)(VARIANT v)
{
if (m_fRO) {
return E_ACCESSDENIED;
}
int idx;
CComVariant vidx;
try {
if (SUCCEEDED(vidx.ChangeType(VT_I4, &v))) {
idx = vidx.lVal;
} else {
return DISP_E_TYPEMISMATCH;
}
if (idx >= m_Devices.size()) {
return DISP_E_BADINDEX;
}
m_Devices.erase(m_Devices.begin() + idx);
} catch(...) {
return E_UNEXPECTED;
}
return NOERROR;
}
};
typedef CTypedDevices<IMSVidInputDevices, IMSVidInputDevice, &CLSID_MSVidInputDevices, IDS_INPUTDEVICES_PROGID, IDS_INPUTDEVICES_DESCRIPTION> CInputDevices;
typedef CTypedDevices<IMSVidOutputDevices, IMSVidOutputDevice, &CLSID_MSVidOutputDevices, IDS_OUTPUTDEVICES_PROGID, IDS_OUTPUTDEVICES_DESCRIPTION> COutputDevices;
typedef CTypedDevices<IMSVidVideoRendererDevices, IMSVidVideoRenderer, &CLSID_MSVidVideoRendererDevices, IDS_VIDEORENDERERS_PROGID, IDS_VIDEORENDERERS_DESCRIPTION> CVideoRendererDevices;
typedef CTypedDevices<IMSVidAudioRendererDevices, IMSVidAudioRenderer, &CLSID_MSVidAudioRendererDevices, IDS_AUDIORENDERERS_PROGID, IDS_AUDIORENDERERS_DESCRIPTION> CAudioRendererDevices;
typedef CTypedDevices<IMSVidFeatures, IMSVidFeature, &CLSID_MSVidFeatures, IDS_FEATURES_PROGID, IDS_FEATURES_DESCRIPTION> CFeatures;
/////////////////////////////////////////////////////////////////////////////
// CDevEnum
class ATL_NO_VTABLE CDevEnumBase :
public CComObjectRootEx<CComSingleThreadModel>,
public IObjectWithSiteImplSec<CDevEnumBase>,
public IEnumVARIANT
{
BEGIN_COM_MAP(CDevEnumBase)
COM_INTERFACE_ENTRY(IEnumVARIANT)
COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
virtual ~CDevEnumBase() {}
};
/////////////////////////////////////////////////////////////////////////////
class CDevEnum : public CComObject<CDevEnumBase>
{
public:
CDevEnum(const PQDispatch& pDevices, DeviceCollection& dci) :
m_pDevices(pDevices), m_DC(dci), i(dci.begin()) {}
CDevEnum(const CDevEnum &orig) :
m_pDevices(orig.m_pDevices), m_DC(orig.m_DC), i(orig.i) {}
virtual ~CDevEnum() {}
// IDevEnum
public:
PQDispatch m_pDevices;
DeviceCollection& m_DC;
DeviceCollection::iterator i;
// IEnumVARIANT
STDMETHOD(Next)(ULONG celt, VARIANT * rgvar, ULONG * pceltFetched)
{
// pceltFetched can legally == 0
//
if (pceltFetched != NULL) {
try {
*pceltFetched = 0;
} catch(...) {
return E_POINTER;
}
}
for (ULONG l=0; l < celt; l++) {
try {
VariantInit( &rgvar[l] ) ;
} catch(...) {
return E_POINTER;
}
}
// Retrieve the next celt elements.
HRESULT hr = NOERROR ;
for (l = 0;i != m_DC.end() && celt != 0 ; ++i, ++l, --celt) {
rgvar[l].vt = VT_DISPATCH ;
rgvar[l].pdispVal = PQDevice(*i).Detach();
if (pceltFetched != NULL) {
(*pceltFetched)++ ;
}
}
if (celt != 0) {
hr = ResultFromScode( S_FALSE ) ;
}
return hr ;
}
STDMETHOD(Skip)(ULONG celt)
{
for (;i != m_DC.end() && celt--; ++i);
return (celt == 0 ? NOERROR : ResultFromScode( S_FALSE )) ;
}
STDMETHOD(Reset)()
{
i = m_DC.begin();
return NOERROR;
}
STDMETHOD(Clone)(IEnumVARIANT * * ppenum)
{
if (ppenum == NULL)
return E_POINTER;
PQEnumVARIANT temp;
try {
temp = new CDevEnum(*this);
} catch(...) {
return E_OUTOFMEMORY;
}
try {
*ppenum = temp.Detach();
} catch(...) {
return E_POINTER;
}
return NOERROR;
}
};
#endif
//end of file devices.h