[KSPROXY]
[reactos.git] / reactos / dll / directx / ksproxy / output_pin.cpp
index b29d12a..d21f383 100644 (file)
@@ -8,17 +8,21 @@
  */
 #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,
@@ -38,12 +42,25 @@ public:
         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);
@@ -61,17 +78,58 @@ public:
     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
@@ -94,6 +152,41 @@ COutputPin::QueryInterface(
         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;
@@ -105,6 +198,60 @@ COutputPin::QueryInterface(
     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
 //
@@ -112,13 +259,161 @@ HANDLE
 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
 //
@@ -126,30 +421,92 @@ HRESULT
 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
@@ -204,8 +561,56 @@ 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
@@ -248,10 +653,11 @@ WINAPI
 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;