2 * Filter Seeking and Control Interfaces
4 * Copyright 2003 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /* FIXME: critical sections */
22 #include "quartz_private.h"
23 #include "control_private.h"
26 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
32 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl;
34 typedef struct PassThruImpl {
35 const ISeekingPassThruVtbl *IPassThru_vtbl;
36 const IUnknownVtbl *IInner_vtbl;
37 const IMediaSeekingVtbl *IMediaSeeking_vtbl;
45 CRITICAL_SECTION time_cs;
47 REFERENCE_TIME time_earliest;
50 static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface,
53 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
54 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
56 if (This->bAggregatable)
57 This->bUnkOuterValid = TRUE;
59 if (IsEqualGUID(&IID_IUnknown, riid))
61 *ppvObj = &(This->IInner_vtbl);
62 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
63 } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) {
64 *ppvObj = &(This->IPassThru_vtbl);
65 TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj);
66 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
67 *ppvObj = &(This->IMediaSeeking_vtbl);
68 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
71 FIXME("unknown interface %s\n", debugstr_guid(riid));
75 IUnknown_AddRef((IUnknown *)(*ppvObj));
79 static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) {
80 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
81 ULONG ref = InterlockedIncrement(&This->ref);
83 TRACE("(%p)->(): new ref = %d\n", This, ref);
88 static ULONG WINAPI SeekInner_Release(IUnknown * iface) {
89 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
90 ULONG ref = InterlockedDecrement(&This->ref);
92 TRACE("(%p)->(): new ref = %d\n", This, ref);
96 This->time_cs.DebugInfo->Spare[0] = 0;
97 DeleteCriticalSection(&This->time_cs);
103 static const IUnknownVtbl IInner_VTable =
105 SeekInner_QueryInterface,
110 /* Generic functions for aggregation */
111 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
113 if (This->bAggregatable)
114 This->bUnkOuterValid = TRUE;
118 if (This->bAggregatable)
119 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
121 if (IsEqualIID(riid, &IID_IUnknown))
125 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
126 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
127 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
128 This->bAggregatable = TRUE;
133 return E_NOINTERFACE;
136 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
139 static ULONG SeekOuter_AddRef(PassThruImpl *This)
141 if (This->pUnkOuter && This->bUnkOuterValid)
142 return IUnknown_AddRef(This->pUnkOuter);
143 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
146 static ULONG SeekOuter_Release(PassThruImpl *This)
148 if (This->pUnkOuter && This->bUnkOuterValid)
149 return IUnknown_Release(This->pUnkOuter);
150 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
153 static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj)
155 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
157 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
159 return SeekOuter_QueryInterface(This, riid, ppvObj);
162 static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface)
164 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
166 TRACE("(%p/%p)->()\n", This, iface);
168 return SeekOuter_AddRef(This);
171 static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface)
173 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
175 TRACE("(%p/%p)->()\n", This, iface);
177 return SeekOuter_Release(This);
180 static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin)
182 ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface);
184 TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin);
187 FIXME("Re-initializing?\n");
189 This->renderer = renderer;
195 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
197 SeekingPassThru_QueryInterface,
198 SeekingPassThru_AddRef,
199 SeekingPassThru_Release,
203 HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj)
207 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
209 *ppObj = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
211 return E_OUTOFMEMORY;
213 fimpl->pUnkOuter = pUnkOuter;
214 fimpl->bUnkOuterValid = FALSE;
215 fimpl->bAggregatable = FALSE;
216 fimpl->IInner_vtbl = &IInner_VTable;
217 fimpl->IPassThru_vtbl = &ISeekingPassThru_Vtbl;
218 fimpl->IMediaSeeking_vtbl = &IMediaSeekingPassThru_Vtbl;
221 fimpl->timevalid = 0;
222 InitializeCriticalSection(&fimpl->time_cs);
223 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
227 typedef HRESULT (*SeekFunc)( IMediaSeeking *to, LPVOID arg );
229 static HRESULT ForwardCmdSeek( PCRITICAL_SECTION crit_sect, IBaseFilter* from, SeekFunc fnSeek, LPVOID arg )
232 HRESULT hr_return = S_OK;
233 IEnumPins *enumpins = NULL;
234 BOOL foundend = FALSE, allnotimpl = TRUE;
236 hr = IBaseFilter_EnumPins( from, &enumpins );
240 hr = IEnumPins_Reset( enumpins );
243 hr = IEnumPins_Next( enumpins, 1, &pin, NULL );
244 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
246 hr = IEnumPins_Reset( enumpins );
253 IPin_QueryDirection( pin, &dir );
254 if (dir == PINDIR_INPUT)
256 IPin *connected = NULL;
258 IPin_ConnectedTo( pin, &connected );
262 IMediaSeeking *seek = NULL;
264 hr_local = IPin_QueryInterface( connected, &IID_IMediaSeeking, (void**)&seek );
265 if (hr_local == S_OK)
270 LeaveCriticalSection( crit_sect );
271 hr_local = fnSeek( seek , arg );
272 EnterCriticalSection( crit_sect );
275 hr_local = fnSeek( seek , arg );
277 if (hr_local != E_NOTIMPL)
280 hr_return = updatehres( hr_return, hr_local );
281 IMediaSeeking_Release( seek );
283 IPin_Release(connected);
289 IEnumPins_Release( enumpins );
291 if (foundend && allnotimpl)
297 TRACE("Returning: %08x\n", hr);
302 HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeCurrent, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking, PCRITICAL_SECTION crit_sect)
304 assert(fnChangeStop && fnChangeCurrent && fnChangeRate);
306 pSeeking->refCount = 1;
307 pSeeking->pUserData = pUserData;
308 pSeeking->fnChangeRate = fnChangeRate;
309 pSeeking->fnChangeStop = fnChangeStop;
310 pSeeking->fnChangeCurrent = fnChangeCurrent;
311 pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards |
312 AM_SEEKING_CanSeekBackwards |
313 AM_SEEKING_CanSeekAbsolute |
314 AM_SEEKING_CanGetStopPos |
315 AM_SEEKING_CanGetDuration;
316 pSeeking->llCurrent = 0;
317 pSeeking->llStop = ((ULONGLONG)0x80000000) << 32;
318 pSeeking->llDuration = pSeeking->llStop;
319 pSeeking->dRate = 1.0;
320 pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME;
321 pSeeking->crst = crit_sect;
327 LONGLONG* current, *stop;
328 DWORD curflags, stopflags;
331 static HRESULT fwd_setposition(IMediaSeeking *seek, LPVOID pargs)
333 struct pos_args *args = (void*)pargs;
335 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
338 static HRESULT fwd_checkcaps(IMediaSeeking *iface, LPVOID pcaps)
341 return IMediaSeeking_CheckCapabilities(iface, caps);
344 static HRESULT fwd_settimeformat(IMediaSeeking *iface, LPVOID pformat)
346 const GUID *format = pformat;
347 return IMediaSeeking_SetTimeFormat(iface, format);
350 static HRESULT fwd_getduration(IMediaSeeking *iface, LPVOID pdur)
352 LONGLONG *duration = pdur;
353 LONGLONG mydur = *duration;
356 hr = IMediaSeeking_GetDuration(iface, &mydur);
360 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
365 static HRESULT fwd_getstopposition(IMediaSeeking *iface, LPVOID pdur)
367 LONGLONG *duration = pdur;
368 LONGLONG mydur = *duration;
371 hr = IMediaSeeking_GetStopPosition(iface, &mydur);
375 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
380 static HRESULT fwd_getcurposition(IMediaSeeking *iface, LPVOID pdur)
382 LONGLONG *duration = pdur;
383 LONGLONG mydur = *duration;
386 hr = IMediaSeeking_GetCurrentPosition(iface, &mydur);
390 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
395 static HRESULT fwd_setrate(IMediaSeeking *iface, LPVOID prate)
397 double *rate = prate;
401 hr = IMediaSeeking_SetRate(iface, *rate);
409 HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
411 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
413 TRACE("(%p)\n", pCapabilities);
415 *pCapabilities = This->dwCapabilities;
420 HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
422 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
426 TRACE("(%p)\n", pCapabilities);
431 EnterCriticalSection(This->crst);
432 hr = ForwardCmdSeek(This->crst, This->pUserData, fwd_checkcaps, pCapabilities);
433 LeaveCriticalSection(This->crst);
434 if (FAILED(hr) && hr != E_NOTIMPL)
437 dwCommonCaps = *pCapabilities & This->dwCapabilities;
442 hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE;
443 *pCapabilities = dwCommonCaps;
448 HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
450 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
452 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
455 HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
457 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
459 *pFormat = TIME_FORMAT_MEDIA_TIME;
463 HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
465 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
466 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
468 EnterCriticalSection(This->crst);
469 *pFormat = This->timeformat;
470 LeaveCriticalSection(This->crst);
475 HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
477 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
480 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
482 EnterCriticalSection(This->crst);
483 if (!IsEqualIID(pFormat, &This->timeformat))
485 LeaveCriticalSection(This->crst);
491 HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
493 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
494 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
496 EnterCriticalSection(This->crst);
497 ForwardCmdSeek(This->crst, This->pUserData, fwd_settimeformat, (LPVOID)pFormat);
498 LeaveCriticalSection(This->crst);
500 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
504 HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
506 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
508 TRACE("(%p)\n", pDuration);
510 EnterCriticalSection(This->crst);
511 *pDuration = This->llDuration;
512 ForwardCmdSeek(This->crst, This->pUserData, fwd_getduration, pDuration);
513 LeaveCriticalSection(This->crst);
518 HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
520 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
522 TRACE("(%p)\n", pStop);
524 EnterCriticalSection(This->crst);
525 *pStop = This->llStop;
526 ForwardCmdSeek(This->crst, This->pUserData, fwd_getstopposition, pStop);
527 LeaveCriticalSection(This->crst);
532 /* FIXME: Make use of the info the filter should expose */
533 HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
535 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
537 TRACE("(%p)\n", pCurrent);
539 EnterCriticalSection(This->crst);
540 *pCurrent = This->llCurrent;
541 ForwardCmdSeek(This->crst, This->pUserData, fwd_getcurposition, pCurrent);
542 LeaveCriticalSection(This->crst);
547 HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
549 if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
554 /* FIXME: clear pTarget? */
558 static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
560 switch (dwFlags & AM_SEEKING_PositioningBitsMask)
562 case AM_SEEKING_NoPositioning:
564 case AM_SEEKING_AbsolutePositioning:
566 case AM_SEEKING_RelativePositioning:
567 case AM_SEEKING_IncrementalPositioning:
568 return value + *pModifier;
575 HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
577 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
578 BOOL bChangeCurrent = FALSE, bChangeStop = FALSE;
579 LONGLONG llNewCurrent, llNewStop;
580 struct pos_args args;
582 TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
584 args.current = pCurrent;
586 args.curflags = dwCurrentFlags;
587 args.stopflags = dwStopFlags;
589 EnterCriticalSection(This->crst);
591 llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags);
592 llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
595 bChangeCurrent = TRUE;
596 if (llNewStop != This->llStop)
599 TRACE("Old: %u, New: %u\n", (DWORD)(This->llCurrent/10000000), (DWORD)(llNewCurrent/10000000));
601 This->llCurrent = llNewCurrent;
602 This->llStop = llNewStop;
604 if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime))
605 *pCurrent = llNewCurrent;
606 if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime))
609 ForwardCmdSeek(This->crst, This->pUserData, fwd_setposition, &args);
610 LeaveCriticalSection(This->crst);
613 This->fnChangeCurrent(This->pUserData);
615 This->fnChangeStop(This->pUserData);
620 HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
622 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
624 TRACE("(%p, %p)\n", pCurrent, pStop);
626 EnterCriticalSection(This->crst);
627 IMediaSeeking_GetCurrentPosition(iface, pCurrent);
628 IMediaSeeking_GetStopPosition(iface, pStop);
629 LeaveCriticalSection(This->crst);
634 HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
636 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
638 TRACE("(%p, %p)\n", pEarliest, pLatest);
640 EnterCriticalSection(This->crst);
642 *pLatest = This->llDuration;
643 LeaveCriticalSection(This->crst);
648 HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
650 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
651 BOOL bChangeRate = (dRate != This->dRate);
654 TRACE("(%e)\n", dRate);
656 if (dRate > 100 || dRate < .001)
658 FIXME("Excessive rate %e, ignoring\n", dRate);
659 return VFW_E_UNSUPPORTED_AUDIO;
662 EnterCriticalSection(This->crst);
665 hr = This->fnChangeRate(This->pUserData);
666 ForwardCmdSeek(This->crst, This->pUserData, fwd_setrate, &dRate);
667 LeaveCriticalSection(This->crst);
672 HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
674 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
676 TRACE("(%p)\n", dRate);
678 EnterCriticalSection(This->crst);
680 *dRate = This->dRate;
681 LeaveCriticalSection(This->crst);
686 HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
688 TRACE("(%p)\n", pPreroll);
694 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
696 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
698 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
700 return SeekOuter_QueryInterface(This, riid, ppvObj);
703 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
705 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
707 TRACE("(%p/%p)->()\n", iface, This);
709 return SeekOuter_AddRef(This);
712 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
714 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
716 TRACE("(%p/%p)->()\n", iface, This);
718 return SeekOuter_Release(This);
721 static HRESULT get_connected(PassThruImpl *This, IMediaSeeking **seek) {
725 hr = IPin_ConnectedTo(This->pin, &pin);
728 hr = IPin_QueryInterface(pin, &IID_IMediaSeeking, (void**)seek);
735 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
737 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
740 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
741 hr = get_connected(This, &seek);
743 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
744 IMediaSeeking_Release(seek);
749 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
751 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
754 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
755 hr = get_connected(This, &seek);
757 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
758 IMediaSeeking_Release(seek);
763 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
765 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
768 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
769 hr = get_connected(This, &seek);
771 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
772 IMediaSeeking_Release(seek);
777 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
779 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
782 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
783 hr = get_connected(This, &seek);
785 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
786 IMediaSeeking_Release(seek);
791 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
793 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
796 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
797 hr = get_connected(This, &seek);
799 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
800 IMediaSeeking_Release(seek);
805 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
807 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
810 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
811 hr = get_connected(This, &seek);
813 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
814 IMediaSeeking_Release(seek);
819 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
821 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
824 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
825 hr = get_connected(This, &seek);
827 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
828 IMediaSeeking_Release(seek);
833 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
835 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
838 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
839 hr = get_connected(This, &seek);
841 hr = IMediaSeeking_GetDuration(seek, pDuration);
842 IMediaSeeking_Release(seek);
847 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
849 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
852 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
853 hr = get_connected(This, &seek);
855 hr = IMediaSeeking_GetStopPosition(seek, pStop);
856 IMediaSeeking_Release(seek);
861 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
863 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
866 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
869 EnterCriticalSection(&This->time_cs);
871 *pCurrent = This->time_earliest;
874 LeaveCriticalSection(&This->time_cs);
876 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
879 hr = get_connected(This, &seek);
881 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
882 IMediaSeeking_Release(seek);
887 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
889 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
892 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
893 hr = get_connected(This, &seek);
895 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
896 IMediaSeeking_Release(seek);
901 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
903 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
906 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
907 hr = get_connected(This, &seek);
909 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
910 IMediaSeeking_Release(seek);
915 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
917 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
920 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
921 hr = get_connected(This, &seek);
923 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
924 IMediaSeeking_Release(seek);
929 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
931 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
934 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
935 hr = get_connected(This, &seek);
937 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
938 IMediaSeeking_Release(seek);
943 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
945 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
948 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
949 hr = get_connected(This, &seek);
951 hr = IMediaSeeking_SetRate(seek, dRate);
952 IMediaSeeking_Release(seek);
957 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
959 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
962 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
963 hr = get_connected(This, &seek);
965 hr = IMediaSeeking_GetRate(seek, dRate);
966 IMediaSeeking_Release(seek);
971 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
973 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
976 TRACE("(%p)\n", pPreroll);
977 hr = get_connected(This, &seek);
979 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
980 IMediaSeeking_Release(seek);
985 void MediaSeekingPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) {
986 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
987 EnterCriticalSection(&This->time_cs);
988 This->time_earliest = start;
990 LeaveCriticalSection(&This->time_cs);
993 void MediaSeekingPassThru_ResetMediaTime(IUnknown *iface) {
994 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
995 EnterCriticalSection(&This->time_cs);
997 LeaveCriticalSection(&This->time_cs);
1000 void MediaSeekingPassThru_EOS(IUnknown *iface) {
1001 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
1002 REFERENCE_TIME time;
1004 hr = IMediaSeeking_GetStopPosition((IMediaSeeking*)&This->IMediaSeeking_vtbl, &time);
1005 EnterCriticalSection(&This->time_cs);
1006 if (SUCCEEDED(hr)) {
1007 This->timevalid = 1;
1008 This->time_earliest = time;
1010 This->timevalid = 0;
1011 LeaveCriticalSection(&This->time_cs);
1014 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
1016 MediaSeekingPassThru_QueryInterface,
1017 MediaSeekingPassThru_AddRef,
1018 MediaSeekingPassThru_Release,
1019 MediaSeekingPassThru_GetCapabilities,
1020 MediaSeekingPassThru_CheckCapabilities,
1021 MediaSeekingPassThru_IsFormatSupported,
1022 MediaSeekingPassThru_QueryPreferredFormat,
1023 MediaSeekingPassThru_GetTimeFormat,
1024 MediaSeekingPassThru_IsUsingTimeFormat,
1025 MediaSeekingPassThru_SetTimeFormat,
1026 MediaSeekingPassThru_GetDuration,
1027 MediaSeekingPassThru_GetStopPosition,
1028 MediaSeekingPassThru_GetCurrentPosition,
1029 MediaSeekingPassThru_ConvertTimeFormat,
1030 MediaSeekingPassThru_SetPositions,
1031 MediaSeekingPassThru_GetPositions,
1032 MediaSeekingPassThru_GetAvailable,
1033 MediaSeekingPassThru_SetRate,
1034 MediaSeekingPassThru_GetRate,
1035 MediaSeekingPassThru_GetPreroll