[ros-diffs] [janderwald] 46176: [PSDK] - Fix KSPROPSETID_Stream definition [KSPROXY] - Implement IKsClockPropertySet, IReferenceClock, IMediaSeeking, IKsTopology interface for CKsProxy - Implement more of IBaseFilter::SetSyncSource for CKsProxy - Add missing AddRef to IBaseFilter::QueryFilterInfo for CKsProxy

janderwald at svn.reactos.org janderwald at svn.reactos.org
Sat Mar 13 18:36:30 CET 2010


Author: janderwald
Date: Sat Mar 13 18:36:30 2010
New Revision: 46176

URL: http://svn.reactos.org/svn/reactos?rev=46176&view=rev
Log:
[PSDK]
- Fix KSPROPSETID_Stream definition
[KSPROXY]
- Implement IKsClockPropertySet, IReferenceClock, IMediaSeeking, IKsTopology interface for CKsProxy
- Implement more of IBaseFilter::SetSyncSource for CKsProxy
- Add missing AddRef to IBaseFilter::QueryFilterInfo for CKsProxy

Added:
    trunk/reactos/dll/directx/ksproxy/node.cpp   (with props)
Modified:
    trunk/reactos/dll/directx/ksproxy/input_pin.cpp
    trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild
    trunk/reactos/dll/directx/ksproxy/output_pin.cpp
    trunk/reactos/dll/directx/ksproxy/precomp.h
    trunk/reactos/dll/directx/ksproxy/proxy.cpp
    trunk/reactos/include/psdk/ks.h

Modified: trunk/reactos/dll/directx/ksproxy/input_pin.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/input_pin.cpp?rev=46176&r1=46175&r2=46176&view=diff
==============================================================================
--- trunk/reactos/dll/directx/ksproxy/input_pin.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/directx/ksproxy/input_pin.cpp [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -140,7 +140,7 @@
     HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
     HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
     HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
-    CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(0), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0), m_ReadOnly(0){};
+    CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0), m_ReadOnly(0){};
     virtual ~CInputPin(){};
 
 protected:

