*/
#include "precomp.h"
+#ifndef _MSC_VER
+const GUID IID_IKsPinFactory = {0xCD5EBE6BL, 0x8B6E, 0x11D1, {0x8A, 0xE0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+#endif
+
class COutputPin : public IPin,
- public IKsObject
+ public IKsObject,
+ public IKsPropertySet,
+ public IStreamBuilder,
+ public IKsPinFactory,
+ public ISpecifyPropertyPages,
+// public IKsPinPipe,
+ public IKsControl
/*
public IQualityControl,
public IKsPinEx,
- public IKsPinPipe,
- public ISpecifyPropertyPages,
- public IStreamBuilder,
- public IKsPropertySet,
- public IKsPinFactory,
- public IKsControl,
public IKsAggregateControl
public IMediaSeeking,
public IAMStreamConfig,
InterlockedDecrement(&m_Ref);
if (!m_Ref)
{
- delete this;
+ //delete this;
return 0;
}
return m_Ref;
}
+ //IKsPinPipe
+ HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
+ HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option);
+ IPin* STDMETHODCALLTYPE KsGetConnectedPin();
+ IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation);
+ HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator);
+ ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag();
+ HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag);
+ GUID STDMETHODCALLTYPE KsGetPinBusCache();
+ HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus);
+ PWCHAR STDMETHODCALLTYPE KsGetPinName();
+ PWCHAR STDMETHODCALLTYPE KsGetFilterName();
+
//IPin methods
HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE EndFlush();
HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+ // ISpecifyPropertyPages
+ HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
+
//IKsObject methods
HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
+ //IKsPropertySet
+ HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
+ HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
+ HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
+
+ //IKsControl
+ HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
+ HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
+ HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
+
+ //IStreamBuilder
+ HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph);
+ HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
+
+ //IKsPinFactory
+ HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
- COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName){};
- virtual ~COutputPin(){};
+ COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId);
+ virtual ~COutputPin();
protected:
LONG m_Ref;
IBaseFilter * m_ParentFilter;
LPCWSTR m_PinName;
+ HANDLE m_hPin;
+ ULONG m_PinId;
+ IKsObject * m_KsObjectParent;
+ IPin * m_Pin;
+};
+
+COutputPin::~COutputPin()
+{
+ if (m_KsObjectParent)
+ m_KsObjectParent->Release();
+}
+
+COutputPin::COutputPin(
+ IBaseFilter * ParentFilter,
+ LPCWSTR PinName,
+ ULONG PinId) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hPin(0), m_PinId(PinId), m_KsObjectParent(0), m_Pin(0)
+{
+ HRESULT hr;
+
+ hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&m_KsObjectParent);
+ assert(hr == S_OK);
+
};
HRESULT
reinterpret_cast<IKsObject*>(*Output)->AddRef();
return NOERROR;
}
+ else if (IsEqualGUID(refiid, IID_IKsPropertySet))
+ {
+ *Output = (IKsPropertySet*)(this);
+ reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IKsControl))
+ {
+ *Output = (IKsControl*)(this);
+ reinterpret_cast<IKsControl*>(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IStreamBuilder))
+ {
+ *Output = (IStreamBuilder*)(this);
+ reinterpret_cast<IStreamBuilder*>(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IKsPinFactory))
+ {
+ *Output = (IKsPinFactory*)(this);
+ reinterpret_cast<IKsPinFactory*>(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
+ {
+ *Output = (ISpecifyPropertyPages*)(this);
+ reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
+ return NOERROR;
+ }
+ else if (IsEqualGUID(refiid, IID_IBaseFilter))
+ {
+ OutputDebugStringW(L"COutputPin::QueryInterface query IID_IBaseFilter\n");
+ DebugBreak();
+ }
WCHAR Buffer[MAX_PATH];
LPOLESTR lpstr;
return E_NOINTERFACE;
}
+//-------------------------------------------------------------------
+// ISpecifyPropertyPages
+//
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::GetPages(CAUUID *pPages)
+{
+ OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");
+
+ if (!pPages)
+ return E_POINTER;
+
+ pPages->cElems = 0;
+ pPages->pElems = NULL;
+
+ return S_OK;
+}
+
+//-------------------------------------------------------------------
+// IKsPinFactory
+//
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsPinFactory(
+ ULONG* PinFactory)
+{
+ *PinFactory = m_PinId;
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------
+// IStreamBuilder
+//
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Render(
+ IPin *ppinOut,
+ IGraphBuilder *pGraph)
+{
+ return S_OK;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Backout(
+ IPin *ppinOut,
+ IGraphBuilder *pGraph)
+{
+ return S_OK;
+}
//-------------------------------------------------------------------
// IKsObject
//
STDMETHODCALLTYPE
COutputPin::KsGetObjectHandle()
{
- OutputDebugStringW(L"COutputPin::KsGetObjectHandle CALLED\n");
+ assert(m_hPin);
+ return m_hPin;
+}
- //FIXME
- // return pin handle
- return NULL;
+//-------------------------------------------------------------------
+// IKsControl
+//
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsProperty(
+ PKSPROPERTY Property,
+ ULONG PropertyLength,
+ LPVOID PropertyData,
+ ULONG DataLength,
+ ULONG* BytesReturned)
+{
+ assert(m_hPin != 0);
+ return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsMethod(
+ PKSMETHOD Method,
+ ULONG MethodLength,
+ LPVOID MethodData,
+ ULONG DataLength,
+ ULONG* BytesReturned)
+{
+ assert(m_hPin != 0);
+ return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
}
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::KsEvent(
+ PKSEVENT Event,
+ ULONG EventLength,
+ LPVOID EventData,
+ ULONG DataLength,
+ ULONG* BytesReturned)
+{
+ assert(m_hPin != 0);
+
+ if (EventLength)
+ return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
+ else
+ return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
+}
+
+
+//-------------------------------------------------------------------
+// IKsPropertySet
+//
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Set(
+ REFGUID guidPropSet,
+ DWORD dwPropID,
+ LPVOID pInstanceData,
+ DWORD cbInstanceData,
+ LPVOID pPropData,
+ DWORD cbPropData)
+{
+ ULONG BytesReturned;
+
+ if (cbInstanceData)
+ {
+ PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
+ if (!Property)
+ return E_OUTOFMEMORY;
+
+ Property->Set = guidPropSet;
+ Property->Id = dwPropID;
+ Property->Flags = KSPROPERTY_TYPE_SET;
+
+ CopyMemory((Property+1), pInstanceData, cbInstanceData);
+
+ HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
+ CoTaskMemFree(Property);
+ return hr;
+ }
+ else
+ {
+ KSPROPERTY Property;
+
+ Property.Set = guidPropSet;
+ Property.Id = dwPropID;
+ Property.Flags = KSPROPERTY_TYPE_SET;
+
+ HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
+ return hr;
+ }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::Get(
+ REFGUID guidPropSet,
+ DWORD dwPropID,
+ LPVOID pInstanceData,
+ DWORD cbInstanceData,
+ LPVOID pPropData,
+ DWORD cbPropData,
+ DWORD *pcbReturned)
+{
+ ULONG BytesReturned;
+
+ if (cbInstanceData)
+ {
+ PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
+ if (!Property)
+ return E_OUTOFMEMORY;
+
+ Property->Set = guidPropSet;
+ Property->Id = dwPropID;
+ Property->Flags = KSPROPERTY_TYPE_GET;
+
+ CopyMemory((Property+1), pInstanceData, cbInstanceData);
+
+ HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
+ CoTaskMemFree(Property);
+ return hr;
+ }
+ else
+ {
+ KSPROPERTY Property;
+
+ Property.Set = guidPropSet;
+ Property.Id = dwPropID;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+
+ HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
+ return hr;
+ }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+COutputPin::QuerySupported(
+ REFGUID guidPropSet,
+ DWORD dwPropID,
+ DWORD *pTypeSupport)
+{
+ KSPROPERTY Property;
+ ULONG BytesReturned;
+
+ Property.Set = guidPropSet;
+ Property.Id = dwPropID;
+ Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
+
+ return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
+}
+
+
//-------------------------------------------------------------------
// IPin interface
//
STDMETHODCALLTYPE
COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
{
+ AM_MEDIA_TYPE MediaType;
+ HRESULT hr;
+ HANDLE hFilter;
+
OutputDebugStringW(L"COutputPin::Connect called\n");
- return E_NOTIMPL;
+ if (pmt)
+ {
+ hr = pReceivePin->QueryAccept(pmt);
+ if (FAILED(hr))
+ return hr;
+ }
+ else
+ {
+ // get parent filter handle
+ hFilter = m_KsObjectParent->KsGetObjectHandle();
+
+ // get media type count
+ ZeroMemory(&MediaType, sizeof(AM_MEDIA_TYPE));
+ hr = KsGetMediaType(0, &MediaType, hFilter, m_PinId);
+ if (FAILED(hr))
+ return hr;
+
+ // query accept
+ hr = pReceivePin->QueryAccept(&MediaType);
+ if (FAILED(hr))
+ return hr;
+
+ pmt = &MediaType;
+ }
+
+ //FIXME create pin handle
+
+ // receive connection;
+ hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
+ if (SUCCEEDED(hr))
+ {
+ // increment reference count
+ pReceivePin->AddRef();
+ m_Pin = pReceivePin;
+ OutputDebugStringW(L"COutputPin::Connect success\n");
+ }
+
+ return hr;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
- OutputDebugStringW(L"COutputPin::ReceiveConnection called\n");
- return E_NOTIMPL;
+ return E_UNEXPECTED;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::Disconnect( void)
{
- OutputDebugStringW(L"COutputPin::Disconnect called\n");
- return E_NOTIMPL;
+ if (!m_Pin)
+ {
+ // pin was not connected
+ return S_FALSE;
+ }
+
+ //FIXME
+ //check if filter is active
+
+ m_Pin->Release();
+ m_Pin = NULL;
+
+ OutputDebugStringW(L"COutputPin::Disconnect\n");
+ return S_OK;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::ConnectedTo(IPin **pPin)
{
+ if (!pPin)
+ return E_POINTER;
+
+ if (m_Pin)
+ {
+ // increment reference count
+ m_Pin->AddRef();
+ *pPin = m_Pin;
+ return S_OK;
+ }
+
*pPin = NULL;
- OutputDebugStringW(L"COutputPin::ConnectedTo called\n");
return VFW_E_NOT_CONNECTED;
}
HRESULT
STDMETHODCALLTYPE
COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
+ HRESULT hr;
+ ULONG MediaTypeCount = 0, Index;
+ AM_MEDIA_TYPE * MediaTypes;
+ HANDLE hFilter;
+
OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n");
- return E_NOTIMPL;
+
+ if (!m_KsObjectParent)
+ {
+ // no interface
+ return E_NOINTERFACE;
+ }
+
+ // get parent filter handle
+ hFilter = m_KsObjectParent->KsGetObjectHandle();
+
+ // query media type count
+ hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount);
+ if (FAILED(hr) || !MediaTypeCount)
+ {
+ OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n");
+ return hr;
+ }
+
+ // allocate media types
+ MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
+ if (!MediaTypes)
+ {
+ // not enough memory
+ OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n");
+ return E_OUTOFMEMORY;
+ }
+
+ // zero media types
+ ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
+
+ for(Index = 0; Index < MediaTypeCount; Index++)
+ {
+ // get media type
+ hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId);
+ if (FAILED(hr))
+ {
+ // failed
+ CoTaskMemFree(MediaTypes);
+ OutputDebugStringW(L"COutputPin::EnumMediaTypes failed2\n");
+ return hr;
+ }
+ }
+
+ return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
}
HRESULT
STDMETHODCALLTYPE
COutputPin_Constructor(
IBaseFilter * ParentFilter,
LPCWSTR PinName,
+ ULONG PinId,
REFIID riid,
LPVOID * ppv)
{
- COutputPin * handler = new COutputPin(ParentFilter, PinName);
+ COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId);
if (!handler)
return E_OUTOFMEMORY;