[QUARTZ]
[reactos.git] / reactos / dll / directx / wine / quartz / filtergraph.c
index b8c1204..9121a21 100644 (file)
@@ -155,7 +155,6 @@ typedef struct _IFilterGraphImpl {
     IUnknown *outer_unk;
     LONG ref;
     IUnknown *punkFilterMapper2;
-    IFilterMapper2 * pFilterMapper2;
     IBaseFilter ** ppFiltersInGraph;
     LPWSTR * pFilterNames;
     ULONG nFilters;
@@ -180,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;
@@ -244,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);
@@ -298,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);
@@ -590,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);
@@ -600,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;
     }
 
@@ -889,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);
@@ -975,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;
@@ -1145,7 +1150,11 @@ error:
         CoTaskMemFree(ppins);
     }
 
+    IEnumMoniker_Release(pEnumMoniker);
+
 out:
+    if (pFilterMapper2)
+        IFilterMapper2_Release(pFilterMapper2);
     if (penummt)
         IEnumMediaTypes_Release(penummt);
     if (mt)
@@ -1241,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);
 
@@ -1350,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);
@@ -1467,6 +1487,9 @@ error:
         hr = S_OK;
     }
 
+    if (pFilterMapper2)
+        IFilterMapper2_Release(pFilterMapper2);
+
     IEnumMediaTypes_Release(penummt);
     return hr;
 }
@@ -1716,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;
 }
@@ -2409,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;
 }
@@ -2496,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;
@@ -2518,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;
 }
@@ -5641,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;
@@ -5655,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);