Modified: trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild?rev=46176&r1=46175&r2=46176&view=diff
==============================================================================
--- trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/directx/ksproxy/ksproxy.rbuild [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -33,6 +33,7 @@
 	<file>interface.cpp</file>
 	<file>ksproxy.cpp</file>
 	<file>ksproxy.rc</file>
+	<file>node.cpp</file>
 	<file>output_pin.cpp</file>
 	<file>proxy.cpp</file>
 	<file>qualityforward.cpp</file>

Added: trunk/reactos/dll/directx/ksproxy/node.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/node.cpp?rev=46176&view=auto
==============================================================================
--- trunk/reactos/dll/directx/ksproxy/node.cpp (added)
+++ trunk/reactos/dll/directx/ksproxy/node.cpp [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -1,0 +1,157 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
+ * FILE:            dll/directx/ksproxy/node.cpp
+ * PURPOSE:         Control Node
+ *
+ * PROGRAMMERS:     Johannes Anderwald (janderwald at reactos.org)
+ */
+#include "precomp.h"
+
+class CKsNode : public IKsControl
+{
+public:
+    STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+
+    STDMETHODIMP_(ULONG) AddRef()
+    {
+        InterlockedIncrement(&m_Ref);
+        return m_Ref;
+    }
+    STDMETHODIMP_(ULONG) Release()
+    {
+        InterlockedDecrement(&m_Ref);
+
+        if (!m_Ref)
+        {
+            delete this;
+            return 0;
+        }
+        return m_Ref;
+    }
+
+    //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);
+
+    CKsNode(IUnknown * pUnkOuter, HANDLE Handle) : m_Ref(0), m_pUnkOuter(pUnkOuter), m_Handle(Handle){};
+    virtual ~CKsNode()
+    {
+        CloseHandle(m_Handle);
+    };
+
+protected:
+    LONG m_Ref;
+    IUnknown * m_pUnkOuter;
+    HANDLE m_Handle;
+};
+
+HRESULT
+STDMETHODCALLTYPE
+CKsNode::QueryInterface(
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    if (IsEqualGUID(refiid, IID_IUnknown) ||
+        IsEqualGUID(refiid, IID_IKsControl))
+    {
+        *Output = PVOID(this);
+        reinterpret_cast<IUnknown*>(*Output)->AddRef();
+        return NOERROR;
+    }
+
+    return E_NOINTERFACE;
+}
+
+//-------------------------------------------------------------------
+// IKsControl
+//
+HRESULT
+STDMETHODCALLTYPE
+CKsNode::KsProperty(
+    PKSPROPERTY Property,
+    ULONG PropertyLength,
+    LPVOID PropertyData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_Handle != 0);
+    return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsNode::KsMethod(
+    PKSMETHOD Method,
+    ULONG MethodLength,
+    LPVOID MethodData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_Handle != 0);
+    return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsNode::KsEvent(
+    PKSEVENT Event,
+    ULONG EventLength,
+    LPVOID EventData,
+    ULONG DataLength,
+    ULONG* BytesReturned)
+{
+    assert(m_Handle != 0);
+
+    if (EventLength)
+        return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
+    else
+        return KsSynchronousDeviceControl(m_Handle, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
+}
+
+HRESULT
+WINAPI
+CKsNode_Constructor(
+    IUnknown * pUnkOuter,
+    HANDLE ParentHandle,
+    ULONG NodeId,
+    ACCESS_MASK DesiredAccess,
+    REFIID riid,
+    LPVOID * ppv)
+{
+    HRESULT hr;
+    HANDLE handle;
+    KSNODE_CREATE NodeCreate;
+
+    OutputDebugStringW(L"CKsNode_Constructor\n");
+
+    //setup request
+    NodeCreate.CreateFlags = 0;
+    NodeCreate.Node = NodeId;
+
+    hr = KsCreateTopologyNode(ParentHandle, &NodeCreate, DesiredAccess, &handle);
+    if (hr != NOERROR)
+    {
+         OutputDebugString("CKsNode_Constructor failed to open device\n");
+         return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, hr);
+    }
+
+    CKsNode * quality = new CKsNode(pUnkOuter, handle);
+
+    if (!quality)
+    {
+        // free clock handle
+        CloseHandle(handle);
+        return E_OUTOFMEMORY;
+    }
+
+    if (FAILED(quality->QueryInterface(riid, ppv)))
+    {
+        /* not supported */
+        delete quality;
+        return E_NOINTERFACE;
+    }
+
+    return NOERROR;
+}

Propchange: trunk/reactos/dll/directx/ksproxy/node.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/directx/ksproxy/output_pin.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/output_pin.cpp?rev=46176&r1=46175&r2=46176&view=diff
==============================================================================
--- trunk/reactos/dll/directx/ksproxy/output_pin.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/directx/ksproxy/output_pin.cpp [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -123,7 +123,7 @@
 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)
+    ULONG PinId) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_KsObjectParent(0), m_Pin(0)
 {
     HRESULT hr;
 

Modified: trunk/reactos/dll/directx/ksproxy/precomp.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/precomp.h?rev=46176&r1=46175&r2=46176&view=diff
==============================================================================
--- trunk/reactos/dll/directx/ksproxy/precomp.h [iso-8859-1] (original)
+++ trunk/reactos/dll/directx/ksproxy/precomp.h [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -20,6 +20,20 @@
 #include <vector>
 #include <assert.h>
 //#include <debug.h>
+
+
+interface DECLSPEC_UUID("877E4351-6FEA-11D0-B863-00AA00A216A1") IKsClock;
+
+#undef INTERFACE
+#define INTERFACE IKsClock
+
+DECLARE_INTERFACE_(IKsClock, IUnknown)
+{
+    STDMETHOD_(HANDLE, KsGetClockHandle)(
+        THIS
+    ) PURE;
+};
+
 
 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
 
@@ -139,4 +153,15 @@
     REFIID riid,
     LPVOID * ppv);
 
+/* node.cpp */
+HRESULT
+WINAPI
+CKsNode_Constructor(
+    IUnknown * pUnkOuter,
+    HANDLE ParentHandle,
+    ULONG NodeId,
+    ACCESS_MASK DesiredAccess,
+    REFIID riid,
+    LPVOID * ppv);
+
 extern const GUID IID_IKsObject;

Modified: trunk/reactos/dll/directx/ksproxy/proxy.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/ksproxy/proxy.cpp?rev=46176&r1=46175&r2=46176&view=diff
==============================================================================
--- trunk/reactos/dll/directx/ksproxy/proxy.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/directx/ksproxy/proxy.cpp [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -14,13 +14,16 @@
 const GUID IID_ISpecifyPropertyPages = {0xB196B28B, 0xBAB4, 0x101A, {0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}};
 const GUID IID_IPersistStream = {0x00000109, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
 const GUID KSPROPSETID_MediaSeeking = {0xEE904F0CL, 0xD09B, 0x11D0, {0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSEVENTSETID_Clock = {0x364D8E20L, 0x62C7, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
 #endif
 
 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
 const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
 const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
 const GUID IID_IKsTopology             = {0x28F54683, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
-
+const GUID IID_IKsClock            = {0x877E4351, 0x6FEA, 0x11D0, {0xB8, 0x63, 0x00, 0xAA, 0x00, 0xA2, 0x16, 0xA1}};
 /*
     Needs IKsClock, IKsNotifyEvent
 */
@@ -35,6 +38,7 @@
                  public IReferenceClock,
                  public IMediaSeeking,
                  public IKsPropertySet,
+                 public IKsClock,
                  public IKsClockPropertySet,
                  public IAMFilterMiscFlags,
                  public IKsControl,
@@ -148,6 +152,9 @@
     // IKsObject
     HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
 
+    // IKsClock
+    HANDLE STDMETHODCALLTYPE KsGetClockHandle();
+
     //IAMDeviceRemoval
     HRESULT STDMETHODCALLTYPE DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink);
     HRESULT STDMETHODCALLTYPE Reassociate(void);
@@ -163,7 +170,7 @@
     HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
 
 
-    CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0) {};
+    CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0), m_hClock(0) {};
     ~CKsProxy()
     {
         if (m_hDevice)
@@ -178,6 +185,9 @@
     HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName);
     HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication);
     HRESULT STDMETHODCALLTYPE CreatePins();
+    HRESULT STDMETHODCALLTYPE GetMediaSeekingFormats(PKSMULTIPLE_ITEM *FormatList);
+    HRESULT STDMETHODCALLTYPE CreateClockInstance();
+    HRESULT STDMETHODCALLTYPE PerformClockProperty(ULONG PropertyId, ULONG PropertyFlags, PVOID OutputBuffer, ULONG OutputBufferSize);
 protected:
     LONG m_Ref;
     IFilterGraph *m_pGraph;
@@ -188,6 +198,7 @@
     PinVector m_Pins;
     LPWSTR m_DevicePath;
     CLSID m_DeviceInterfaceGUID;
+    HANDLE m_hClock;
 };
 
 HRESULT
@@ -196,7 +207,7 @@
     IN  REFIID refiid,
     OUT PVOID* Output)
 {
-    *Output = (PVOID)0xDEADDEAD;//NULL;
+    *Output = NULL;
 
     if (IsEqualGUID(refiid, IID_IUnknown) ||
         IsEqualGUID(refiid, IID_IBaseFilter))
@@ -227,6 +238,12 @@
     {
         *Output = (IKsObject*)(this);
         reinterpret_cast<IKsObject*>(*Output)->AddRef();
+        return NOERROR;
+    }
+    else if (IsEqualGUID(refiid, IID_IKsClock))
+    {
+        *Output = (IKsClock*)(this);
+        reinterpret_cast<IKsClock*>(*Output)->AddRef();
         return NOERROR;
     }
     else if (IsEqualGUID(refiid, IID_IReferenceClock))
@@ -335,13 +352,110 @@
 //-------------------------------------------------------------------
 // IKsClockPropertySet interface
 //
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::CreateClockInstance()
+{
+    HRESULT hr;
+    HANDLE hPin = INVALID_HANDLE_VALUE;
+    ULONG Index;
+    PIN_DIRECTION PinDir;
+    IKsObject *pObject;
+    KSCLOCK_CREATE ClockCreate;
+
+    // find output pin and handle
+    for(Index = 0; Index < m_Pins.size(); Index++)
+    {
+        //get pin
+        IPin * pin = m_Pins[Index];
+        if (!pin)
+            continue;
+
+        // get direction
+        hr = pin->QueryDirection(&PinDir);
+        if (FAILED(hr))
+            continue;
+
+        // query IKsObject interface
+        hr = pin->QueryInterface(IID_IKsObject, (void**)&pObject);
+        if (FAILED(hr))
+            continue;
+
+
+        // get pin handle
+        hPin = pObject->KsGetObjectHandle();
+
+        //release IKsObject
+        pObject->Release();
+
+        if (hPin != INVALID_HANDLE_VALUE)
+            break;
+    }
+
+    if (hPin == INVALID_HANDLE_VALUE)
+    {
+        // clock can only be instantiated on a pin handle
+        return E_NOTIMPL;
+    }
+
+    if (m_hClock)
+    {
+        // release clock handle
+        CloseHandle(m_hClock);
+    }
+
+    //setup clock create request
+    ClockCreate.CreateFlags = 0;
+
+    // setup clock create request
+    hr = KsCreateClock(hPin, &ClockCreate, &m_hClock); // FIXME KsCreateClock returns NTSTATUS
+    if (SUCCEEDED(hr))
+    {
+        // failed to create clock
+        return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
+    }
+
+    return S_OK;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::PerformClockProperty(
+    ULONG PropertyId,
+    ULONG PropertyFlags,
+    PVOID OutputBuffer,
+    ULONG OutputBufferSize)
+{
+    KSPROPERTY Property;
+    HRESULT hr;
+    ULONG BytesReturned;
+
+    if (!m_hClock)
+    {
+        // create clock
+        hr = CreateClockInstance();
+        if (FAILED(hr))
+            return hr;
+    }
+
+    // setup request
+    Property.Set = KSPROPSETID_Clock;
+    Property.Id = PropertyId;
+    Property.Flags = PropertyFlags;
+
+    hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)OutputBuffer, OutputBufferSize, &BytesReturned);
+
+    return hr;
+}
+
 HRESULT
 STDMETHODCALLTYPE
 CKsProxy::KsGetTime(
     LONGLONG* Time)
 {
-    OutputDebugStringW(L"CKsProxy::KsGetTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsGetTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG));
 }
 
 HRESULT
@@ -349,8 +463,8 @@
 CKsProxy::KsSetTime(
     LONGLONG Time)
 {
-    OutputDebugStringW(L"CKsProxy::KsSetTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsSetTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG));
 }
 
 HRESULT
@@ -358,8 +472,8 @@
 CKsProxy::KsGetPhysicalTime(
     LONGLONG* Time)
 {
-    OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG));
 }
 
 HRESULT
@@ -368,7 +482,7 @@
     LONGLONG Time)
 {
     OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime NotImplemented\n");
-    return E_NOTIMPL;
+    return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG));
 }
 
 HRESULT
