Maarten Lankhorst : quartz: Call send flush/ endofstream and segment messages downstream.
Alexandre Julliard
julliard at winehq.org
Wed Mar 19 07:28:21 CDT 2008
Module: wine
Branch: master
Commit: ebf6bbd50f40bb0616607b27fa1040285841a5ed
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ebf6bbd50f40bb0616607b27fa1040285841a5ed
Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Tue Mar 18 18:47:17 2008 -0700
quartz: Call send flush/endofstream and segment messages downstream.
---
dlls/quartz/pin.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 146 insertions(+), 10 deletions(-)
diff --git a/dlls/quartz/pin.c b/dlls/quartz/pin.c
index c895185..77dabf0 100644
--- a/dlls/quartz/pin.c
+++ b/dlls/quartz/pin.c
@@ -37,6 +37,105 @@ static const IPinVtbl PullPin_Vtbl;
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
#define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary)))
+typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg );
+
+/** Helper function, there are a lot of places where the error code is inherited
+ * The following rules apply:
+ *
+ * Return the first received error code (E_NOTIMPL is ignored)
+ * If no errors occur: return the first received non-error-code that isn't S_OK
+ */
+static HRESULT updatehres( HRESULT original, HRESULT new )
+{
+ if (FAILED( original ) || new == E_NOTIMPL)
+ return original;
+
+ if (FAILED( new ) || original == S_OK)
+ return new;
+
+ return original;
+}
+
+/** Sends a message from a pin further to other, similar pins
+ * fnMiddle is called on each pin found further on the stream.
+ * fnEnd (can be NULL) is called when the message can't be sent any further (this is a renderer or source)
+ *
+ * If the pin given is an input pin, the message will be sent downstream to other input pins
+ * If the pin given is an output pin, the message will be sent upstream to other output pins
+ */
+static HRESULT SendFurther( IPin *from, SendPinFunc fnMiddle, LPVOID arg, SendPinFunc fnEnd )
+{
+ PIN_INFO pin_info;
+ ULONG amount = 0;
+ HRESULT hr = S_OK;
+ HRESULT hr_return = S_OK;
+ IEnumPins *enumpins = NULL;
+ BOOL foundend = TRUE;
+ PIN_DIRECTION from_dir;
+
+ IPin_QueryDirection( from, &from_dir );
+
+ hr = IPin_QueryInternalConnections( from, NULL, &amount );
+ if (hr != E_NOTIMPL && amount)
+ FIXME("Use QueryInternalConnections!\n");
+ hr = S_OK;
+
+ pin_info.pFilter = NULL;
+ hr = IPin_QueryPinInfo( from, &pin_info );
+ if (FAILED(hr))
+ goto out;
+
+ hr = IBaseFilter_EnumPins( pin_info.pFilter, &enumpins );
+ if (FAILED(hr))
+ goto out;
+
+ hr = IEnumPins_Reset( enumpins );
+ while (hr == S_OK) {
+ IPin *pin = NULL;
+ hr = IEnumPins_Next( enumpins, 1, &pin, NULL );
+ if (hr == VFW_E_ENUM_OUT_OF_SYNC)
+ {
+ hr = IEnumPins_Reset( enumpins );
+ continue;
+ }
+ if (pin)
+ {
+ PIN_DIRECTION dir;
+
+ IPin_QueryDirection( pin, &dir );
+ if (dir != from_dir)
+ {
+ IPin *connected = NULL;
+
+ foundend = FALSE;
+ IPin_ConnectedTo( pin, &connected );
+ if (connected)
+ {
+ HRESULT hr_local;
+
+ hr_local = fnMiddle( pin, arg );
+ hr_return = updatehres( hr_return, hr_local );
+ IPin_Release(connected);
+ }
+ }
+ IPin_Release( pin );
+ }
+ } while (hr == S_OK);
+ if (!foundend)
+ hr = hr_return;
+ else if (fnEnd) {
+ HRESULT hr_local;
+
+ hr_local = fnEnd( from, arg );
+ hr_return = updatehres( hr_return, hr_local );
+ }
+
+out:
+ if (pin_info.pFilter)
+ IBaseFilter_Release( pin_info.pFilter );
+ return hr;
+}
+
static inline InputPin *impl_from_IMemInputPin( IMemInputPin *iface )
{
return (InputPin *)((char*)iface - FIELD_OFFSET(InputPin, lpVtblMemInput));
@@ -488,36 +587,73 @@ HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, cons
return hr;
}
+static HRESULT deliver_endofstream(IPin* pin, LPVOID unused)
+{
+ return IPin_EndOfStream( pin );
+}
+
HRESULT WINAPI InputPin_EndOfStream(IPin * iface)
{
- TRACE("()\n");
+ FIXME("() stub\n");
- return S_OK;
+ /* Should do an end of stream notification?
+ * Also, don't accept any more samples from now!
+ * TODO: Don't accept any more packets
+ */
+
+ return SendFurther( iface, deliver_endofstream, NULL, NULL );
+}
+
+static HRESULT deliver_beginflush(IPin* pin, LPVOID unused)
+{
+ return IPin_BeginFlush( pin );
}
HRESULT WINAPI InputPin_BeginFlush(IPin * iface)
{
- FIXME("()\n");
- return E_NOTIMPL;
+ FIXME("() stub\n");
+
+ /* TODO: Drop all cached packets, and don't accept any more samples! */
+ return SendFurther( iface, deliver_beginflush, NULL, NULL );
+}
+
+static HRESULT deliver_endflush(IPin* pin, LPVOID unused)
+{
+ return IPin_EndFlush( pin );
}
HRESULT WINAPI InputPin_EndFlush(IPin * iface)
{
- FIXME("()\n");
- return E_NOTIMPL;
+ FIXME("() stub\n");
+
+ /* TODO: Accept any samples again */
+ return SendFurther( iface, deliver_endflush, NULL, NULL );
+}
+
+typedef struct newsegmentargs
+{
+ REFERENCE_TIME tStart, tStop;
+ double rate;
+} newsegmentargs;
+
+static HRESULT deliver_newsegment(IPin *pin, LPVOID data)
+{
+ newsegmentargs *args = data;
+ return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate);
}
HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
InputPin *This = (InputPin *)iface;
+ newsegmentargs args;
TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate);
- This->tStart = tStart;
- This->tStop = tStop;
- This->dRate = dRate;
+ args.tStart = This->tStart = tStart;
+ args.tStop = This->tStop = tStop;
+ args.rate = This->dRate = dRate;
- return S_OK;
+ return SendFurther( iface, deliver_newsegment, &args, NULL );
}
static const IPinVtbl InputPin_Vtbl =
More information about the wine-cvs
mailing list