strmbase: Implement BaseFilter in strmbase.
[wine/multimedia.git] / dlls / quartz / control.c
blobb1485a440ab875e9cd23de6decc141d4529f38cc
1 /*
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"
25 #include "uuids.h"
26 #include "wine/debug.h"
28 #include <assert.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;
39 LONG ref;
40 IUnknown * pUnkOuter;
41 IPin * pin;
42 BOOL bUnkOuterValid;
43 BOOL bAggregatable;
44 BOOL renderer;
45 CRITICAL_SECTION time_cs;
46 BOOL timevalid;
47 REFERENCE_TIME time_earliest;
48 } PassThruImpl;
50 static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface,
51 REFIID riid,
52 LPVOID *ppvObj) {
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);
69 } else {
70 *ppvObj = NULL;
71 FIXME("unknown interface %s\n", debugstr_guid(riid));
72 return E_NOINTERFACE;
75 IUnknown_AddRef((IUnknown *)(*ppvObj));
76 return S_OK;
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);
85 return 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);
94 if (ref == 0)
96 This->time_cs.DebugInfo->Spare[0] = 0;
97 DeleteCriticalSection(&This->time_cs);
98 CoTaskMemFree(This);
100 return ref;
103 static const IUnknownVtbl IInner_VTable =
105 SeekInner_QueryInterface,
106 SeekInner_AddRef,
107 SeekInner_Release
110 /* Generic functions for aggregation */
111 static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv)
113 if (This->bAggregatable)
114 This->bUnkOuterValid = TRUE;
116 if (This->pUnkOuter)
118 if (This->bAggregatable)
119 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
121 if (IsEqualIID(riid, &IID_IUnknown))
123 HRESULT hr;
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;
129 return hr;
132 *ppv = NULL;
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);
186 if (This->pin)
187 FIXME("Re-initializing?\n");
189 This->renderer = renderer;
190 This->pin = pin;
192 return S_OK;
195 static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl =
197 SeekingPassThru_QueryInterface,
198 SeekingPassThru_AddRef,
199 SeekingPassThru_Release,
200 SeekingPassThru_Init
203 HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj)
205 PassThruImpl *fimpl;
207 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
209 *ppObj = fimpl = CoTaskMemAlloc(sizeof(*fimpl));
210 if (!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;
219 fimpl->ref = 1;
220 fimpl->pin = NULL;
221 fimpl->timevalid = 0;
222 InitializeCriticalSection(&fimpl->time_cs);
223 fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs");
224 return S_OK;
227 HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeCurrent, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking, PCRITICAL_SECTION crit_sect)
229 assert(fnChangeStop && fnChangeCurrent && fnChangeRate);
231 pSeeking->refCount = 1;
232 pSeeking->pUserData = pUserData;
233 pSeeking->fnChangeRate = fnChangeRate;
234 pSeeking->fnChangeStop = fnChangeStop;
235 pSeeking->fnChangeCurrent = fnChangeCurrent;
236 pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards |
237 AM_SEEKING_CanSeekBackwards |
238 AM_SEEKING_CanSeekAbsolute |
239 AM_SEEKING_CanGetStopPos |
240 AM_SEEKING_CanGetDuration;
241 pSeeking->llCurrent = 0;
242 pSeeking->llStop = ((ULONGLONG)0x80000000) << 32;
243 pSeeking->llDuration = pSeeking->llStop;
244 pSeeking->dRate = 1.0;
245 pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME;
246 pSeeking->crst = crit_sect;
247 return S_OK;
250 HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
252 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
254 TRACE("(%p)\n", pCapabilities);
256 *pCapabilities = This->dwCapabilities;
258 return S_OK;
261 HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
263 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
264 HRESULT hr;
265 DWORD dwCommonCaps;
267 TRACE("(%p)\n", pCapabilities);
269 if (!pCapabilities)
270 return E_POINTER;
272 dwCommonCaps = *pCapabilities & This->dwCapabilities;
274 if (!dwCommonCaps)
275 hr = E_FAIL;
276 else
277 hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE;
278 *pCapabilities = dwCommonCaps;
279 return hr;
282 HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
284 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
286 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
289 HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
291 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
293 *pFormat = TIME_FORMAT_MEDIA_TIME;
294 return S_OK;
297 HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
299 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
300 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
302 EnterCriticalSection(This->crst);
303 *pFormat = This->timeformat;
304 LeaveCriticalSection(This->crst);
306 return S_OK;
309 HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
311 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
312 HRESULT hr = S_OK;
314 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
316 EnterCriticalSection(This->crst);
317 if (!IsEqualIID(pFormat, &This->timeformat))
318 hr = S_FALSE;
319 LeaveCriticalSection(This->crst);
321 return hr;
324 HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
326 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
327 TRACE("%p %s\n", This, qzdebugstr_guid(pFormat));
328 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : E_INVALIDARG);
332 HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
334 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
336 TRACE("(%p)\n", pDuration);
338 EnterCriticalSection(This->crst);
339 *pDuration = This->llDuration;
340 LeaveCriticalSection(This->crst);
342 return S_OK;
345 HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
347 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
349 TRACE("(%p)\n", pStop);
351 EnterCriticalSection(This->crst);
352 *pStop = This->llStop;
353 LeaveCriticalSection(This->crst);
355 return S_OK;
358 /* FIXME: Make use of the info the filter should expose */
359 HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
361 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
363 TRACE("(%p)\n", pCurrent);
365 EnterCriticalSection(This->crst);
366 *pCurrent = This->llCurrent;
367 LeaveCriticalSection(This->crst);
369 return S_OK;
372 HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
374 if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
376 *pTarget = Source;
377 return S_OK;
379 /* FIXME: clear pTarget? */
380 return E_INVALIDARG;
383 static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
385 switch (dwFlags & AM_SEEKING_PositioningBitsMask)
387 case AM_SEEKING_NoPositioning:
388 return value;
389 case AM_SEEKING_AbsolutePositioning:
390 return *pModifier;
391 case AM_SEEKING_RelativePositioning:
392 case AM_SEEKING_IncrementalPositioning:
393 return value + *pModifier;
394 default:
395 assert(FALSE);
396 return 0;
400 HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
402 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
403 BOOL bChangeCurrent = FALSE, bChangeStop = FALSE;
404 LONGLONG llNewCurrent, llNewStop;
406 TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
407 EnterCriticalSection(This->crst);
409 llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags);
410 llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
412 if (pCurrent)
413 bChangeCurrent = TRUE;
414 if (llNewStop != This->llStop)
415 bChangeStop = TRUE;
417 TRACE("Old: %u, New: %u\n", (DWORD)(This->llCurrent/10000000), (DWORD)(llNewCurrent/10000000));
419 This->llCurrent = llNewCurrent;
420 This->llStop = llNewStop;
422 if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime))
423 *pCurrent = llNewCurrent;
424 if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime))
425 *pStop = llNewStop;
426 LeaveCriticalSection(This->crst);
428 if (bChangeCurrent)
429 This->fnChangeCurrent(This->pUserData);
430 if (bChangeStop)
431 This->fnChangeStop(This->pUserData);
433 return S_OK;
436 HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
438 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
440 TRACE("(%p, %p)\n", pCurrent, pStop);
442 EnterCriticalSection(This->crst);
443 IMediaSeeking_GetCurrentPosition(iface, pCurrent);
444 IMediaSeeking_GetStopPosition(iface, pStop);
445 LeaveCriticalSection(This->crst);
447 return S_OK;
450 HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
452 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
454 TRACE("(%p, %p)\n", pEarliest, pLatest);
456 EnterCriticalSection(This->crst);
457 *pEarliest = 0;
458 *pLatest = This->llDuration;
459 LeaveCriticalSection(This->crst);
461 return S_OK;
464 HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
466 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
467 BOOL bChangeRate = (dRate != This->dRate);
468 HRESULT hr = S_OK;
470 TRACE("(%e)\n", dRate);
472 if (dRate > 100 || dRate < .001)
474 FIXME("Excessive rate %e, ignoring\n", dRate);
475 return VFW_E_UNSUPPORTED_AUDIO;
478 EnterCriticalSection(This->crst);
479 This->dRate = dRate;
480 if (bChangeRate)
481 hr = This->fnChangeRate(This->pUserData);
482 LeaveCriticalSection(This->crst);
484 return hr;
487 HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
489 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
491 TRACE("(%p)\n", dRate);
493 EnterCriticalSection(This->crst);
494 /* Forward? */
495 *dRate = This->dRate;
496 LeaveCriticalSection(This->crst);
498 return S_OK;
501 HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
503 TRACE("(%p)\n", pPreroll);
505 *pPreroll = 0;
506 return S_OK;
509 static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj)
511 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
513 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
515 return SeekOuter_QueryInterface(This, riid, ppvObj);
518 static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface)
520 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
522 TRACE("(%p/%p)->()\n", iface, This);
524 return SeekOuter_AddRef(This);
527 static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface)
529 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
531 TRACE("(%p/%p)->()\n", iface, This);
533 return SeekOuter_Release(This);
536 static HRESULT get_connected(PassThruImpl *This, IMediaSeeking **seek) {
537 HRESULT hr;
538 IPin *pin;
539 *seek = NULL;
540 hr = IPin_ConnectedTo(This->pin, &pin);
541 if (FAILED(hr))
542 return VFW_E_NOT_CONNECTED;
543 hr = IPin_QueryInterface(pin, &IID_IMediaSeeking, (void**)seek);
544 IPin_Release(pin);
545 if (FAILED(hr))
546 hr = E_NOTIMPL;
547 return hr;
550 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
552 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
553 IMediaSeeking *seek;
554 HRESULT hr;
555 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
556 hr = get_connected(This, &seek);
557 if (SUCCEEDED(hr)) {
558 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
559 IMediaSeeking_Release(seek);
561 else
562 return E_NOTIMPL;
563 return hr;
566 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
568 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
569 IMediaSeeking *seek;
570 HRESULT hr;
571 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
572 hr = get_connected(This, &seek);
573 if (SUCCEEDED(hr)) {
574 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
575 IMediaSeeking_Release(seek);
577 else
578 return E_NOTIMPL;
579 return hr;
582 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
584 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
585 IMediaSeeking *seek;
586 HRESULT hr;
587 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
588 hr = get_connected(This, &seek);
589 if (SUCCEEDED(hr)) {
590 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
591 IMediaSeeking_Release(seek);
593 else
594 return E_NOTIMPL;
595 return hr;
598 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
600 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
601 IMediaSeeking *seek;
602 HRESULT hr;
603 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
604 hr = get_connected(This, &seek);
605 if (SUCCEEDED(hr)) {
606 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
607 IMediaSeeking_Release(seek);
609 else
610 return E_NOTIMPL;
611 return hr;
614 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
616 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
617 IMediaSeeking *seek;
618 HRESULT hr;
619 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
620 hr = get_connected(This, &seek);
621 if (SUCCEEDED(hr)) {
622 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
623 IMediaSeeking_Release(seek);
625 else
626 return E_NOTIMPL;
627 return hr;
630 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
632 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
633 IMediaSeeking *seek;
634 HRESULT hr;
635 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
636 hr = get_connected(This, &seek);
637 if (SUCCEEDED(hr)) {
638 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
639 IMediaSeeking_Release(seek);
641 else
642 return E_NOTIMPL;
643 return hr;
646 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
648 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
649 IMediaSeeking *seek;
650 HRESULT hr;
651 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
652 hr = get_connected(This, &seek);
653 if (SUCCEEDED(hr)) {
654 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
655 IMediaSeeking_Release(seek);
657 else
658 return E_NOTIMPL;
659 return hr;
662 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
664 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
665 IMediaSeeking *seek;
666 HRESULT hr;
667 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
668 hr = get_connected(This, &seek);
669 if (SUCCEEDED(hr)) {
670 hr = IMediaSeeking_GetDuration(seek, pDuration);
671 IMediaSeeking_Release(seek);
673 else
674 return E_NOTIMPL;
675 return hr;
678 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
680 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
681 IMediaSeeking *seek;
682 HRESULT hr;
683 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
684 hr = get_connected(This, &seek);
685 if (SUCCEEDED(hr)) {
686 hr = IMediaSeeking_GetStopPosition(seek, pStop);
687 IMediaSeeking_Release(seek);
689 else
690 return E_NOTIMPL;
691 return hr;
694 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
696 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
697 IMediaSeeking *seek;
698 HRESULT hr = S_OK;
699 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
700 if (!pCurrent)
701 return E_POINTER;
702 EnterCriticalSection(&This->time_cs);
703 if (This->timevalid)
704 *pCurrent = This->time_earliest;
705 else
706 hr = E_FAIL;
707 LeaveCriticalSection(&This->time_cs);
708 if (SUCCEEDED(hr)) {
709 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
710 return hr;
712 hr = get_connected(This, &seek);
713 if (SUCCEEDED(hr)) {
714 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
715 IMediaSeeking_Release(seek);
717 else
718 return E_NOTIMPL;
719 return hr;
722 static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
724 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
725 IMediaSeeking *seek;
726 HRESULT hr;
727 TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat));
728 hr = get_connected(This, &seek);
729 if (SUCCEEDED(hr)) {
730 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
731 IMediaSeeking_Release(seek);
733 else
734 return E_NOTIMPL;
735 return hr;
738 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
740 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
741 IMediaSeeking *seek;
742 HRESULT hr;
743 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
744 hr = get_connected(This, &seek);
745 if (SUCCEEDED(hr)) {
746 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
747 IMediaSeeking_Release(seek);
748 } else if (hr == VFW_E_NOT_CONNECTED)
749 hr = S_OK;
750 return hr;
753 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
755 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
756 IMediaSeeking *seek;
757 HRESULT hr;
758 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
759 hr = get_connected(This, &seek);
760 if (SUCCEEDED(hr)) {
761 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
762 IMediaSeeking_Release(seek);
764 else
765 return E_NOTIMPL;
766 return hr;
769 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
771 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
772 IMediaSeeking *seek;
773 HRESULT hr;
774 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
775 hr = get_connected(This, &seek);
776 if (SUCCEEDED(hr)) {
777 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
778 IMediaSeeking_Release(seek);
780 else
781 return E_NOTIMPL;
782 return hr;
785 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
787 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
788 IMediaSeeking *seek;
789 HRESULT hr;
790 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
791 hr = get_connected(This, &seek);
792 if (SUCCEEDED(hr)) {
793 hr = IMediaSeeking_SetRate(seek, dRate);
794 IMediaSeeking_Release(seek);
796 else
797 return E_NOTIMPL;
798 return hr;
801 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
803 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
804 IMediaSeeking *seek;
805 HRESULT hr;
806 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
807 hr = get_connected(This, &seek);
808 if (SUCCEEDED(hr)) {
809 hr = IMediaSeeking_GetRate(seek, dRate);
810 IMediaSeeking_Release(seek);
812 else
813 return E_NOTIMPL;
814 return hr;
817 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
819 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
820 IMediaSeeking *seek;
821 HRESULT hr;
822 TRACE("(%p)\n", pPreroll);
823 hr = get_connected(This, &seek);
824 if (SUCCEEDED(hr)) {
825 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
826 IMediaSeeking_Release(seek);
828 else
829 return E_NOTIMPL;
830 return hr;
833 void MediaSeekingPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) {
834 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
835 EnterCriticalSection(&This->time_cs);
836 This->time_earliest = start;
837 This->timevalid = 1;
838 LeaveCriticalSection(&This->time_cs);
841 void MediaSeekingPassThru_ResetMediaTime(IUnknown *iface) {
842 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
843 EnterCriticalSection(&This->time_cs);
844 This->timevalid = 0;
845 LeaveCriticalSection(&This->time_cs);
848 void MediaSeekingPassThru_EOS(IUnknown *iface) {
849 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
850 REFERENCE_TIME time;
851 HRESULT hr;
852 hr = IMediaSeeking_GetStopPosition((IMediaSeeking*)&This->IMediaSeeking_vtbl, &time);
853 EnterCriticalSection(&This->time_cs);
854 if (SUCCEEDED(hr)) {
855 This->timevalid = 1;
856 This->time_earliest = time;
857 } else
858 This->timevalid = 0;
859 LeaveCriticalSection(&This->time_cs);
862 static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl =
864 MediaSeekingPassThru_QueryInterface,
865 MediaSeekingPassThru_AddRef,
866 MediaSeekingPassThru_Release,
867 MediaSeekingPassThru_GetCapabilities,
868 MediaSeekingPassThru_CheckCapabilities,
869 MediaSeekingPassThru_IsFormatSupported,
870 MediaSeekingPassThru_QueryPreferredFormat,
871 MediaSeekingPassThru_GetTimeFormat,
872 MediaSeekingPassThru_IsUsingTimeFormat,
873 MediaSeekingPassThru_SetTimeFormat,
874 MediaSeekingPassThru_GetDuration,
875 MediaSeekingPassThru_GetStopPosition,
876 MediaSeekingPassThru_GetCurrentPosition,
877 MediaSeekingPassThru_ConvertTimeFormat,
878 MediaSeekingPassThru_SetPositions,
879 MediaSeekingPassThru_GetPositions,
880 MediaSeekingPassThru_GetAvailable,
881 MediaSeekingPassThru_SetRate,
882 MediaSeekingPassThru_GetRate,
883 MediaSeekingPassThru_GetPreroll