@@ -376,8 +490,8 @@
 CKsProxy::KsGetCorrelatedTime(
     KSCORRELATED_TIME* CorrelatedTime)
 {
-    OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
 }
 
 HRESULT
@@ -385,8 +499,8 @@
 CKsProxy::KsSetCorrelatedTime(
     KSCORRELATED_TIME* CorrelatedTime)
 {
-    OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
 }
 
 HRESULT
@@ -394,8 +508,8 @@
 CKsProxy::KsGetCorrelatedPhysicalTime(
     KSCORRELATED_TIME* CorrelatedTime)
 {
-    OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
 }
 
 HRESULT
@@ -403,8 +517,8 @@
 CKsProxy::KsSetCorrelatedPhysicalTime(
     KSCORRELATED_TIME* CorrelatedTime)
 {
-    OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME));
 }
 
 HRESULT
@@ -412,8 +526,8 @@
 CKsProxy::KsGetResolution(
     KSRESOLUTION* Resolution)
 {
-    OutputDebugStringW(L"CKsProxy::KsGetResolution NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsGetResolution\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_RESOLUTION, KSPROPERTY_TYPE_GET, (PVOID)Resolution, sizeof(KSRESOLUTION));
 }
 
 HRESULT
@@ -421,8 +535,8 @@
 CKsProxy::KsGetState(
     KSSTATE* State)
 {
-    OutputDebugStringW(L"CKsProxy::KsGetState NotImplemented\n");
-    return E_NOTIMPL;
+    OutputDebugStringW(L"CKsProxy::KsGetState\n");
+    return PerformClockProperty(KSPROPERTY_CLOCK_STATE, KSPROPERTY_TYPE_GET, (PVOID)State, sizeof(KSSTATE));
 }
 
 //-------------------------------------------------------------------
@@ -433,8 +547,40 @@
 CKsProxy::GetTime(
     REFERENCE_TIME *pTime)
 {
-    OutputDebugStringW(L"CKsProxy::GetTime NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+
+    OutputDebugStringW(L"CKsProxy::GetTime\n");
+
+    if (!pTime)
+        return E_POINTER;
+
+    //
+    //FIXME locks
+    //
+
+    if (!m_hClock)
+    {
+        // create clock
+        hr = CreateClockInstance();
+        if (FAILED(hr))
+            return hr;
+    }
+
+    // setup request
+    Property.Set = KSPROPSETID_Clock;
+    Property.Id = KSPROPERTY_CLOCK_TIME;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    // perform request
+    hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pTime, sizeof(REFERENCE_TIME), &BytesReturned);
+
+    // TODO
+    // increment value
+    //
+
+    return hr;
 }
 
 HRESULT
@@ -445,8 +591,62 @@
     HEVENT hEvent,
     DWORD_PTR *pdwAdviseCookie)
 {
-    OutputDebugStringW(L"CKsProxy::AdviseTime NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    KSEVENT Property;
+    ULONG BytesReturned;
+    PKSEVENT_TIME_MARK Event;
+
+    OutputDebugStringW(L"CKsProxy::AdviseTime\n");
+
+    //
+    //FIXME locks
+    //
+
+    if (!pdwAdviseCookie)
+        return E_POINTER;
+
+    if (!m_hClock)
+    {
+        // create clock
+        hr = CreateClockInstance();
+        if (FAILED(hr))
+            return hr;
+    }
+
+    // allocate event entry
+    Event = (PKSEVENT_TIME_MARK)CoTaskMemAlloc(sizeof(KSEVENT_TIME_MARK));
+    if (Event)
+    {
+        // setup request
+        Property.Set = KSEVENTSETID_Clock;
+        Property.Id = KSEVENT_CLOCK_POSITION_MARK;
+        Property.Flags = KSEVENT_TYPE_ENABLE;
+
+        Event->EventData.NotificationType = KSEVENTF_EVENT_HANDLE;
+        Event->EventData.EventHandle.Event = (HANDLE)hEvent;
+        Event->EventData.Alignment.Alignment[0] = 0;
+        Event->EventData.Alignment.Alignment[1] = 0;
+        Event->MarkTime = baseTime + streamTime;
+
+        // perform request
+        hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_MARK), &BytesReturned);
+        if (SUCCEEDED(hr))
+        {
+            // store event handle
+            *pdwAdviseCookie = (DWORD_PTR)Event;
+        }
+        else
+        {
+            // failed to enable event
+            CoTaskMemFree(Event);
+        }
+    }
+    else
+    {
+         hr = E_OUTOFMEMORY;
+    }
+
+    return hr;
 }
 
 HRESULT
