wer: Add new stubbed wer.dll.
[wine/hramrach.git] / dlls / quartz / control.c
blob84e7dd7814ea16ca05136a72bd9057f1b3275596
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 typedef HRESULT (*SeekFunc)( IMediaSeeking *to, LPVOID arg );
229 static HRESULT ForwardCmdSeek( PCRITICAL_SECTION crit_sect, IBaseFilter* from, SeekFunc fnSeek, LPVOID arg )
231 HRESULT hr = S_OK;
232 HRESULT hr_return = S_OK;
233 IEnumPins *enumpins = NULL;
234 BOOL foundend = FALSE, allnotimpl = TRUE;
236 hr = IBaseFilter_EnumPins( from, &enumpins );
237 if (FAILED(hr))
238 goto out;
240 hr = IEnumPins_Reset( enumpins );
241 while (hr == S_OK) {
242 IPin *pin = NULL;
243 hr = IEnumPins_Next( enumpins, 1, &pin, NULL );
244 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
246 hr = IEnumPins_Reset( enumpins );
247 continue;
249 if (pin)
251 PIN_DIRECTION dir;
253 IPin_QueryDirection( pin, &dir );
254 if (dir == PINDIR_INPUT)
256 IPin *connected = NULL;
258 IPin_ConnectedTo( pin, &connected );
259 if (connected)
261 HRESULT hr_local;
262 IMediaSeeking *seek = NULL;
264 hr_local = IPin_QueryInterface( connected, &IID_IMediaSeeking, (void**)&seek );
265 if (hr_local == S_OK)
267 foundend = TRUE;
268 if (crit_sect)
270 LeaveCriticalSection( crit_sect );
271 hr_local = fnSeek( seek , arg );
272 EnterCriticalSection( crit_sect );
274 else
275 hr_local = fnSeek( seek , arg );
277 if (hr_local != E_NOTIMPL)
278 allnotimpl = FALSE;
280 hr_return = updatehres( hr_return, hr_local );
281 IMediaSeeking_Release( seek );
283 IPin_Release(connected);
286 IPin_Release( pin );
289 IEnumPins_Release( enumpins );
291 if (foundend && allnotimpl)
292 hr = E_NOTIMPL;
293 else
294 hr = hr_return;
296 out:
297 TRACE("Returning: %08x\n", hr);
298 return 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;
323 return S_OK;
326 struct pos_args {
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)
340 DWORD *caps = 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;
354 HRESULT hr;
356 hr = IMediaSeeking_GetDuration(iface, &mydur);
357 if (FAILED(hr))
358 return hr;
360 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
361 *duration = mydur;
362 return hr;
365 static HRESULT fwd_getstopposition(IMediaSeeking *iface, LPVOID pdur)
367 LONGLONG *duration = pdur;
368 LONGLONG mydur = *duration;
369 HRESULT hr;
371 hr = IMediaSeeking_GetStopPosition(iface, &mydur);
372 if (FAILED(hr))
373 return hr;
375 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
376 *duration = mydur;
377 return hr;
380 static HRESULT fwd_getcurposition(IMediaSeeking *iface, LPVOID pdur)
382 LONGLONG *duration = pdur;
383 LONGLONG mydur = *duration;
384 HRESULT hr;
386 hr = IMediaSeeking_GetCurrentPosition(iface, &mydur);
387 if (FAILED(hr))
388 return hr;
390 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
391 *duration = mydur;
392 return hr;
395 static HRESULT fwd_setrate(IMediaSeeking *iface, LPVOID prate)
397 double *rate = prate;
399 HRESULT hr;
401 hr = IMediaSeeking_SetRate(iface, *rate);
402 if (FAILED(hr))
403 return hr;
405 return hr;
409 HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
411 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
413 TRACE("(%p)\n", pCapabilities);
415 *pCapabilities = This->dwCapabilities;
417 return S_OK;
420 HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
422 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
423 HRESULT hr;
424 DWORD dwCommonCaps;
426 TRACE("(%p)\n", pCapabilities);
428 if (!pCapabilities)
429 return E_POINTER;
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)
435 return hr;
437 dwCommonCaps = *pCapabilities & This->dwCapabilities;
439 if (!dwCommonCaps)
440 hr = E_FAIL;
441 else
442 hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE;
443 *pCapabilities = dwCommonCaps;
445 return hr;
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;
460 return S_OK;
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);
472 return S_OK;
475 HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
477 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
478 HRESULT hr = S_OK;
480 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
482 EnterCriticalSection(This->crst);
483 if (!IsEqualIID(pFormat, &This->timeformat))
484 hr = S_FALSE;
485 LeaveCriticalSection(This->crst);
487 return hr;
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);
515 return S_OK;
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);
529 return S_OK;
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);
544 return S_OK;
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))
551 *pTarget = Source;
552 return S_OK;
554 /* FIXME: clear pTarget? */
555 return E_INVALIDARG;
558 static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
560 switch (dwFlags & AM_SEEKING_PositioningBitsMask)
562 case AM_SEEKING_NoPositioning:
563 return value;
564 case AM_SEEKING_AbsolutePositioning:
565 return *pModifier;
566 case AM_SEEKING_RelativePositioning:
567 case AM_SEEKING_IncrementalPositioning:
568 return value + *pModifier;
569 default:
570 assert(FALSE);
571 return 0;
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;
585 args.stop = pStop;
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);
594 if (pCurrent)
595 bChangeCurrent = TRUE;
596 if (llNewStop != This->llStop)
597 bChangeStop = TRUE;
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))
607 *pStop = llNewStop;
609 ForwardCmdSeek(This->crst, This->pUserData, fwd_setposition, &args);
610 LeaveCriticalSection(This->crst);
612 if (bChangeCurrent)
613 This->fnChangeCurrent(This->pUserData);
614 if (bChangeStop)
615 This->fnChangeStop(This->pUserData);
617 return S_OK;
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);
631 return S_OK;
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);
641 *pEarliest = 0;
642 *pLatest = This->llDuration;
643 LeaveCriticalSection(This->crst);
645 return S_OK;
648 HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
650 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
651 BOOL bChangeRate = (dRate != This->dRate);
652 HRESULT hr = S_OK;
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);
663 This->dRate = dRate;
664 if (bChangeRate)
665 hr = This->fnChangeRate(This->pUserData);
666 ForwardCmdSeek(This->crst, This->pUserData, fwd_setrate, &dRate);
667 LeaveCriticalSection(This->crst);
669 return hr;
672 HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
674 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
676 TRACE("(%p)\n", dRate);
678 EnterCriticalSection(This->crst);
679 /* Forward? */
680 *dRate = This->dRate;
681 LeaveCriticalSection(This->crst);
683 return S_OK;
686 HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
688 TRACE("(%p)\n", pPreroll);
690 *pPreroll = 0;
691 return S_OK;
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) {
722 HRESULT hr;
723 IPin *pin;
724 *seek = NULL;
725 hr = IPin_ConnectedTo(This->pin, &pin);
726 if (FAILED(hr))
727 return hr;
728 hr = IPin_QueryInterface(pin, &IID_IMediaSeeking, (void**)seek);
729 IPin_Release(pin);
730 if (FAILED(hr))
731 hr = E_NOTIMPL;
732 return hr;
735 static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
737 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
738 IMediaSeeking *seek;
739 HRESULT hr;
740 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
741 hr = get_connected(This, &seek);
742 if (SUCCEEDED(hr)) {
743 hr = IMediaSeeking_GetCapabilities(seek, pCapabilities);
744 IMediaSeeking_Release(seek);
746 return hr;
749 static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
751 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
752 IMediaSeeking *seek;
753 HRESULT hr;
754 TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities);
755 hr = get_connected(This, &seek);
756 if (SUCCEEDED(hr)) {
757 hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities);
758 IMediaSeeking_Release(seek);
760 return hr;
763 static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
765 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
766 IMediaSeeking *seek;
767 HRESULT hr;
768 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
769 hr = get_connected(This, &seek);
770 if (SUCCEEDED(hr)) {
771 hr = IMediaSeeking_IsFormatSupported(seek, pFormat);
772 IMediaSeeking_Release(seek);
774 return hr;
777 static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
779 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
780 IMediaSeeking *seek;
781 HRESULT hr;
782 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
783 hr = get_connected(This, &seek);
784 if (SUCCEEDED(hr)) {
785 hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat);
786 IMediaSeeking_Release(seek);
788 return hr;
791 static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
793 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
794 IMediaSeeking *seek;
795 HRESULT hr;
796 TRACE("(%p/%p)->(%p)\n", iface, This, pFormat);
797 hr = get_connected(This, &seek);
798 if (SUCCEEDED(hr)) {
799 hr = IMediaSeeking_GetTimeFormat(seek, pFormat);
800 IMediaSeeking_Release(seek);
802 return hr;
805 static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
807 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
808 IMediaSeeking *seek;
809 HRESULT hr;
810 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
811 hr = get_connected(This, &seek);
812 if (SUCCEEDED(hr)) {
813 hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat);
814 IMediaSeeking_Release(seek);
816 return hr;
819 static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
821 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
822 IMediaSeeking *seek;
823 HRESULT hr;
824 TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat));
825 hr = get_connected(This, &seek);
826 if (SUCCEEDED(hr)) {
827 hr = IMediaSeeking_SetTimeFormat(seek, pFormat);
828 IMediaSeeking_Release(seek);
830 return hr;
833 static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
835 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
836 IMediaSeeking *seek;
837 HRESULT hr;
838 TRACE("(%p/%p)->(%p)\n", iface, This, pDuration);
839 hr = get_connected(This, &seek);
840 if (SUCCEEDED(hr)) {
841 hr = IMediaSeeking_GetDuration(seek, pDuration);
842 IMediaSeeking_Release(seek);
844 return hr;
847 static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
849 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
850 IMediaSeeking *seek;
851 HRESULT hr;
852 TRACE("(%p/%p)->(%p)\n", iface, This, pStop);
853 hr = get_connected(This, &seek);
854 if (SUCCEEDED(hr)) {
855 hr = IMediaSeeking_GetStopPosition(seek, pStop);
856 IMediaSeeking_Release(seek);
858 return hr;
861 static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
863 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
864 IMediaSeeking *seek;
865 HRESULT hr = S_OK;
866 TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent);
867 if (!pCurrent)
868 return E_POINTER;
869 EnterCriticalSection(&This->time_cs);
870 if (This->timevalid)
871 *pCurrent = This->time_earliest;
872 else
873 hr = E_FAIL;
874 LeaveCriticalSection(&This->time_cs);
875 if (SUCCEEDED(hr)) {
876 hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME);
877 return hr;
879 hr = get_connected(This, &seek);
880 if (SUCCEEDED(hr)) {
881 hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent);
882 IMediaSeeking_Release(seek);
884 return hr;
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);
890 IMediaSeeking *seek;
891 HRESULT hr;
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);
894 if (SUCCEEDED(hr)) {
895 hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat);
896 IMediaSeeking_Release(seek);
898 return hr;
901 static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
903 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
904 IMediaSeeking *seek;
905 HRESULT hr;
906 TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
907 hr = get_connected(This, &seek);
908 if (SUCCEEDED(hr)) {
909 hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
910 IMediaSeeking_Release(seek);
912 return hr;
915 static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
917 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
918 IMediaSeeking *seek;
919 HRESULT hr;
920 TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop);
921 hr = get_connected(This, &seek);
922 if (SUCCEEDED(hr)) {
923 hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop);
924 IMediaSeeking_Release(seek);
926 return hr;
929 static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
931 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
932 IMediaSeeking *seek;
933 HRESULT hr;
934 TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest);
935 hr = get_connected(This, &seek);
936 if (SUCCEEDED(hr)) {
937 hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest);
938 IMediaSeeking_Release(seek);
940 return hr;
943 static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate)
945 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
946 IMediaSeeking *seek;
947 HRESULT hr;
948 TRACE("(%p/%p)->(%e)\n", iface, This, dRate);
949 hr = get_connected(This, &seek);
950 if (SUCCEEDED(hr)) {
951 hr = IMediaSeeking_SetRate(seek, dRate);
952 IMediaSeeking_Release(seek);
954 return hr;
957 static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate)
959 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
960 IMediaSeeking *seek;
961 HRESULT hr;
962 TRACE("(%p/%p)->(%p)\n", iface, This, dRate);
963 hr = get_connected(This, &seek);
964 if (SUCCEEDED(hr)) {
965 hr = IMediaSeeking_GetRate(seek, dRate);
966 IMediaSeeking_Release(seek);
968 return hr;
971 static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
973 ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface);
974 IMediaSeeking *seek;
975 HRESULT hr;
976 TRACE("(%p)\n", pPreroll);
977 hr = get_connected(This, &seek);
978 if (SUCCEEDED(hr)) {
979 hr = IMediaSeeking_GetPreroll(seek, pPreroll);
980 IMediaSeeking_Release(seek);
982 return hr;
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;
989 This->timevalid = 1;
990 LeaveCriticalSection(&This->time_cs);
993 void MediaSeekingPassThru_ResetMediaTime(IUnknown *iface) {
994 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
995 EnterCriticalSection(&This->time_cs);
996 This->timevalid = 0;
997 LeaveCriticalSection(&This->time_cs);
1000 void MediaSeekingPassThru_EOS(IUnknown *iface) {
1001 ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface);
1002 REFERENCE_TIME time;
1003 HRESULT hr;
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;
1009 } else
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