Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/qedit/mediadet.c | 30 +++++- dlls/qedit/tests/mediadet.c | 180 ++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+), 2 deletions(-)
diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c index 8119015..5ee621b 100644 --- a/dlls/qedit/mediadet.c +++ b/dlls/qedit/mediadet.c @@ -568,8 +568,34 @@ static HRESULT WINAPI MediaDet_get_StreamTypeB(IMediaDet* iface, BSTR *pVal) static HRESULT WINAPI MediaDet_get_StreamLength(IMediaDet* iface, double *pVal) { MediaDetImpl *This = impl_from_IMediaDet(iface); - FIXME("(%p): stub!\n", This); - return VFW_E_INVALIDMEDIATYPE; + IMediaSeeking *seeking; + HRESULT hr; + + TRACE("(%p)\n", This); + + if (!pVal) + return E_POINTER; + + if (!This->cur_pin) + return E_INVALIDARG; + + hr = IPin_QueryInterface(This->cur_pin, &IID_IMediaSeeking, (void **) &seeking); + if (SUCCEEDED(hr)) + { + LONGLONG duration; + + hr = IMediaSeeking_GetDuration(seeking, &duration); + if (SUCCEEDED(hr)) + { + hr = IMediaSeeking_ConvertTimeFormat(seeking, &duration, &TIME_FORMAT_MEDIA_TIME, duration, NULL); + if (SUCCEEDED(hr)) + *pVal = (REFTIME)duration / 10000000; + } + IMediaSeeking_Release(seeking); + return hr; + } + + return hr; }
static HRESULT WINAPI MediaDet_get_Filename(IMediaDet* iface, BSTR *pVal) diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c index 04efc18..95d3208 100644 --- a/dlls/qedit/tests/mediadet.c +++ b/dlls/qedit/tests/mediadet.c @@ -75,6 +75,7 @@ static IUnknown test_outer = {&outer_vtbl}; struct testfilter { IBaseFilter IBaseFilter_iface; + IMediaSeeking IMediaSeeking_iface; LONG ref; WCHAR *name; IFilterGraph *graph; @@ -198,6 +199,8 @@ static HRESULT WINAPI testpin_QueryInterface(IPin *iface, REFIID iid, void **out
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IPin)) *out = &filter->IPin_iface; + else if (IsEqualGUID(iid, &IID_IMediaSeeking)) + *out = &filter->IMediaSeeking_iface; else { *out = NULL; @@ -461,6 +464,169 @@ static const IEnumPinsVtbl testenumpins_vtbl = testenumpins_Clone };
+static inline struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface); +} + +static HRESULT WINAPI testseek_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IBaseFilter_QueryInterface(&filter->IBaseFilter_iface, iid, out); +} + +static ULONG WINAPI testseek_AddRef(IMediaSeeking *iface) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IBaseFilter_AddRef(&filter->IBaseFilter_iface); +} + +static ULONG WINAPI testseek_Release(IMediaSeeking *iface) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IBaseFilter_Release(&filter->IBaseFilter_iface); +} + +static HRESULT WINAPI testseek_GetCapabilities(IMediaSeeking *iface, DWORD *caps) +{ + if (winetest_debug > 1) trace("IMediaSeeking_GetCapabilities()\n"); + + *caps = AM_SEEKING_CanGetDuration; + return S_OK; +} + +static HRESULT WINAPI testseek_CheckCapabilities(IMediaSeeking *iface, DWORD *caps) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_IsFormatSupported(IMediaSeeking *iface, const GUID *format) +{ + if (winetest_debug > 1) trace("IMediaSeeking_IsFormatSupported(%s)\n", wine_dbgstr_guid(format)); + + return IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE; +} + +static HRESULT WINAPI testseek_QueryPreferredFormat(IMediaSeeking *iface, GUID *format) +{ + if (winetest_debug > 1) trace("IMediaSeeking_QueryPreferredFormat()\n"); + + *format = TIME_FORMAT_MEDIA_TIME; + return S_OK; +} + +static HRESULT WINAPI testseek_GetTimeFormat(IMediaSeeking *iface, GUID *format) +{ + if (winetest_debug > 1) trace("IMediaSeeking_GetTimeFormat()\n"); + + *format = TIME_FORMAT_MEDIA_TIME; + return S_OK; +} + +static HRESULT WINAPI testseek_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format) +{ + if (winetest_debug > 1) trace("IMediaSeeking_IsUsingTimeFormat(%s)\n", wine_dbgstr_guid(format)); + + return IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE; +} + +static HRESULT WINAPI testseek_SetTimeFormat(IMediaSeeking *iface, const GUID *format) +{ + if (winetest_debug > 1) trace("IMediaSeeking_SetTimeFormat(%s)\n", wine_dbgstr_guid(format)); + + return IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME) ? S_OK : E_INVALIDARG; +} + +static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *duration) +{ + if (winetest_debug > 1) trace("IMediaSeeking_GetDuration()\n"); + + *duration = 42000000; + return S_OK; +} + +static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target, + const GUID *target_format, LONGLONG source, const GUID *source_format) +{ + if (winetest_debug > 1) + trace("IMediaSeeking_ConvertTimeFormat(%s: %s -> %s)\n", wine_dbgstr_longlong(source), + wine_dbgstr_guid(source_format), wine_dbgstr_guid(target_format)); + + if (source_format && !IsEqualGUID(source_format, &TIME_FORMAT_MEDIA_TIME)) + return E_INVALIDARG; + if (target_format && !IsEqualGUID(target_format, &TIME_FORMAT_MEDIA_TIME)) + return E_INVALIDARG; + + *target = source; + return S_OK; +} + +static HRESULT WINAPI testseek_SetPositions(IMediaSeeking *iface, LONGLONG *current, + DWORD current_flags, LONGLONG *stop, DWORD stop_flags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_SetRate(IMediaSeeking *iface, double rate) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetRate(IMediaSeeking *iface, double *rate) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll) +{ + return E_NOTIMPL; +} + +static const IMediaSeekingVtbl testseek_vtbl = +{ + testseek_QueryInterface, + testseek_AddRef, + testseek_Release, + testseek_GetCapabilities, + testseek_CheckCapabilities, + testseek_IsFormatSupported, + testseek_QueryPreferredFormat, + testseek_GetTimeFormat, + testseek_IsUsingTimeFormat, + testseek_SetTimeFormat, + testseek_GetDuration, + testseek_GetStopPosition, + testseek_GetCurrentPosition, + testseek_ConvertTimeFormat, + testseek_SetPositions, + testseek_GetPositions, + testseek_GetAvailable, + testseek_SetRate, + testseek_GetRate, + testseek_GetPreroll +}; + static inline struct testfilter *impl_from_IBaseFilter(IBaseFilter *iface) { return CONTAINING_RECORD(iface, struct testfilter, IBaseFilter_iface); @@ -479,6 +645,8 @@ static HRESULT WINAPI testfilter_QueryInterface(IBaseFilter *iface, REFIID iid, { *out = &filter->IBaseFilter_iface; } + else if (IsEqualGUID(iid, &IID_IMediaSeeking)) + *out = &filter->IMediaSeeking_iface; else { if (IsEqualGUID(iid, &IID_IFileSourceFilter)) ok(0, "Filter queried for IFileSourceFilter\n"); @@ -645,6 +813,7 @@ static IBaseFilter *create_testfilter(void)
memset(filter, 0, sizeof(*filter)); filter->IBaseFilter_iface.lpVtbl = &testfilter_vtbl; + filter->IMediaSeeking_iface.lpVtbl = &testseek_vtbl; filter->IEnumPins_iface.lpVtbl = &testenumpins_vtbl; filter->IPin_iface.lpVtbl = &testpin_vtbl; filter->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl; @@ -784,6 +953,7 @@ static void test_mediadet(void) BSTR bstr; IPin *pin; AM_MEDIA_TYPE mt, *pmt; + double duration; IUnknown *unk; double fps; int flags; @@ -846,6 +1016,12 @@ static void test_mediadet(void) hr = IMediaDet_get_StreamTypeB(pM, NULL); ok(hr == E_INVALIDARG, "IMediaDet_get_StreamTypeB failed: %08x\n", hr);
+ hr = IMediaDet_get_StreamLength(pM, &duration); + ok(hr == E_INVALIDARG, "IMediaDet_get_StreamLength failed: %08x\n", hr); + + hr = IMediaDet_get_StreamLength(pM, NULL); + ok(hr == E_POINTER, "IMediaDet_get_StreamLength failed: %08x\n", hr); + hr = IMediaDet_get_Filter(pM, NULL); ok(hr == E_POINTER, "IMediaDet_get_Filter failed: %08x\n", hr);
@@ -1133,6 +1309,10 @@ static void test_mediadet(void) ok(hr == S_OK, "IMediaDet_get_OutputStreams failed: %08x\n", hr); ok(nstrms == 1, "IMediaDet_get_OutputStreams: nstrms is %i\n", nstrms);
+ hr = IMediaDet_get_StreamLength(pM, &duration); + ok(hr == S_OK, "IMediaDet_get_StreamLength failed: %08x\n", hr); + ok(duration == 4.2, "Wrong duration %.16e\n", duration); + /* Now use the filter obtained from put_Filename for put_Filter. */ hr = IMediaDet_put_Filter(pM, (IUnknown*)filter); ok(hr == S_OK, "IMediaDet_put_Filter failed: %08x\n", hr);