@@ -457,8 +657,63 @@
     HSEMAPHORE hSemaphore,
     DWORD_PTR *pdwAdviseCookie)
 {
-    OutputDebugStringW(L"CKsProxy::AdvisePeriodic NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    KSEVENT Property;
+    ULONG BytesReturned;
+    PKSEVENT_TIME_INTERVAL Event;
+
+    OutputDebugStringW(L"CKsProxy::AdvisePeriodic\n");
+
+    //
+    //FIXME locks
+    //
+
+    if (!pdwAdviseCookie)
+        return E_POINTER;
+
+    if (!m_hClock)
+    {
+        // create clock
+        hr = CreateClockInstance();
+        if (FAILED(hr))
+            return hr;
+    }
+
+    // allocate event entry
+    Event = (PKSEVENT_TIME_INTERVAL)CoTaskMemAlloc(sizeof(KSEVENT_TIME_INTERVAL));
+    if (Event)
+    {
+        // setup request
+        Property.Set = KSEVENTSETID_Clock;
+        Property.Id = KSEVENT_CLOCK_INTERVAL_MARK;
+        Property.Flags = KSEVENT_TYPE_ENABLE;
+
+        Event->EventData.NotificationType = KSEVENTF_SEMAPHORE_HANDLE;
+        Event->EventData.SemaphoreHandle.Semaphore = (HANDLE)hSemaphore;
+        Event->EventData.SemaphoreHandle.Reserved = 0;
+        Event->EventData.SemaphoreHandle.Adjustment = 1;
+        Event->TimeBase = startTime;
+        Event->Interval = periodTime;
+
+        // perform request
+        hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_INTERVAL), &BytesReturned);
+        if (SUCCEEDED(hr))
+        {
+            // store event handle
+            *pdwAdviseCookie = (DWORD_PTR)Event;
+        }
+        else
+        {
+            // failed to enable event
+            CoTaskMemFree(Event);
+        }
+    }
+    else
+    {
+         hr = E_OUTOFMEMORY;
+    }
+
+    return hr;
 }
 
 HRESULT
