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