[QUARTZ]
[reactos.git] / reactos / dll / directx / wine / quartz / filtergraph.c
index 896762f..9121a21 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <config.h>
-#include <stdarg.h>
-
-#define COBJMACROS
-
-#include "windef.h"
-#include "winbase.h"
-#include "winuser.h"
-#include "winreg.h"
-#include "shlwapi.h"
-#include "dshow.h"
-#include <wine/debug.h>
 #include "quartz_private.h"
-#include "ole2.h"
-#include "olectl.h"
-#include <strmif.h>
-#include "vfwmsgs.h"
-#include "evcode.h"
-#include <wine/unicode.h>
-
-
-WINE_DEFAULT_DEBUG_CHANNEL(quartz);
 
 typedef struct {
     HWND     hWnd;      /* Target window */
@@ -88,7 +67,7 @@ static int EventsQueue_Destroy(EventsQueue* omr)
     return TRUE;
 }
 
-static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
+static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
 {
     EnterCriticalSection(&omr->msg_crst);
     if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))
@@ -117,7 +96,7 @@ static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
     return TRUE;
 }
 
-static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut)
+static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut)
 {
     if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
        return FALSE;
@@ -176,7 +155,6 @@ typedef struct _IFilterGraphImpl {
     IUnknown *outer_unk;
     LONG ref;
     IUnknown *punkFilterMapper2;
-    IFilterMapper2 * pFilterMapper2;
     IBaseFilter ** ppFiltersInGraph;
     LPWSTR * pFilterNames;
     ULONG nFilters;
@@ -201,7 +179,6 @@ typedef struct _IFilterGraphImpl {
     GUID timeformatseek;
     REFERENCE_TIME start_time;
     REFERENCE_TIME pause_time;
-    LONGLONG stop_position;
     LONG recursioncount;
     IUnknown *pSite;
     LONG version;
@@ -265,11 +242,11 @@ static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown *iface, REFIID ri
         TRACE("   requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
         return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
     } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
-        *ppvObj = This->pFilterMapper2;
         TRACE("   returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
+        return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
     } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) {
-        *ppvObj = This->pFilterMapper2;
         TRACE("   returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj);
+        return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
     } else if (IsEqualGUID(&IID_IGraphVersion, riid)) {
         *ppvObj = &This->IGraphConfig_iface;
         TRACE("   returning IGraphConfig interface (%p)\n", *ppvObj);
@@ -319,9 +296,6 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
                 IUnknown_Release(This->ItfCacheEntries[i].iface);
         }
 
-        /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 */
-        IUnknown_AddRef(This->outer_unk);
-        IFilterMapper2_Release(This->pFilterMapper2);
         IUnknown_Release(This->punkFilterMapper2);
 
         if (This->pSite) IUnknown_Release(This->pSite);
@@ -377,7 +351,7 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *
     HRESULT hr;
     int i,j;
     WCHAR* wszFilterName = NULL;
-    int duplicate_name = FALSE;
+    BOOL duplicate_name = FALSE;
 
     TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
 
@@ -450,7 +424,7 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *
         This->filterCapacity = newCapacity;
     }
 
-    hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
+    hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)&This->IFilterGraph2_iface, wszFilterName);
 
     if (SUCCEEDED(hr))
     {
@@ -490,7 +464,7 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
             if (This->defaultclock && This->refClockProvider == pFilter)
             {
                 IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL);
-                This->defaultclock = 1;
+                This->defaultclock = TRUE;
             }
 
             TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
@@ -611,7 +585,7 @@ static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *
     if (info_out.dir != PINDIR_OUTPUT)
     {
         IBaseFilter_Release(info_out.pFilter);
-        return E_UNEXPECTED;
+        return VFW_E_CANNOT_CONNECT;
     }
 
     hr = IPin_QueryPinInfo(in, &info_in);
@@ -621,7 +595,7 @@ static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *
         goto out;
     if (info_in.dir != PINDIR_INPUT)
     {
-        hr = E_UNEXPECTED;
+        hr = VFW_E_CANNOT_CONNECT;
         goto out;
     }
 
@@ -822,7 +796,7 @@ static HRESULT GetFilterInfo(IMoniker* pMoniker, VARIANT* pvar)
         hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
 
     if (SUCCEEDED(hr))
-        TRACE("Moniker = %s\n", debugstr_w(V_UNION(pvar, bstrVal)));
+        TRACE("Moniker = %s\n", debugstr_w(V_BSTR(pvar)));
 
     if (pPropBagCat)
         IPropertyBag_Release(pPropBagCat);
@@ -910,9 +884,13 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
     CLSID FilterCLSID;
     PIN_DIRECTION dir;
     unsigned int i = 0;
+    IFilterMapper2 *pFilterMapper2 = NULL;
 
     TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
 