@@ -466,8 +721,28 @@
 CKsProxy::Unadvise(
     DWORD_PTR dwAdviseCookie)
 {
-    OutputDebugStringW(L"CKsProxy::Unadvise NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    ULONG BytesReturned;
+
+    OutputDebugStringW(L"CKsProxy::Unadvise\n");
+
+    if (m_hClock)
+    {
+        //lets disable the event
+        hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_DISABLE_EVENT, (PVOID)dwAdviseCookie, sizeof(KSEVENTDATA), 0, 0, &BytesReturned);
+        if (SUCCEEDED(hr))
+        {
+            // lets free event data
+            CoTaskMemFree((LPVOID)dwAdviseCookie);
+        }
+    }
+    else
+    {
+        // no clock available
+        hr = E_FAIL;
+    }
+
+    return hr;
 }
 
 //-------------------------------------------------------------------
@@ -478,8 +753,55 @@
 CKsProxy::GetCapabilities(
     DWORD *pCapabilities)
 {
-    OutputDebugStringW(L"CKsProxy::GetCapabilities NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr = S_OK;
+    DWORD TempCaps;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_CAPABILITIES;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetCapabilities\n");
+
+    if (!pCapabilities)
+        return E_POINTER;
+
+
+    *pCapabilities = (KS_SEEKING_CanSeekAbsolute | KS_SEEKING_CanSeekForwards | KS_SEEKING_CanSeekBackwards | KS_SEEKING_CanGetCurrentPos |
+                      KS_SEEKING_CanGetStopPos | KS_SEEKING_CanGetDuration | KS_SEEKING_CanPlayBackwards);
+
+    KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pCapabilities, sizeof(KS_SEEKING_CAPABILITIES), &BytesReturned);
+    // check if plugins support it
+    for(Index = 0; Index < m_Plugins.size(); Index++)
+    {
+        // get plugin
+        IUnknown * Plugin = m_Plugins[Index];
+
+        if (!Plugin)
+           continue;
+
+        // query for IMediaSeeking interface
+        IMediaSeeking *pSeek = NULL;
+        hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+        if (FAILED(hr))
+        {
+            *pCapabilities = 0;
+            return hr;
+        }
+
+        TempCaps = 0;
+        // set time format
+        hr = pSeek->GetCapabilities(&TempCaps);
+        if (SUCCEEDED(hr))
+        {
+            // and with supported flags
+            *pCapabilities = (*pCapabilities & TempCaps);
+        }
+        // release IMediaSeeking interface
+        pSeek->Release();
+    }
+    return hr;
 }
 
 HRESULT
@@ -487,8 +809,75 @@
 CKsProxy::CheckCapabilities(
     DWORD *pCapabilities)
 {
-    OutputDebugStringW(L"CKsProxy::CheckCapabilities NotImplemented\n");
-    return E_NOTIMPL;
+    DWORD Capabilities;
+    HRESULT hr;
+
+    OutputDebugStringW(L"CKsProxy::CheckCapabilities\n");
+
+    if (!pCapabilities)
+        return E_POINTER;
+
+    if (!*pCapabilities)
+        return E_FAIL;
+
+    hr = GetCapabilities(&Capabilities);
+    if (SUCCEEDED(hr))
+    {
+        if ((Capabilities | *pCapabilities) == Capabilities)
+        {
+            // all present
+            return S_OK;
+        }
+
+        Capabilities = (Capabilities & *pCapabilities);
+        if (Capabilities)
+        {
+            // not all present
+            *pCapabilities = Capabilities;
+            return S_FALSE;
+        }
+        // no capabilities are present
+        return E_FAIL;
+    }
+
+    return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CKsProxy::GetMediaSeekingFormats(
+    PKSMULTIPLE_ITEM *FormatList)
+{
+    KSPROPERTY Property;
+    HRESULT hr;
+    ULONG BytesReturned;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    // query for format size list
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
+
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
+    {
+        // allocate format list
+        *FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
+        if (!*FormatList)
+        {
+            // not enough memory
+            return E_OUTOFMEMORY;
+        }
+
+        // get format list
+        hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)*FormatList, BytesReturned, &BytesReturned);
+        if (FAILED(hr))
+        {
+            // failed to query format list
+            CoTaskMemFree(FormatList);
+        }
+    }
+    return hr;
 }
 
 HRESULT
@@ -496,58 +885,31 @@
 CKsProxy::IsFormatSupported(
     const GUID *pFormat)
 {
-    KSPROPERTY Property;
     PKSMULTIPLE_ITEM FormatList;
     LPGUID pGuid;
     ULONG Index;
     HRESULT hr = S_FALSE;
-    ULONG BytesReturned;
 
     OutputDebugStringW(L"CKsProxy::IsFormatSupported\n");
 
     if (!pFormat)
         return E_POINTER;
 
-    Property.Set = KSPROPSETID_MediaSeeking;
-    Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS;
-    Property.Flags = KSPROPERTY_TYPE_GET;
-
-    // query for format size list
-    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
-
-    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
-    {
-        // allocate format list
-        FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
-        if (!FormatList)
-        {
-            // not enough memory
-            return E_OUTOFMEMORY;
-        }
-
-        // get format list
-        hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)FormatList, BytesReturned, &BytesReturned);
-        if (FAILED(hr))
-        {
-            // failed to query format list
-            CoTaskMemFree(FormatList);
-            return hr;
-        }
-
+    // get media formats
+    hr = GetMediaSeekingFormats(&FormatList);
+    if (SUCCEEDED(hr))
+    {
         //iterate through format list
         pGuid = (LPGUID)(FormatList + 1);
         for(Index = 0; Index < FormatList->Count; Index++)
         {
             if (IsEqualGUID(*pGuid, *pFormat))
             {
-                OutputDebugStringW(L"CKsProxy::IsFormatSupported found format\n");
                 CoTaskMemFree(FormatList);
                 return S_OK;
             }
             pGuid++;
         }
-
-        OutputDebugStringW(L"CKsProxy::IsFormatSupported FormatNotFound\n");
         // free format list
         CoTaskMemFree(FormatList);
     }
