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