+    if(!ppinOut || !ppinIn)
+        return E_POINTER;
+
     if (TRACE_ON(quartz))
     {
         hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
@@ -996,10 +974,16 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
     TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
     TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
 
+    hr = IUnknown_QueryInterface(This->punkFilterMapper2, &IID_IFilterMapper2, (void**)&pFilterMapper2);
+    if (FAILED(hr)) {
+        WARN("Unable to get IFilterMapper2 (%x)\n", hr);
+        goto out;
+    }
+
     /* Try to find a suitable filter that can connect to the pin to render */
     tab[0] = mt->majortype;
     tab[1] = mt->subtype;
-    hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
+    hr = IFilterMapper2_EnumMatchingFilters(pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
     if (FAILED(hr)) {
         WARN("Unable to enum filters (%x)\n", hr);
         goto out;
@@ -1071,7 +1055,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
             }
         }
 
-        hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
+        hr = IFilterGraph2_AddFilter(iface, pfilter, V_BSTR(&var));
         if (FAILED(hr)) {
             WARN("Unable to add filter (%x)\n", hr);
             IBaseFilter_Release(pfilter);
@@ -1166,7 +1150,11 @@ error:
         CoTaskMemFree(ppins);
     }
 
+    IEnumMoniker_Release(pEnumMoniker);
+
 out:
+    if (pFilterMapper2)
+        IFilterMapper2_Release(pFilterMapper2);
     if (penummt)
         IEnumMediaTypes_Release(penummt);
     if (mt)
@@ -1262,6 +1250,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
     ULONG nb;
     IMoniker* pMoniker;
     INT x;
+    IFilterMapper2 *pFilterMapper2 = NULL;
 
     TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
 
@@ -1371,10 +1360,20 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
                 continue;
             }
 
+            if (pFilterMapper2 == NULL)
+            {
+                hr = IUnknown_QueryInterface(This->punkFilterMapper2, &IID_IFilterMapper2, (void**)&pFilterMapper2);
+                if (FAILED(hr))
+                {
+                    WARN("Unable to query IFilterMapper2 (%x)\n", hr);
+                    break;
+                }
+            }
+
             /* Try to find a suitable renderer with the same media type */
             tab[0] = mt->majortype;
             tab[1] = mt->subtype;
-            hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
+            hr = IFilterMapper2_EnumMatchingFilters(pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
             if (FAILED(hr))
             {
                 WARN("Unable to enum filters (%x)\n", hr);
@@ -1405,7 +1404,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
                 goto error;
             }
 
-            hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
+            hr = IFilterGraph2_AddFilter(iface, pfilter, V_BSTR(&var));
             if (FAILED(hr)) {
                 WARN("Unable to add filter (%x)\n", hr);
                 IBaseFilter_Release(pfilter);
@@ -1445,10 +1444,10 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
                 IPin_Release(ppinfilter);
 
                 if (FAILED(hr)) {
-                    WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
+                    WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_BSTR(&var)), hr);
                     goto error;
                 }
-                TRACE("Connected, recursing %s\n",  debugstr_w(V_UNION(&var, bstrVal)));
+                TRACE("Connected, recursing %s\n",  debugstr_w(V_BSTR(&var)));
 
                 VariantClear(&var);
 
@@ -1488,6 +1487,9 @@ error:
         hr = S_OK;
     }
 
+    if (pFilterMapper2)
+        IFilterMapper2_Release(pFilterMapper2);
+
     IEnumMediaTypes_Release(penummt);
     return hr;
 }
@@ -1502,7 +1504,7 @@ static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcw
     IEnumPins* penumpins = NULL;
     HRESULT hr;
     BOOL partial = FALSE;
-    HRESULT any = FALSE;
+    BOOL any = FALSE;
 
     TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
 
@@ -1680,7 +1682,7 @@ static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR
     }
 
     /* The file has been already loaded */