@@ -589,8 +951,55 @@
 CKsProxy::QueryPreferredFormat(
     GUID *pFormat)
 {
-    OutputDebugStringW(L"CKsProxy::QueryPreferredFormat NotImplemented\n");
-    return E_NOTIMPL;
+    PKSMULTIPLE_ITEM FormatList;
+    HRESULT hr;
+    ULONG Index;
+
+    OutputDebugStringW(L"CKsProxy::QueryPreferredFormat\n");
+
+    if (!pFormat)
+        return E_POINTER;
+
+    hr = GetMediaSeekingFormats(&FormatList);
+    if (SUCCEEDED(hr))
+    {
+        if (FormatList->Count)
+        {
+            CopyMemory(pFormat, (FormatList + 1), sizeof(GUID));
+            CoTaskMemFree(FormatList);
+            return S_OK;
+        }
+        CoTaskMemFree(FormatList);
+    }
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // get preferred time format
+                hr = pSeek->QueryPreferredFormat(pFormat);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE)
+                    return hr;
+            }
+        }
+        hr = S_FALSE;
+    }
+
+    return hr;
 }
 
 HRESULT
@@ -598,8 +1007,45 @@
 CKsProxy::GetTimeFormat(
     GUID *pFormat)
 {
-    OutputDebugStringW(L"CKsProxy::GetTimeFormat NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetTimeFormat\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            hr = E_NOTIMPL;
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // set time format
+                hr = pSeek->GetTimeFormat(pFormat);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE)
+                    break;
+            }
+        }
+    }
+    return hr;
 }
 
 HRESULT
@@ -607,8 +1053,17 @@
 CKsProxy::IsUsingTimeFormat(
     const GUID *pFormat)
 {
-    OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat NotImplemented\n");
-    return E_NOTIMPL;
+    GUID Format;
+
+    OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat\n");
+
+    if (FAILED(QueryPreferredFormat(&Format)))
+        return S_FALSE;
+
+    if (IsEqualGUID(Format, *pFormat))
+        return S_OK;
+    else
+        return S_FALSE;
 }
 
 HRESULT
@@ -616,8 +1071,47 @@
 CKsProxy::SetTimeFormat(
     const GUID *pFormat)
 {
-    OutputDebugStringW(L"CKsProxy::SetTimeFormat NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT;
+    Property.Flags = KSPROPERTY_TYPE_SET;
+
+    OutputDebugStringW(L"CKsProxy::SetTimeFormat\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            hr = E_NOTIMPL;
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (FAILED(hr))
+            {
+                //not supported
+                break;
+            }
+            // set time format
+            hr = pSeek->SetTimeFormat(pFormat);
+            // release IMediaSeeking interface
+            pSeek->Release();
+
+            if (FAILED(hr))
+                break;
+        }
+    }
+    return hr;
 }
 
 HRESULT
@@ -625,8 +1119,45 @@
 CKsProxy::GetDuration(
     LONGLONG *pDuration)
 {
-    OutputDebugStringW(L"CKsProxy::GetDuration NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_DURATION;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetDuration\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pDuration, sizeof(LONGLONG), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            hr = E_NOTIMPL;
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // get duration
+                hr = pSeek->GetStopPosition(pDuration);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE) // plugin implements it
+                     break;
+            }
+        }
+    }
+    return hr;
 }
 
 HRESULT
@@ -634,8 +1165,45 @@
 CKsProxy::GetStopPosition(
     LONGLONG *pStop)
 {
-    OutputDebugStringW(L"CKsProxy::GetStopPosition NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_STOPPOSITION;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetStopPosition\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pStop, sizeof(LONGLONG), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            hr = E_NOTIMPL;
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // get stop position
+                hr = pSeek->GetStopPosition(pStop);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE) // plugin implements it
+                     break;
+            }
+        }
+    }
+    return hr;
 }
 
 HRESULT
@@ -643,8 +1211,45 @@
 CKsProxy::GetCurrentPosition(
     LONGLONG *pCurrent)
 {
-    OutputDebugStringW(L"CKsProxy::GetCurrentPosition NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_POSITION;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetCurrentPosition\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pCurrent, sizeof(LONGLONG), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            hr = E_NOTIMPL;
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // get current position
+                hr = pSeek->GetCurrentPosition(pCurrent);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE) // plugin implements it
+                     break;
+            }
+        }
+    }
+    return hr;
 }
 
 HRESULT
