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 static HRESULT WINAPI
MediaSeekingPassThru_QueryInterface(IMediaSeeking
*iface
, REFIID riid
, LPVOID
*ppvObj
)
229 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
231 TRACE("(%p/%p)->(%s (%p), %p)\n", This
, iface
, debugstr_guid(riid
), riid
, ppvObj
);
233 return SeekOuter_QueryInterface(This
, riid
, ppvObj
);
236 static ULONG WINAPI
MediaSeekingPassThru_AddRef(IMediaSeeking
*iface
)
238 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
240 TRACE("(%p/%p)->()\n", iface
, This
);
242 return SeekOuter_AddRef(This
);
245 static ULONG WINAPI
MediaSeekingPassThru_Release(IMediaSeeking
*iface
)
247 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
249 TRACE("(%p/%p)->()\n", iface
, This
);
251 return SeekOuter_Release(This
);
254 static HRESULT
get_connected(PassThruImpl
*This
, IMediaSeeking
**seek
) {
258 hr
= IPin_ConnectedTo(This
->pin
, &pin
);
260 return VFW_E_NOT_CONNECTED
;
261 hr
= IPin_QueryInterface(pin
, &IID_IMediaSeeking
, (void**)seek
);
268 static HRESULT WINAPI
MediaSeekingPassThru_GetCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
270 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
273 TRACE("(%p/%p)->(%p)\n", iface
, This
, pCapabilities
);
274 hr
= get_connected(This
, &seek
);
276 hr
= IMediaSeeking_GetCapabilities(seek
, pCapabilities
);
277 IMediaSeeking_Release(seek
);
284 static HRESULT WINAPI
MediaSeekingPassThru_CheckCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
286 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
289 TRACE("(%p/%p)->(%p)\n", iface
, This
, pCapabilities
);
290 hr
= get_connected(This
, &seek
);
292 hr
= IMediaSeeking_CheckCapabilities(seek
, pCapabilities
);
293 IMediaSeeking_Release(seek
);
300 static HRESULT WINAPI
MediaSeekingPassThru_IsFormatSupported(IMediaSeeking
* iface
, const GUID
* pFormat
)
302 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
305 TRACE("(%p/%p)->(%s)\n", iface
, This
, qzdebugstr_guid(pFormat
));
306 hr
= get_connected(This
, &seek
);
308 hr
= IMediaSeeking_IsFormatSupported(seek
, pFormat
);
309 IMediaSeeking_Release(seek
);
316 static HRESULT WINAPI
MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking
* iface
, GUID
* pFormat
)
318 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
321 TRACE("(%p/%p)->(%p)\n", iface
, This
, pFormat
);
322 hr
= get_connected(This
, &seek
);
324 hr
= IMediaSeeking_QueryPreferredFormat(seek
, pFormat
);
325 IMediaSeeking_Release(seek
);
332 static HRESULT WINAPI
MediaSeekingPassThru_GetTimeFormat(IMediaSeeking
* iface
, GUID
* pFormat
)
334 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
337 TRACE("(%p/%p)->(%p)\n", iface
, This
, pFormat
);
338 hr
= get_connected(This
, &seek
);
340 hr
= IMediaSeeking_GetTimeFormat(seek
, pFormat
);
341 IMediaSeeking_Release(seek
);
348 static HRESULT WINAPI
MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
350 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
353 TRACE("(%p/%p)->(%s)\n", iface
, This
, qzdebugstr_guid(pFormat
));
354 hr
= get_connected(This
, &seek
);
356 hr
= IMediaSeeking_IsUsingTimeFormat(seek
, pFormat
);
357 IMediaSeeking_Release(seek
);
364 static HRESULT WINAPI
MediaSeekingPassThru_SetTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
366 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
369 TRACE("(%p/%p)->(%s)\n", iface
, This
, qzdebugstr_guid(pFormat
));
370 hr
= get_connected(This
, &seek
);
372 hr
= IMediaSeeking_SetTimeFormat(seek
, pFormat
);
373 IMediaSeeking_Release(seek
);
380 static HRESULT WINAPI
MediaSeekingPassThru_GetDuration(IMediaSeeking
* iface
, LONGLONG
* pDuration
)
382 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
385 TRACE("(%p/%p)->(%p)\n", iface
, This
, pDuration
);
386 hr
= get_connected(This
, &seek
);
388 hr
= IMediaSeeking_GetDuration(seek
, pDuration
);
389 IMediaSeeking_Release(seek
);
396 static HRESULT WINAPI
MediaSeekingPassThru_GetStopPosition(IMediaSeeking
* iface
, LONGLONG
* pStop
)
398 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
401 TRACE("(%p/%p)->(%p)\n", iface
, This
, pStop
);
402 hr
= get_connected(This
, &seek
);
404 hr
= IMediaSeeking_GetStopPosition(seek
, pStop
);
405 IMediaSeeking_Release(seek
);
412 static HRESULT WINAPI
MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking
* iface
, LONGLONG
* pCurrent
)
414 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
417 TRACE("(%p/%p)->(%p)\n", iface
, This
, pCurrent
);
420 EnterCriticalSection(&This
->time_cs
);
422 *pCurrent
= This
->time_earliest
;
425 LeaveCriticalSection(&This
->time_cs
);
427 hr
= IMediaSeeking_ConvertTimeFormat(iface
, pCurrent
, NULL
, *pCurrent
, &TIME_FORMAT_MEDIA_TIME
);
430 hr
= get_connected(This
, &seek
);
432 hr
= IMediaSeeking_GetCurrentPosition(seek
, pCurrent
);
433 IMediaSeeking_Release(seek
);
440 static HRESULT WINAPI
MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking
* iface
, LONGLONG
* pTarget
, const GUID
* pTargetFormat
, LONGLONG Source
, const GUID
* pSourceFormat
)
442 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
445 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface
, This
, pTarget
, debugstr_guid(pTargetFormat
), (DWORD
)(Source
>>32), (DWORD
)Source
, debugstr_guid(pSourceFormat
));
446 hr
= get_connected(This
, &seek
);
448 hr
= IMediaSeeking_ConvertTimeFormat(seek
, pTarget
, pTargetFormat
, Source
, pSourceFormat
);
449 IMediaSeeking_Release(seek
);
456 static HRESULT WINAPI
MediaSeekingPassThru_SetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, DWORD dwCurrentFlags
, LONGLONG
* pStop
, DWORD dwStopFlags
)
458 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
461 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface
, This
, pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
462 hr
= get_connected(This
, &seek
);
464 hr
= IMediaSeeking_SetPositions(seek
, pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
465 IMediaSeeking_Release(seek
);
466 } else if (hr
== VFW_E_NOT_CONNECTED
)
471 static HRESULT WINAPI
MediaSeekingPassThru_GetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, LONGLONG
* pStop
)
473 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
476 TRACE("(%p/%p)->(%p, %p)\n", iface
, This
, pCurrent
, pStop
);
477 hr
= get_connected(This
, &seek
);
479 hr
= IMediaSeeking_GetPositions(seek
, pCurrent
, pStop
);
480 IMediaSeeking_Release(seek
);
487 static HRESULT WINAPI
MediaSeekingPassThru_GetAvailable(IMediaSeeking
* iface
, LONGLONG
* pEarliest
, LONGLONG
* pLatest
)
489 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
492 TRACE("(%p/%p)->(%p,%p)\n", iface
, This
, pEarliest
, pLatest
);
493 hr
= get_connected(This
, &seek
);
495 hr
= IMediaSeeking_GetAvailable(seek
, pEarliest
, pLatest
);
496 IMediaSeeking_Release(seek
);
503 static HRESULT WINAPI
MediaSeekingPassThru_SetRate(IMediaSeeking
* iface
, double dRate
)
505 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
508 TRACE("(%p/%p)->(%e)\n", iface
, This
, dRate
);
509 hr
= get_connected(This
, &seek
);
511 hr
= IMediaSeeking_SetRate(seek
, dRate
);
512 IMediaSeeking_Release(seek
);
519 static HRESULT WINAPI
MediaSeekingPassThru_GetRate(IMediaSeeking
* iface
, double * dRate
)
521 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
524 TRACE("(%p/%p)->(%p)\n", iface
, This
, dRate
);
525 hr
= get_connected(This
, &seek
);
527 hr
= IMediaSeeking_GetRate(seek
, dRate
);
528 IMediaSeeking_Release(seek
);
535 static HRESULT WINAPI
MediaSeekingPassThru_GetPreroll(IMediaSeeking
* iface
, LONGLONG
* pPreroll
)
537 ICOM_THIS_MULTI(PassThruImpl
, IMediaSeeking_vtbl
, iface
);
540 TRACE("(%p)\n", pPreroll
);
541 hr
= get_connected(This
, &seek
);
543 hr
= IMediaSeeking_GetPreroll(seek
, pPreroll
);
544 IMediaSeeking_Release(seek
);
551 void MediaSeekingPassThru_RegisterMediaTime(IUnknown
*iface
, REFERENCE_TIME start
) {
552 ICOM_THIS_MULTI(PassThruImpl
, IInner_vtbl
, iface
);
553 EnterCriticalSection(&This
->time_cs
);
554 This
->time_earliest
= start
;
556 LeaveCriticalSection(&This
->time_cs
);
559 void MediaSeekingPassThru_ResetMediaTime(IUnknown
*iface
) {
560 ICOM_THIS_MULTI(PassThruImpl
, IInner_vtbl
, iface
);
561 EnterCriticalSection(&This
->time_cs
);
563 LeaveCriticalSection(&This
->time_cs
);
566 void MediaSeekingPassThru_EOS(IUnknown
*iface
) {
567 ICOM_THIS_MULTI(PassThruImpl
, IInner_vtbl
, iface
);
570 hr
= IMediaSeeking_GetStopPosition((IMediaSeeking
*)&This
->IMediaSeeking_vtbl
, &time
);
571 EnterCriticalSection(&This
->time_cs
);
574 This
->time_earliest
= time
;
577 LeaveCriticalSection(&This
->time_cs
);
580 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl
=
582 MediaSeekingPassThru_QueryInterface
,
583 MediaSeekingPassThru_AddRef
,
584 MediaSeekingPassThru_Release
,
585 MediaSeekingPassThru_GetCapabilities
,
586 MediaSeekingPassThru_CheckCapabilities
,
587 MediaSeekingPassThru_IsFormatSupported
,
588 MediaSeekingPassThru_QueryPreferredFormat
,
589 MediaSeekingPassThru_GetTimeFormat
,
590 MediaSeekingPassThru_IsUsingTimeFormat
,
591 MediaSeekingPassThru_SetTimeFormat
,
592 MediaSeekingPassThru_GetDuration
,
593 MediaSeekingPassThru_GetStopPosition
,
594 MediaSeekingPassThru_GetCurrentPosition
,
595 MediaSeekingPassThru_ConvertTimeFormat
,
596 MediaSeekingPassThru_SetPositions
,
597 MediaSeekingPassThru_GetPositions
,
598 MediaSeekingPassThru_GetAvailable
,
599 MediaSeekingPassThru_SetRate
,
600 MediaSeekingPassThru_GetRate
,
601 MediaSeekingPassThru_GetPreroll