-    IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
+    hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
     if (FAILED(hr)) {
         WARN("GetCurFile (%x)\n", hr);
         goto error;
@@ -1737,8 +1739,27 @@ static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *ifac
         IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
 {
     IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
+    HRESULT hr;
+    IBaseFilter* pfilter;
 
-    TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
+    TRACE("(%p/%p)->(%p %p %s %p)\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
+
+    hr = IMoniker_BindToObject(pMoniker, pCtx, NULL, &IID_IBaseFilter, (void**)&pfilter);
+    if(FAILED(hr)) {
+        WARN("Unable to bind moniker to filter object (%x)\n", hr);
+        return hr;
+    }
+
+    hr = IFilterGraph2_AddFilter(iface, pfilter, lpcwstrFilterName);
+    if (FAILED(hr)) {
+        WARN("Unable to add filter (%x)\n", hr);
+        IBaseFilter_Release(pfilter);
+        return hr;
+    }
+
+    if(ppFilter)
+        *ppFilter = pfilter;
+    else IBaseFilter_Release(pfilter);
 
     return S_OK;
 }
@@ -2430,59 +2451,21 @@ static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *p
     return hr;
 }
 
-static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
+static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
+        const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
 {
     IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
-    HRESULT hr = S_OK;
 
-    TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
+    TRACE("(%p/%p)->(%p, %s, 0x%s, %s)\n", This, iface, pTarget,
+        debugstr_guid(pTargetFormat), wine_dbgstr_longlong(Source), debugstr_guid(pSourceFormat));
 
-    if (!pStop)
-        return E_POINTER;
+    if (!pSourceFormat)
+        pSourceFormat = &This->timeformatseek;
 
-    EnterCriticalSection(&This->cs);
-    if (This->stop_position < 0)
-        /* Stop position not set, use duration instead */
-        hr = IMediaSeeking_GetDuration(iface, pStop);
+    if (IsEqualGUID(pTargetFormat, pSourceFormat))
+        *pTarget = Source;
     else
-        *pStop = This->stop_position;
-    LeaveCriticalSection(&This->cs);
-
-    return hr;
-}
-
-static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
-{
-    IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
-    LONGLONG time = 0;
-
-    if (!pCurrent)
-        return E_POINTER;
-
-    EnterCriticalSection(&This->cs);
-    if (This->state == State_Running && This->refClock && This->start_time >= 0)
-    {
-        IReferenceClock_GetTime(This->refClock, &time);
-        if (time)
-            time -= This->start_time;
-    }
-    if (This->pause_time > 0)
-        time += This->pause_time;
-    *pCurrent = time;
-    LeaveCriticalSection(&This->cs);
-
-    TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
-
-    return S_OK;
-}
-
-static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
-        const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
-{
-    IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
-
-    FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
-        pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
+        FIXME("conversion %s->%s not supported\n", debugstr_guid(pSourceFormat), debugstr_guid(pTargetFormat));
 
     return S_OK;
 }
@@ -2517,11 +2500,6 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *
         (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
         FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
 
-    if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
-        This->stop_position = *pStop;
-    else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
-        FIXME("Stop position not handled yet!\n");
-
     if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
         IMediaControl_Pause(&This->IMediaControl_iface);
     args.current = pCurrent;
@@ -2539,16 +2517,68 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *
     return hr;
 }
 
+static HRESULT WINAPI found_getposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
+{
+    struct pos_args *args = (void*)pargs;
+
+    return IMediaSeeking_GetPositions(seek, args->current, args->stop);
+}
+
 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
         LONGLONG *pStop)
 {
     IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
+    struct pos_args args;
+    LONGLONG time = 0;
     HRESULT hr;
 
     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
-    hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
-    if (SUCCEEDED(hr))
-        hr = IMediaSeeking_GetStopPosition(iface, pStop);
+
+    args.current = pCurrent;
+    args.stop = pStop;
+    EnterCriticalSection(&This->cs);
+    hr = all_renderers_seek(This, found_getposition, (DWORD_PTR)&args);
+    if (This->state == State_Running && This->refClock && This->start_time >= 0)
+    {
+        IReferenceClock_GetTime(This->refClock, &time);
+        if (time)
+            time -= This->start_time;
+    }
+    if (This->pause_time > 0)
+        time += This->pause_time;
+    *pCurrent += time;
+    LeaveCriticalSection(&This->cs);
+
+    return hr;
+}
+
+static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
+{
+    LONGLONG time;
+    HRESULT hr;
+
+    if (!pCurrent)
+        return E_POINTER;
+
+    hr = MediaSeeking_GetPositions(iface, pCurrent, &time);
+
+    TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
+
+    return hr;
+}
+
+static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
+{
+    IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
+    LONGLONG time;
+    HRESULT hr;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
+
+    if (!pStop)
+        return E_POINTER;
+
+    hr = MediaSeeking_GetPositions(iface, &time, pStop);
 
     return hr;
 }
@@ -5278,7 +5308,7 @@ static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceC
                 IMediaEventSink *pEventSink;
                 HRESULT eshr;
 
-                eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
+                eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (void **)&pEventSink);
                 if (SUCCEEDED(eshr))
                 {
                     IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
@@ -5662,7 +5692,6 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     fimpl->nItfCacheEntries = 0;
     memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
     fimpl->start_time = fimpl->pause_time = 0;
-    fimpl->stop_position = -1;
     fimpl->punkFilterMapper2 = NULL;
     fimpl->recursioncount = 0;
     fimpl->version = 0;
@@ -5676,14 +5705,6 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
 
-    if (SUCCEEDED(hr))
-        hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2,
-                (void**)&fimpl->pFilterMapper2);
-
-    if (SUCCEEDED(hr))
-        /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
-        IUnknown_Release(fimpl->outer_unk);
-
     if (FAILED(hr)) {
         ERR("Unable to create filter mapper (%x)\n", hr);
         if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);