@@ -655,8 +1260,74 @@
     LONGLONG Source,
     const GUID *pSourceFormat)
 {
-    OutputDebugStringW(L"CKsProxy::ConvertTimeFormat NotImplemented\n");
-    return E_NOTIMPL;
+    KSP_TIMEFORMAT Property;
+    ULONG BytesReturned, Index;
+    GUID SourceFormat, TargetFormat;
+    HRESULT hr;
+
+    Property.Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Property.Id = KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT;
+    Property.Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::ConvertTimeFormat\n");
+
+    if (!pTargetFormat)
+    {
+        // get current format
+        hr = GetTimeFormat(&TargetFormat);
+        if (FAILED(hr))
+            return hr;
+
+        pTargetFormat = &TargetFormat;
+    }
+
+    if (!pSourceFormat)
+    {
+        // get current format
+        hr = GetTimeFormat(&SourceFormat);
+        if (FAILED(hr))
+            return hr;
+
+        pSourceFormat = &SourceFormat;
+    }
+
+    Property.SourceFormat = *pSourceFormat;
+    Property.TargetFormat = *pTargetFormat;
+    Property.Time = Source;
+
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_TIMEFORMAT), (PVOID)pTarget, sizeof(LONGLONG), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        //default error
+        hr = E_NOTIMPL;
+
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // convert time format
+                hr = pSeek->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE) // plugin implements it
+                     break;
+            }
+        }
+    }
+
+    return hr;
 }
 
 HRESULT
@@ -667,8 +1338,71 @@
     LONGLONG *pStop,
     DWORD dwStopFlags)
 {
-    OutputDebugStringW(L"CKsProxy::SetPositions NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    KSPROPERTY_POSITIONS Positions;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_POSITIONS;
+    Property.Flags = KSPROPERTY_TYPE_SET;
+
+    Positions.Current = *pCurrent;
+    Positions.CurrentFlags = (KS_SEEKING_FLAGS)dwCurrentFlags;
+    Positions.Stop = *pStop;
+    Positions.StopFlags = (KS_SEEKING_FLAGS)dwStopFlags;
+
+    OutputDebugStringW(L"CKsProxy::SetPositions\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Positions, sizeof(KSPROPERTY_POSITIONS), &BytesReturned);
+    if (SUCCEEDED(hr))
+    {
+        if (dwCurrentFlags & AM_SEEKING_ReturnTime)
+        {
+            // retrieve current position
+            hr = GetCurrentPosition(pCurrent);
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            if (dwStopFlags & AM_SEEKING_ReturnTime)
+            {
+                // retrieve current position
+                hr = GetStopPosition(pStop);
+            }
+        }
+        return hr;
+    }
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        hr = E_NOTIMPL;
+
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // set positions
+                hr = pSeek->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (FAILED(hr))
+                    break;
+            }
+        }
+    }
+
+    return hr;
 }
 
 HRESULT
@@ -677,8 +1411,15 @@
     LONGLONG *pCurrent,
     LONGLONG *pStop)
 {
-    OutputDebugStringW(L"CKsProxy::GetPositions NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+
+    OutputDebugStringW(L"CKsProxy::GetPositions\n");
+
+    hr = GetCurrentPosition(pCurrent);
+    if (SUCCEEDED(hr))
+        hr = GetStopPosition(pStop);
+
+    return hr;
 }
 
 HRESULT
@@ -687,8 +1428,52 @@
     LONGLONG *pEarliest,
     LONGLONG *pLatest)
 {
-    OutputDebugStringW(L"CKsProxy::GetAvailable NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    KSPROPERTY_MEDIAAVAILABLE Media;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_AVAILABLE;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetAvailable\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Media, sizeof(KSPROPERTY_MEDIAAVAILABLE), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            hr = E_NOTIMPL;
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // delegate call
+                hr = pSeek->GetAvailable(pEarliest, pLatest);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE) // plugin implements it
+                     break;
+            }
+        }
+    }
+    else if (SUCCEEDED(hr))
+    {
+        *pEarliest = Media.Earliest;
+        *pLatest = Media.Latest;
+    }
+
+    return hr;
 }
 
 HRESULT
@@ -696,7 +1481,6 @@
 CKsProxy::SetRate(
     double dRate)
 {
-    OutputDebugStringW(L"CKsProxy::SetRate NotImplemented\n");
     return E_NOTIMPL;
 }
 
@@ -705,7 +1489,6 @@
 CKsProxy::GetRate(
     double *pdRate)
 {
-    OutputDebugStringW(L"CKsProxy::GetRate NotImplemented\n");
     return E_NOTIMPL;
 }
 
@@ -714,8 +1497,45 @@
 CKsProxy::GetPreroll(
     LONGLONG *pllPreroll)
 {
-    OutputDebugStringW(L"CKsProxy::GetPreroll NotImplemented\n");
-    return E_NOTIMPL;
+    KSPROPERTY Property;
+    ULONG BytesReturned, Index;
+    HRESULT hr;
+
+    Property.Set = KSPROPSETID_MediaSeeking;
+    Property.Id = KSPROPERTY_MEDIASEEKING_PREROLL;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    OutputDebugStringW(L"CKsProxy::GetPreroll\n");
+
+    hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pllPreroll, sizeof(LONGLONG), &BytesReturned);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+    {
+        // check if all plugins support it
+        for(Index = 0; Index < m_Plugins.size(); Index++)
+        {
+            // get plugin
+            IUnknown * Plugin = m_Plugins[Index];
+
+            if (!Plugin)
+               continue;
+
+            // query for IMediaSeeking interface
+            IMediaSeeking *pSeek = NULL;
+            hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
+            if (SUCCEEDED(hr))
+            {
+                // get preroll
+                hr = pSeek->GetPreroll(pllPreroll);
+                // release IMediaSeeking interface
+                pSeek->Release();
+
+                if (hr != S_FALSE) // plugin implements it
+                     break;
+            }
+        }
+        hr = E_NOTIMPL;
+    }
+    return hr;
 }
 
 //-------------------------------------------------------------------
@@ -922,8 +1742,23 @@
     REFGUID InterfaceId,
     LPVOID* Interface)
 {
-    OutputDebugStringW(L"CKsProxy::CreateNodeInstance NotImplemented\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+
+    OutputDebugStringW(L"CKsProxy::CreateNodeInstance\n");
+
+    *Interface = NULL;
+
+    if (IsEqualIID(IID_IUnknown, InterfaceId) || !UnkOuter)
+    {
+        hr = CKsNode_Constructor(UnkOuter, m_hDevice, NodeId, DesiredAccess, InterfaceId, Interface);
+    }
+    else
+    {
+        // interface not supported
+        hr = E_NOINTERFACE;
+    }
+
+    return hr;
 }
 
 //-------------------------------------------------------------------
@@ -1119,7 +1954,16 @@
     return NOERROR;
 }
 
-
+//-------------------------------------------------------------------
+// IKsClock interface
+//
+
+HANDLE
+STDMETHODCALLTYPE
+CKsProxy::KsGetClockHandle()
+{
+    return m_hClock;
+}
 
 
 //-------------------------------------------------------------------
@@ -1647,6 +2491,90 @@
 CKsProxy::SetSyncSource(
     IReferenceClock *pClock)
 {
+    HRESULT hr;
+    IKsClock *pKsClock;
+    HANDLE hClock, hPin;
+    ULONG Index;
+    IPin * pin;
+    IKsObject * pObject;
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+    PIN_DIRECTION PinDir;
+
+// Plug In Distributor: IKsClock 
+
+
+    // FIXME
+    // need locks
+
+    if (!pClock)
+        return E_POINTER;
+
+    hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock);
+    if (FAILED(hr))
+        return hr;
+
+    // get clock handle
+    hClock = pKsClock->KsGetClockHandle();
+    if (!hClock || hClock == INVALID_HANDLE_VALUE)
+    {
+        // failed
+        pKsClock->Release();
+        return E_FAIL;
+    }
+
+    // distribute clock to all pins
+    for(Index = 0; Index < m_Pins.size(); Index++)
+    {
+        // get current pin
+        pin = m_Pins[Index];
+        if (!pin)
+            continue;
+
+        // get IKsObject interface
+        hr = pin->QueryInterface(IID_IKsObject, (void **)&pObject);
+        if (SUCCEEDED(hr))
+        {
+            // get pin handle
+            hPin = pObject->KsGetObjectHandle();
+            if (hPin != INVALID_HANDLE_VALUE && hPin)
+            {
+                // set clock
+                Property.Set = KSPROPSETID_Stream;
+                Property.Id = KSPROPERTY_STREAM_MASTERCLOCK;
+                Property.Flags = KSPROPERTY_TYPE_SET;
+
+                // set master clock
+                hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)hClock, sizeof(HANDLE), &BytesReturned);
+
+                if (FAILED(hr))
+                {
+                    if (hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND) &&
+                        hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
+                    {
+                        // failed to set master clock
+                        pKsClock->Release();
+                        pObject->Release();
+                        return hr;
+                    }
+                }
+            }
+            // release IKsObject
+            pObject->Release();
+        }
+
+        // now get the direction
+        hr = pin->QueryDirection(&PinDir);
+        if (SUCCEEDED(hr))
+        {
+            if (PinDir == PINDIR_OUTPUT)
+            {
+                // notify pin via
+                //CBaseStreamControl::SetSyncSource(pClock)
+            }
+        }
+    }
+
     if (pClock)
     {
         pClock->AddRef();
@@ -1727,6 +2655,9 @@
 
     pInfo->achName[0] = L'\0';
     pInfo->pGraph = m_pGraph;
+
+    if (m_pGraph)
+        m_pGraph->AddRef();
 
     return S_OK;
 }

Modified: trunk/reactos/include/psdk/ks.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/ks.h?rev=46176&r1=46175&r2=46176&view=diff
==============================================================================
--- trunk/reactos/include/psdk/ks.h [iso-8859-1] (original)
+++ trunk/reactos/include/psdk/ks.h [iso-8859-1] Sat Mar 13 18:36:30 2010
@@ -724,8 +724,10 @@
     Properties/Methods/Events
 */
 
-#define KSPROPSETID_Stream \
+#define STATIC_KSPROPSETID_Stream\
     0x65aaba60L, 0x98ae, 0x11cf, 0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4
+DEFINE_GUIDSTRUCT("65aaba60-98ae-11cf-a10d-0020afd156e4", KSPROPSETID_Stream);
+#define KSPROPSETID_Stream DEFINE_GUIDNAMED(KSPROPSETID_Stream)
 
 typedef enum
 {
@@ -2091,7 +2093,7 @@
 typedef struct _KSEVENT_ENTRY KSEVENT_ENTRY, *PKSEVENT_ENTRY;
 
 #if defined(_NTDDK_)
-
+	
 typedef NTSTATUS (NTAPI *PFNKSADDEVENT)(
     IN  PIRP Irp,
     IN  PKSEVENTDATA EventData,




More information about the Ros-diffs mailing list